K&R练习1.16 - 行长度的限制

21

我正在学习K&R的《C程序设计语言》这本书中的C编程。我正在做书中指定的练习。我现在在第1.16题,但是我不理解它。

练习1.16:

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

我的问题:

  1. "…尽可能多地打印文本…" - 字符串长度有什么限制吗?也许在标准头文件中有一个变量,表示字符串长度的最大允许值?

  2. "…任意长度的输入行的长度…" - 但是在代码中MAXLINE被定义为1000。这也是一个有限的大小。我在这里看到了一些解决方案here,但我认为这不是一个解决方案,因为在前面有一条限制行长度的限制(1000个字符)。

也许我没有理解任务。我的理解是我必须取消1000个字符的限制。

1
我现在没有带我的K&R,所以实际上无法检查最长行程序的要求。但是请记住,您可以读取、打印和计算单个字符,无需将它们保存在字符串中。 - pmg
@pmg 根据任务文本,我必须打印最大行的文本。 - Andrey Bushman
好吧...如果你必须打印最长的行,你得把它保存在某个地方。我的建议对这个练习来说不太好,抱歉。 - pmg
你不必一次性保存所有内容。 - Carl Norum
6个回答

29

这是K&R中的一个早期练习,你只需要对代码进行一些小的修改,而不是对代码进行全面的重新设计。

  1. "...尽可能多地输出文本..."

    由你来解释。我会通过打印存储在longest缓冲区中的内容来完成。即打印出长达1000个字符的行。再次强调,这是一个早期练习,还没有介绍动态分配内存的知识。在K&R编写的时候,存储任意长度的文本行并不像今天这样可行。

  2. "...任意长的输入行的长度..."

    是一个硬性要求。你需要找到正确的长度,无论它有多长(至少在int范围内)。

解决这个问题的一种方法是:

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

我不会泄露代码,告诉你如何实现这个功能,但你只需要在1-16练习中最长的程序中添加6行代码即可。


谢谢。我会尝试将其翻译成俄语,并在明天编写代码。现在是晚上,我想睡觉了。感谢大家! - Andrey Bushman

2
  1. 在现代机器上,“尽可能多的文本”很可能是所有文本,这要归功于自动换行的终端程序。那本书是在电传打字机终端仍在使用时编写的。除了可能是机器内存限制之外,没有对字符串长度的限制。

  2. 他们希望你添加一些循环来读取字符并查找换行符,而不是假设读入MAXLINE大小的缓冲区一定包含一个换行符。


我记得在某个地方读到过 Linux 上文本文件每行的字符限制是 4096 个。现在是否支持超出这个限制了?从何时开始支持? - जलजनक
自动换行终端程序 - 它是什么? - Andrey Bushman
1
@DoSparKot,试试吧 - 我相信你会发现没有这样的限制。我从未听说过这样的事情。 - Carl Norum
1
@Bush - 一个终端程序,当文本到达窗口右侧时自动换行。就像在文字处理器中的自动换行一样。 - Carl Norum
1
啊..原来是fgets()LINE_MAX限制。 - जलजनक

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',长度为1;我认为它满足任意长输入行的长度要求,并尽可能地输出文本。它是这样工作的


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


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;
    }

根据我的理解,这个问题只需要求出每条任意线的长度以及最后整个文本的长度。

尝试运行这段代码并告诉我它是否符合问题要求,因为我对这个问题也感到困惑。


0

我想提供一个想法,如果你将可复制字符的数量限制得非常小,比如说100个字符,并且你的程序应该判断哪些行的长度超过了这个限制,那么这个练习实际上会更有意义。

(如果你真的把限制改得非常小,代码就变得更容易测试:如果它挑出了第一行达到这个小限制的字符,你就知道你的代码不起作用了,而如果它返回最长行的前几个字符,它就是有效的。)

保留代码的部分来复制和计算字符,直到遇到换行符、EOF或行大小限制。添加代码,它会在计数和复制结束后继续计数,只要getchar()还没有返回EOF或换行符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接