use*_*782 1 c coding-style kernighan-and-ritchie
我正在阅读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;
}
Run Code Online (Sandbox Code Playgroud)
功能有问题getline.如果lim-1输入行的第一个字符不是一个新行,则getline将插入'\0'在lim-1第地方离开lim第地方未使用(或空).
我通过修改getlineas 删除了这个限制,
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;
}
Run Code Online (Sandbox Code Playgroud)
我的版本是getline正确的吗?
如果是这样,哪个版本在运行时最快,需要最少的内存,并使用最少的内存?
由于这个问题仍然没有关闭也没有移到另一个网站......我会在这里回答.
关于允许在C缓冲区中写入的位置(在哪些索引处)的部分已在相关问题中得到回答,但我看到必须在此重复:您只能在0到lim-1包含的索引处写入.lim在行为未定义的意义上,不允许您写入索引; 在实践中会发生什么取决于你在内存中溢出的任何事情.(您可能还需要查看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; }块不会在这种情况下执行,所以i不增加等于lim,这使得最后分配s[i]安全!换句话说,忽略(为使这个更容易掌握的缘故)有关的部分EOF,一个后置条件的for循环是(i==lim-1 && c!='\n' )||(i<lim-1 && c=='\n').要知道为什么是这样的话,你需要了解的短路行为的&&:时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').)
| 归档时间: |
|
| 查看次数: |
881 次 |
| 最近记录: |