19

我正在从 K&R 的“ The C Programming Language ”一书中学习 C。我正在做书中指定的练习。我在练习 1.16,但我不明白。

练习 1.16:

修改最长行程序的主程序,使其正确打印任意长输入行的长度,并尽可能多地打印文本。

我的问题:

  1. “......尽可能多的文本......” - 字符串长度是否有一些限制?也许在标准标题中有一个具有最大允许字符串长度值的变量?

  2. “......任意长输入行的长度......” - 但在代码中 MAXLINE 定义为 1000。它的大小也有限。我在这里看到了一些解决方案,但在我看来,这不是解决方案决定,因为前者对行的长度有限制(1000 个字符)。

也许我不明白这个任务。我的理解是我必须取消 1000 个字符的限制。

4

6 回答 6

26

这是 K&R 中的一个相当早的练习,您只应该对代码进行一些小的更改,而不是对代码进行全面的重新设计。

  1. “……尽可能多的文字……”

    由你来解释。我会通过打印longest缓冲区中存储的内容来做到这一点。即打印出最多 1000 个字符的行。同样,这是一个早期练习,还很少介绍动态分配的内存。在编写 K&R 时,存储任意长的文本行并不像今天那样可行。

  2. “......任意长的输入行的长度......”

    是硬性要求。无论长度有多长,您都应该找到正确的长度(至少在 . 的范围内int

解决此问题的一种方法是:

  • 调用 getline() 后,检查读入line缓冲区的最后一个字符是否为换行符('\n')
  • 如果是,您阅读了完整的一行。该len变量是行的正确长度(getline() 的返回值,与原始代码相比无需特殊考虑。
  • 如果不是,则说明您没有阅读整行,需要寻找这一行的结尾。您添加一个 while 循环,调用 getchar() 直到它返回一个换行符(或 EOF),然后计算您在该循环中读取的字符数。只是做len++数。
  • 当 while 循环完成时,newlen现在是行的实际长度,但我们的缓冲区只有它的前 999 个字符。
  • line和以前一样,如果该行是迄今为止最长的,则存储(copy() 函数调用)当前缓冲区(最多 1000 个字符)。
  • 完成后,像以前一样打印出存储的行(longest缓冲区)和max长度变量。
    • 由于上面提到的 while 循环,max长度现在是正确的。
    • 如果该longest行确实超过 1000 个字符。您至少打印出前 999 个字符 - 这是“尽可能多”。

我不会剧透并发布完成此任务所需的代码,但您只需将 6 行代码添加到练习 1-16 的最长行程序中即可。

于 2013-02-27T18:57:29.710 回答
2
  1. 在现代机器上,“尽可能多的文本”可能是所有的文本,这要归功于自动换行的终端程序。那本书是在电传终端还在使用时写的。除了您正在使用的机器的内存限制之外,字符串长度没有限制。

  2. 他们希望您添加某种循环来读取字符并查找换行符,而不是假设读取到已MAXLINE调整大小的缓冲区肯定会包含换行符。

于 2013-02-27T18:46:40.300 回答
1

这是我的版本:

int getline(char s[],int lim)
{
    int c,i;
    for(i=0;i<lim-1&&(c=getchar())!=EOF&&c!='\n';++i)
        s[i]=c;
    if(c=='\n')
    {
        s[i]=c;
        ++i;
    }
    if(c!=EOF)
    {
        while((c=getchar())!=EOF&&c!='\n')
            i++;
    }
    s[i]='\0';
    return i;
}
    #define MAXLINE 1000
    int len;
    int max;
    char line[MAXLINE];
    char longest[MAXLINE];

    max=0;
    while((len=getline(line,MAXLINE))>1)
    {
        if(len>max)
        {
            max=len;
            copy(longest,line);
        }
    }
    if(max>0)
    {
        printf("%d:%s",max,longest);
    }
    return 0;

由于一些未知的原因,示例代码在我的电脑上特别不起作用,当条件为'len>0'时,循环不会结束我认为主要原因是当你什么都不输入时,但你仍然必须按回车,所以接收为'\n',len为1;我认为它满足了打印任意长输入行的长度以及尽可能多的文本的要求。 它像这样工作

于 2019-02-13T11:28:58.180 回答
0


    #include

    main()
    {
       long tlength = 0;
       short input, llength = 1;
       while (llength > 0)  {
          llength = 0;
          while ((input = getchar()) != EOF) {
              ++llength;
              if (input == '\n')
              break;
          }
          tlength = tlength + llength;
          printf("\nLength of just above line : %5d\n\n", llength);
       }
       printf("\n\tLength of entire text : %8ld\n", tlength);
       return 0;
    }

据我说,这个问题只需要任意行的长度+最后是整个文本的长度。

尝试运行此代码并根据问题告诉我它是否正确,因为我对这个问题也感到困惑。

于 2019-05-15T08:56:11.687 回答
0

我想提出这个练习实际上更有意义,如果想象你可以复制的字符数的限制非常小——比如 100 个字符——并且你的程序应该在比这更长的行之间进行判断限制。

(如果您实际上将限制更改为非常小,则代码变得更容易测试:如果它挑选出达到该小限制的第一行,您就会知道您的代码没有工作,而如果它返回第一行但是-最长行的许多字符,它正在工作。)

保留复制和计算字符的代码部分,直到它遇到换行符或 EOF 或行大小限制。添加代码,在此计数和复制停止的地方拾取,并且即使在复制停止后仍会继续计数,只要 getchar() 仍然没有返回 EOF 或换行符。

于 2020-11-07T01:31:40.183 回答
0

我的解决方案:就在对 getLine 的调用下方

if ( line[len-1] != '\n' && line[len-1] != EOF) //if end of line or file wasnt found after max length
{
    int c;
    while ( ( c = getchar() ) != '\n' && c != EOF ) 
        len++; //keep counting length until end of line or file is found
}

为了测试它,将 MAXLINE 更改为 25

于 2021-01-15T12:18:01.287 回答