最近C语言已经学完,布置的大做业:学生管理系统5个版本也完成了。可是又买了一本《C和指针》,主要是感受本身的指针仍是没有彻底熟悉。因此仍是要好好研究一下。闲话很少说,直接第一章。一看是快速入门,觉得很简单,但那个程序就把我卡了半天才看懂,按照做者说的的确运用了C语言中的大部分技巧。数组
程序1.1:首先读取一串列标号,这些列标号成对出现,即是输入行的列范围。这串列标号以一个负值结尾,做为结束标志。剩余的输入行被程序读入并打印,而后输入行中被选中范围的字符串被提取出来打印。函数
书中代码以下:学习
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_CLOS 20 /*所能处理的最大列号*/ #define MAX_INPUT 1000 /*每一个数入行的最大长度*/ int read_column_numbers(int columns[],int max); void rearrange(char *output,char const*input,int n_columns,int const columns[MAX_CLOS]); int main(void) { int n_columns; /*进行处理的列标号*/ int columns[MAX_CLOS]; /*须要处理的列数*/ char input[MAX_INPUT]; /*须要容纳的输入的数组*/ char output[MAX_INPUT]; /*容纳输出行的数组*/ n_columns=read_column_numbers(columns,MAX_CLOS); while(gets(input)!=NULL) /*若是读入不存在输入行则程序结束*/ { printf("Original input :%s\n",input); rearrange(output,input,n_columns,columns); printf("Rearranged line :%s\n",output); } return EXIT_SUCCESS; } /*读取须要处理的列标号,若是超出规定范围不予理会*/ int read_column_numbers(int columns[],int max) { int num=0; int ch; while(num<max&&scanf("%d",&columns[num])==1&&columns[num]>0) { /*这个循环条件保证了读取的行号不会超过最大值,并且利用&&的短路特性, 也不会即便超过最大行号也不会被scanf读入,同时scanf保证了读入整型数据, 同时后面的条件输入的为正数*/ num+=1; } /*判断是否读入的数据是成对的*/ if(num%2) { puts("Last column number is not paired."); exit(EXIT_FAILURE); } while((ch=getchar())!=EOF&&ch!='\n'); /*用来处理包含最后那个负值的全部字符*/ return num; } /*处理输入行*/ void rearrange(char *output,char const*input,int n_columns,int const columns[MAX_CLOS]) { int col; /*columns数组的下标*/ int output_col; /*输出行的列计数器*/ int len; /*输入行的长度*/ int nchars; /*成对处理的列之间的长度*/ len=strlen(input); output_col=0; for(col=0;col<n_columns;col+=2) { if(columns[col]>=len||output_col==MAX_INPUT-1) /*若是输入行的标号小于须要处理的列标号或者 输出数组已满结束任务*/ break; nchars=columns[col+1]-columns[col]+1; if(output_col+nchars>MAX_INPUT-1); nchars=MAX_INPUT-output_col-1; /*若是输出行数据空间不够则只处理到能容纳到的数据*/ strncpy(output+output_col,input+columns[col],nchars); output_col+=nchars; } output[output_col]='\0'; }
一点点思考:不得不说,Kenneth这种大师思惟的确很完善,要是我写的确不少地方都想不到(我怎么敢和大师比2333!),好比while(ch=getchar())那个语句,一开始我百思不得其解,后来才明白为的是清除负值以后的字符(包括负值自己)由于这些字符虽然没有被读走,同时也仍然在stdin中存在。因此在主函数调用gets这个函数进行读取的时候这些未被读走的字符就会被解释为第一行数据进而使咱们得不到本身想要的结果。 而他对于可能形成数组越界访问的状况也进行了处理。想一想本身在写的时候历来没有在意过这些,都是越界了才会debug找出来。另一个细节就是他传入rearrange这个函数的input数组,加了前缀const,防止函数内可能形成的改动。这点也是我须要学习的。spa
不过我也对于他的主函数设置的while条件有一些异议,gets函数在读到文件尾(EOF)才会获得NULL,这种的确适合咱们打开一个文件进行读取的操做,由于这个文件的末尾必定会有EOF。可是若是咱们在键盘输入的时候,咱们只有CtrlZ才能够获得EOF,这点总让我感受很不爽,其实主要是我懒不想摁CtrlZ,另外是我在书上并非很理解它的输入样例(你们能够去看一下),里面没有CtrlZ,因此,我并非很懂做者的意思。但貌似没有其余更好的方法了。就暂且认为是须要输入CtrlZ。在这个问题上纠结这么久,我也是醉了。debug
这个程序的确很经典,包含的东西多但不难,其实你们能够按照示例试一下输出,而后就会获得很好玩的结果了。感受本身学了一学期C,仍是什么都不会,本身打的时候打不下去,而后看了书的程序也是看了半天。。。多是由于最近在看Java致使的吧。不能一天放松啊。。。指针