/* 这个程序从标准输入中读取输入行并在标准输出中打印这些输出行, 每个输出行的后面一行是该行内容的一部分 输入的第一行是一串列标号,串的最后以一个负数结尾 这些列标号成对出现,说明需要被打印的输入行的列范围 例如,0 3 10 13 -1 表示第0列到第3列,第10列到第13列的内容将被打印 */ /* 下面这5行称为预处理指令,是由预处理器(preprocessor)解释的, 预处理器读入源码,根据预处理指令对其进行修改,然后把修改过的源码交给编译器 */ #include <stdio.h> /* 访问标准I/O库中的函数 */ #include <stdlib.h> /* 定义了EXIT_SUCCESS 和 EXIT_FAILURE符号 */ #include <string.h> /* 提供操作字符串的函数 */ #define MAX_COLS 20 #define MAX_INPUT 1000 /* 下面两行声明被称为函数原型(function prototype) */ int read_column_numbers(int columns[], int max); /* 函数原型中参数的名字并非必须也就是说也可以写成 (int[], int) */ /* const表示 函数将不会修改函数调用者所传递的这两个参数 */ void rearrange(char *output, char const *input, int n_columns, int const columns[]); /* C程序必须要有一个main方法,是程序执行的起点 */ int main(void) { int n_columns; int columns[MAX_COLS]; char input[MAX_INPUT]; char output[MAX_INPUT]; n_columns = read_column_numbers(columns, MAX_COLS); 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; } /* C语言中数组是按照引用传递,就是地址调用,而常量,变量等是按值传递的。在函数中对变量的任何修改都会在函数返回时丢失 C语言中所有传递给函数的参数都是按值传递的 */ int read_column_numbers(int columns[], int max) { int num = 0; int ch; /* scanf 每次调用时,都从标准输入读取一个十进制整数,如果转换失败(输入字符无法转换为整数),返回0. 转换成功,就将值存在columns[num]中 */ while(num < max && scanf("%d", &columns[num]) == 1 && columns[num] >= 0) num +=1; /* %是整除的余,不是整除的结果,如果num是偶数,那么num%2应该等于0 */ if(num%2 !=0){ puts("Last column number is not paired"); exit(EXIT_FAILURE); } /* EOF用于提示文件的结尾 这个while的循环体中没有任何语句,仅仅完成while表达式的测试部分就足已达到我们的目的,赋值语句在循环的条件部分 */ while( (ch = getchar()) != EOF && ch != '\n') ; return num; } /* 处理输入行,将指定的字符连接在一起,输出行以NUL结尾 const关键字有两个作用:1.声明该函数中这个参数是不可修改的,2.会使编译器去验证是否违背该意图 */ void rearrange( char *output, char const *input, int n_columns, int const columns[]){ int col; int output_col; int len; len = strlen(input); output_col = 0; /* for循环的每个部分都是可选的。第一部分是初始部分,只在循环开始前执行一次,第二个是测试部分,第三是调整部分 */ for(col = 0; col<n_columns; col += 2){ int nchars = columns[col+1]-columns[col]+1; if(columns[col]>=len || output_col == MAX_INPUT-1) break; if(output_col + nchars > MAX_INPUT - 1){ nchars = MAX_INPUT - output_col - 1; } /* strncpy函数把选中的字符从输入行复制到输出行中可用的下一个位置 strncpy函数的前两个参数分别是目标字符串和源字符串地址,第三个参数指定需要复制的字符数 在该调用中,目标字符串的位置是输出数组的起始地址向后偏移output_col列的地址 源字符串的位置则是输入数组起始地址向后偏移columns[col]个位置的地址 */ strncpy(output+output_col, input+columns[col], nchars); output_col+=nchars; } output[output_col] = '\0'; } /* 函数库里有很多操作字符串的函数。除非特别的说明,这些函数的参数既可以使字符串常量,也可以使字符型数组名,还可以使一个指向字符的指针 strcpy接受两个参数,第二个字符串参数将被复制到第一个字符串参数,第一个字符串原有的字符将被覆盖 strcat函数也接受两个参数,把第二个字符串参数添加到第一个字符串参数的末尾。这两个函数中第一个字符串参数不能是字符串常量 可这两个函数需要确保目标字符串有足够的空间,函数本身不会对其做检查 strchr第一个参数是字符串,第二个是一个字符,在字符串内搜索字符参数第一次出现的位置,搜索成功就返回指向这个位置的指针,失败返回NULL指针 strstr类似,只不过搜索的是字符串 */
自己学习,不喜勿喷