理解读取一组文本行并打印K&R书中最长的程序

Understanding the program that reads a set of text lines and prints the longest in K &R's book

我正在阅读 K &R 的书,第 1.9 节。从给定的一组行中打印最长行的程序给出为

#include <stdio.h>
#define MAXLINE 1000                   /* maximum input line length */

int getline(char line[], int maxline);
void copy(char to[], char from[]);

/* print the longest input line */

main()
{
   int len;                               /* current line length */
   int max;                               /* maximum length seen so far */
   char line[MAXLINE];                    /* current input line */
   char longest[MAXLINE];                 /* longest line saved here */
   max = 0;
   while ((len = getline(line, MAXLINE)) > 0)
      if (len > max) {
         max = len;
         copy(longest, line);
      }
   if (max > 0) /* there was a line */
      printf("%s", longest);
   return 0;
}

/* getline: read a line into s, return length */

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;
   }
   s[i] = '[=10=]';
   return i;
}

/* copy: copy 'from' into 'to'; assume to is big enough */

void copy(char to[], char from[])
{
   int i;
   i = 0;
   while ((to[i] = from[i]) != '[=10=]')
      ++i;
}

getline 函数有问题。如果输入行的第 lim-1 个字符不是换行符,则 getline 将在第 lim-1 处插入 '[=15=]',而第 lim 处未使用(或空的)。

我通过将 getline 修改为

来移除此限制
int getline(char s[], int lim)
{
   int c, i;
   for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
      s[i] = c;
   s[i] = c;
   s[i+1] = '[=11=]';
   return i;
}

我的 getline 版本正确吗?

如果是,哪个版本在 运行 时间最快,需要最少的内存,使用最少的内存?

由于这个问题还没有关闭也没有转移到其他站点...我会在这里回答。

关于允许在 C 缓冲区中写入的位置(在什么索引处)的部分已在 related question, but I see have to repeat it here: you're only allowed to write at indices from 0 to lim-1, inclusively. You are not allowed to write to the lim index, in the sense that the behavior is undefined; what will happen in practice depends on whatever you happen to overflow to in memory. (You may also want to look at https://security.stackexchange.com/questions/53878/how-to-explain-buffer-overflow-to-a-layman 中得到回答;尽管它在技术上不正确,但那里的最佳答案应该给你正确的直觉,为什么溢出是一个问题。)

在这个问题的 getline 的任一版本中,for 循环可以在 i==lim-1 时退出。在您的 getline 版本(您问题中的那个 lower/later )中,您然后无条件地写入 s[i+1],这意味着您写入 s[lim],这是缓冲区溢出(又名缓冲区溢出)。

K&R 的版本有点微妙,因为如果 i==lim-1 在循环结束时,那么 c 不能 '\n',所以他们的 if (c == '\n') { s[i] = c; ++i; } 块在这种情况下不会执行,所以 i 不会递增等于 lim,这使得最后一个赋值 s[i] 安全!换句话说,忽略(为了更容易理解)关于 EOF 的部分,&&postcondition for the for loop is that (i==lim-1 && c!='\n' )||(i<lim-1 && c=='\n'). To see why this is the case, you need to understand the short-circuit behavior:当 i==lim-1 时,[ 的旧值=19=]将通过不执行(短路)c=getchar()来保持;此外,先前获得的 c 保证不会是 \n,因为在相反的情况下,for 循环会提前一次退出循环,即当 i<lim-1 时。 (for 循环的完整后置条件,不忽略 EOF(i==lim-1 && c!='\n' && c!=EOF)||(i<lim-1 && c==EOF)||(i<lim-1 && c=='\n')。)

// Program to print the length and content of the longest line in a text sep by new lines

#include <stdio.h>
char strcop(char *curr, char *bigg);
main()
{
    int cur=0, big=0,d, count=0;
    char curr[100], bigg[100];


    while((d=getchar())!=EOF)
    {
// Read the line till a new line is encountered
    if (d!= '\n')
    {
        curr[count] = d;
        count++;
        cur++;
    }

// compare with the big line after a new line is encountered and store the new big line
    else
    {   // comparing the length of lines
        if(cur>big)
        {
            big = cur;
            strcop(curr, bigg);
        }
        cur = count = 0;

    }


    }

for (int k =0 ; k<big; k++)
{
printf("%c", bigg[k]);
}
printf("\n");
//for (int k =0 ; k<big; k++)
//{
//printf("%c", curr[k]);
//}
//printf("count %d", count);
//printf("big %d", big);
//printf("cur %d", cur);
}

char strcop(char *curr, char *bigg)
{
    while(*curr)
    {
        *(bigg++) = *(curr++);
    }
}