【问题标题】:K&R Exercise 1.16 - Limitation on line lengthK&R 练习 1.16 - 行长限制
【发布时间】:2013-02-13 17:06:03
【问题描述】:

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

练习 1.16:

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

我的问题:

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

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

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

【问题讨论】:

  • 我现在没有 K&R,所以我无法真正检查最长线路程序的要求。但请记住,您可以读取、打印和计算单个字符,而无需将它们保存在字符串中。
  • @pmg 但是根据任务的文本,我也必须打印最大行文本。
  • 嗯......如果你必须打印最长的行,你必须把它保存在某个地方。我的建议对练习没有好处,抱歉。
  • 不过,您不必一次保存所有内容。

标签: c kernighan-and-ritchie c89


【解决方案1】:

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

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

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

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

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

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

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

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

【讨论】:

  • 谢谢。我会试着把它翻译成俄语,明天再写代码。现在是晚上,我想睡觉。谢谢大家!
【解决方案2】:
  1. 在现代机器上,“尽可能多的文本”可能是所有文本,这要归功于自动换行终端程序。那本书是在电传终端还在使用的时候写的。除了您正在使用的机器的内存限制之外,字符串长度没有限制。

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

【讨论】:

  • 我记得在某个地方读到过4096 Linux 上文本文件中每行的字符数限制。现在还支持吗?从什么时候开始?
  • automatically line-wrapping terminal programs - 这是什么?
  • @DoSparKot,试试看 - 我相信你会看到没有这样的限制。我从来没有听说过这样的事情。
  • @Bush - 一个终端程序,当文本到达窗口右侧时,它会将文本换行到下一行。就像文字处理器中的换行一样。
  • 啊.. 这是fgets()LINE_MAX 限制。
【解决方案3】:

这是我的版本:

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; 我认为它满足了打印任意长输入行的长度以及尽可能多的文本的要求。 And it works like this

【讨论】:

    【解决方案4】:
    
    
        #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;
        }
    
    

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

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

    【讨论】:

      【解决方案5】:

      我想提供的是,如果想象您可以复制的字符数的限制非常小(例如 100 个字符)并且您的程序应该在以下行之间进行判断,那么这个练习实际上会更有意义超过这个限制。

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

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

      【讨论】:

        【解决方案6】:

        我的解决方案:就在对 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-06-25
          • 2015-01-14
          • 1970-01-01
          • 1970-01-01
          • 2011-11-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多