gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 01:03:57 25 4
gpt4 key购买 nike

我正在阅读 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] = '\0';
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]) != '\0')
++i;
}

getline 函数有问题。如果输入行的第 lim-1 个字符不是换行符,则 getline 将在 lim- 处插入 '\0'第 1 个位置,第 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] = '\0';
return i;
}

我的 getline 版本是否正确?

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

最佳答案

由于这个问题仍然没有关闭也没有转移到另一个站点......我会在这里回答。

关于允许在 C 缓冲区中写入的位置(在什么索引处)的部分已在 related question 中得到解答。 , 但我看到必须在这里重复一遍:你只能在从 0 到 lim-1 的索引处写入,包括在内。不允许您写入 lim索引,在行为未定义的意义上;在实践中会发生什么取决于你发生了什么overflow到内存中。 (您可能还想看看 https://security.stackexchange.com/questions/53878/how-to-explain-buffer-overflow-to-a-layman ;尽管从技术上讲它不正确,但那里的最佳答案应该会给您正确的直觉,为什么溢出是一个问题。)

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

K&R 的版本更加微妙,因为如果 i==lim-1在循环结束时,然后是 c 不能'\n' , 所以他们的 if (c == '\n') { s[i] = c; ++i; }在这种情况下 block 不执行,所以 i不递增等于 lim , 这使得最后一个赋值 s[i]安全的!换句话说,忽略(为了更容易理解)关于 EOF 的部分。 , 一个 postcondition对于 for循环是(i==lim-1 && c!='\n' )||(i<lim-1 && c=='\n') .要了解为什么会这样,您需要了解 short-circuit behavior&& :当i==lim-1 , c 的旧值将通过不执行(短路)来保持 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')。)

关于c - 理解读取一组文本行并打印K&R书中最长的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28534101/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com