代码之家  ›  专栏  ›  技术社区  ›  alex

这个小C程序是否满足K&R练习?

  •  5
  • alex  · 技术社区  · 15 年前

    我正在进行K&R的练习1-18

    这就是我到目前为止想到的

    #include <stdio.h>
    
    #define MAXLINE 1000
    
    int getline(char line[], int maxline);
    void copy(char to[], char from[]);
    
    int main () {
    
        int len;
        char line[MAXLINE];
    
        while (getline(line, MAXLINE) > 0) {
                printf("%s", line);
        }
        return 0;
    }
    
    
    int getline(char s[], int lim) {
        int c, i, lastNonBlankIndex;
        lastNonBlankIndex = 0;
    
        for (i=0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
    
            if (c != ' ' && c != '\t') {
                lastNonBlankIndex = i + 1;
    
            } 
    
            s[i] = c;
        }
    
        if (i != lastNonBlankIndex) {
            i = lastNonBlankIndex;
            c = '\n';
        }
    
        if (c == '\n') {
            s[i] = c;   
            ++i;
        }
        s[i] = '\0';
        return i;
    }
    

    第二部分听起来很难,因为我不确定如果行只有空格或制表符,我应该返回什么。毕竟,如果我返回0,它将停止 getline() 打电话。我应该在这里建立一个 #define ,例如 ALL_BLANKS

    不管怎样,对于实际的主要问题,这是从行中删除尾随空格和制表符的正确方法吗?我做了一些输入 去工作。但是,如果我复制并粘贴带有换行符的文本到CL中,它看起来是串在一起的。当我在CL中输入一行并按回车键时,它会自动打印出来。我是否应该建立一个行数组,然后在完成后循环并打印它们?

    5 回复  |  直到 10 年前
        1
  •  5
  •   schot    15 年前

    您的代码看起来是正确的,但我认为如果您将读取行的操作与 stdin 以及剥离尾随空白行(解耦)。然后你可以使用未修改的 getline 从书本(代码重用)中删除,并且在返回0时不会有停止的问题。

    如果您对其他解决方案感兴趣,clcwiki有一个几乎完整的 K&R2 solutions .

    #include <stdio.h>
    #define MAXLINE 1024
    
    int getline(char s[], int lim);
    
    main()
    {
        int i, len;
        char line[MAXLINE];
    
        while ((len = getline(line, MAXLINE)) > 0) {
            i = len - 2;
            while (i >= 0 && (line[i] == ' ' || line[i] == '\t'))
                --i;
            if (i >= 0) {
                line[i+1] = '\n';
                line[i+2] = '\0';
                printf("%s", line);
            }
        }
        return 0;
    }
    

    这是我不久前写的第1类解决方案。 getline公司 如本书第28页所示。最好将删除空白放在一个单独的函数中 rstrip ,但我把它作为练习留给读者。

        2
  •  0
  •   Gilles 'SO- stop being evil'    15 年前

    你的基本设计是健全的。最好是像您所做的那样,在构建完剥离行之后立即打印它,这样您的程序一次只需要在内存中保留一行,而不需要保留整个文件。

    您的代码有一个小问题:它没有实现问题的第二部分(完全删除空行)。那是因为你总是钉钉子 '\n'

        3
  •  0
  •   nategoose    15 年前

    getline 如果出现错误或达到EOF,则应返回-1(通常为负值)。然后您的循环条件可以检查它是否返回了一些内容 >= 0 并且仍然允许0长度的线。

    for (i=0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
    

    int i = 0;
    
    while (i < lim) {
       c = getchar();
       if (c == EOF || c == '\n') {
           break;
       }
       line[i] = (char)c;
       i++;
    }
    line[i] = '\0'; // Null terminate the string
    

    这段代码应该为您读入一行。我会将行的读入和尾部空白的删除分开。您可以很容易地从字符串的末尾向后操作,以删除以null结尾的行的位置处的空格,因为在读入该行之后,您现在知道了它的长度。从本质上说,你把绳子长起来,然后在它长完之后再把它剪下来。

        4
  •  0
  •   Feyyaz    10 年前

    我就是这样做的。

    #include <stdio.h>
    #define MAXLINE 1000
    
    #define IN 1
    #define OUT 0
    
    int state = OUT;
    
    int getline(char s[], int lim);
    void copy(char to[], char from[]);
    
    int main(void)
    {
    int lenght;
    int max = 0;
    char line[MAXLINE];
    char longest[MAXLINE];
    
    while ((lenght = getline(line, MAXLINE)) > 0)
        if (lenght > max)
        {
            max = lenght;
            copy(longest, line);
        }
    if (max > 0)
        printf("\n%s\n", longest);
    
        return 0;
    
        }
       int getline(char s[], int lim)
       {
       int i, c;
       for (i = 0; i < lim - 1 && ((c = getchar()) != EOF) && (c != '\n'); i++)
       {
    
    
        if (state == IN && c != ' ' && c != '\t')
        {
            s[i] = ' ';
            i++;
            state = OUT;
        }
        if (s[0] == ' ')
        {
            s[0] = '\b';
        }
    
    
        s[i] = c;
    
    
        if (c == ' ' || c == '\t')
        {
            i--;
            state = IN;
        }
    }
    if (c == '\n')
    {
        s[i] = c;
        i++;
    }
    s[i] = '\0';
    
    return i;
     }
    
    void copy(char to[], char from[])
    {
    int i = 0;
    while ((to[i] = from[i]) != '\0')
        i++;
    }
    
        5
  •  -1
  •   user411313    15 年前
    #include <stdio.h>
    
    #define MAXLINE 1000
    
    size_t getline(char *s,size_t lim)
    {
      if( fgets(s,lim,stdin) )
      {
        while( *s && strchr(" \t\n",s[strlen(s)-1]) )
          s[strlen(s)-1]=0;
        return strlen(s);
      }
      return 0;
    }
    
    main()
    {
        int len;
        char line[MAXLINE];
    
        while (getline(line,sizeof line)) {
                printf("%s", line);
        }
        return 0;
    }