MyEyes

Logging my life

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
/*
    这个程序从标准输入中读取输入行并在标准输出中打印这些输出行,
    每个输出行的后面一行是该行内容的一部分

    输入的第一行是一串列标号,串的最后以一个负数结尾
    这些列标号成对出现,说明需要被打印的输入行的列范围
    例如,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类似,只不过搜索的是字符串
*/

自己学习,不喜勿喷

posted on 2012-04-23 15:51  MyEyes  阅读(276)  评论(0编辑  收藏  举报