【发布时间】:2015-04-17 21:43:03
【问题描述】:
我有一个关于 K&R 示例的小问题(排序行示例,第 108 页)。
我不明白当我取消注释 readlines 中的行时看到的行为,这会删除使用 getline 读取输入时添加的换行符。
int main()
{
int nlines;
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
my_qsort(lineptr, 0, nlines-1);
writelines(lineptr, nlines);
return 0;
} else {
printf("error: input too big \n");
return 1;
}
}
int readlines(char *lineptr[], int maxlines)
{
int len, nlines;
char *p, line[MAXLEN];
nlines = 0;
while ((len = my_getline(line, MAXLEN)) > 0)
if (nlines >= maxlines || (p = alloc(len)) == NULL)
return -1;
else {
line[len-1] = '\0'; //delete newline.
my_strcpy(p, line);
lineptr[nlines++] = p;
}
return nlines;
}
void writelines(char *lineptr[], int nlines)
{
while (nlines-- > 0)
printf("%s\n", *lineptr++);
}
例如,如果我随后输入以下内容:
linje1
linje2
linje3
linje4
然后writelines会输出:
linje1
linje2
linje3
linje4
linje2
linje3
linje4
linje3
linje4
linje4
"and one last newline..."
从中我推断 lineptr[0] 指向所有行。 lineptr[1] 指向除第一行之外的所有内容 ... , lineptr[3] 仅指向“linje4”
我不明白我们如何通过将行存储为“linje1\n”而不是“linje1”来获得这种行为。
澄清:
在 writelines 中(当 lineptr 指向数组的开头时)
呼叫printf("%s", *lineptr) 如何打印所有行?
编辑 2:
啊,我明白了,但这是来自 K&R 的 getline 函数
int my_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;
}
而且我确信它总是会给我一个以 null 结尾的字符串,不管它是否以换行符结尾?
这是K&R的alloc:
#define ALLOCSIZE 10000
static char allocbuf[ALLOCSIZE]; // Storeage for alloc
static char *allocp = allocbuf; // Next free position
char *alloc(int n) // Return pointer to n characters
{
if (allocbuf + ALLOCSIZE - allocp >= n) { // it fits
allocp += n;
return allocp - n;
} else
return 0;
}
编辑 3: 感谢所有的cmets。但是整个程序的输入与 K&R 中的完全一样,并且运行良好(我已经将输出与 grep 进行了比较),因此所有外围功能都按预期工作(例如 my_strcpy 的工作方式与 strcpy 完全相同,并复制字符串直到并包括空终止符)。 alloc 函数只是一个指向 K&R 的 char 大数组的指针。
我还是不明白的是:
C 读入一些文本行,复制它,将行 i 存储在内存中的某处,并让lineptr[i] 指向该内存位置:
使用 my_getline 读取行,读取整行(包括换行符),然后以空字符终止字符串。
如果我跳过line[len-1] = '\0'; 步骤,readlines 然后将指向该行副本的指针存储在lineptr[i] 中。在记忆中,我认为字符串(for i=1)看起来像这样"linje1\n\0"
但正如@DanJAB 指出的那样,很可能缺少空字符,因此字符串存储为"linje1\n",因此当 writelines 打印时(通过 lineptr) 这一行,它会在内存中打印出这之后的所有内容,因为缺少空字符,而这恰好是其余的行。
但我无法理解的是为什么 line[len-1] = '\0'; 显然需要将字符串 (i=1) 存储为 "linje1\0",而 my_getline 总是返回一个以 null 结尾的字符串?
再次感谢,对于任何潜在的不明确之处,我们深表歉意。
最终编辑 整个问题在于 alloc(len) 没有为最终的空字符分配空间!谢谢你帮助我。
【问题讨论】:
-
也许空终止符丢失的问题在另一个函数中。也许
my_strcpy做得不对。 -
@DanJAB 不,如果我用库版本替换该函数,我会得到完全相同的结果。不过还是谢谢。
-
MAXLEN是什么类型/值? -
一种基本的调试技术是使用打印语句。例如,在行:
line[len-1] = '\0'; //delete newline.之后,您可以添加:printf("line: <<%s>>\n", line);以检查换行符是否已被删除。当然,如果没有换行符,您已经删除了其他最后一个字符,但这不应该是您的数据的问题。
标签: c