我买了一本名为“C(ANSI C)编程语言”的C书,试图自学,好C.无论如何,这本书包含了很多章节后面的例子和实践,这很好。< / p>
无论如何,下面的代码是我对“计算最长行类型的程序”一书的答案,作者在函数getLine(char s[], int lim)
中使用了for循环。这允许在line
函数内正确显示字符串main()
。然而,使用while不会起作用 - 出于对我来说未知的原因,也许有人可能会根据我的错误来了解情况。
编辑:总结以上内容。 printf("%s\n", line);
不会显示任何内容。
感谢任何帮助。
#include <stdio.h>
#define MAXLINE 1024
getLine(char s[], int lim) {
int c, i = 0;
while((c = getchar()) != EOF && c != '\n' && i < lim) {
s[++i] = c;
}
if(c == '\n' && i != 0) {
s[++i] = c;
s[++i] = '\0';
}
return i;
}
main(void) {
int max = 0, len;
char line[MAXLINE], longest[MAXLINE];
while((len = getLine(line,MAXLINE)) > 0) {
if(len > max) {
max = len;
printf("%s\n", line);
}
}
return 0;
}
答案 0 :(得分:1)
你有很多严重的错误。这是我找到的以及如何修复它们。
将您的代码更改为postincrement i以避免第一个数组成员未初始化,并避免双重打印最终字符:
s[++i] = c;
...
s[++i] = c;
s[++i] = '\0';
到
s[i++] = c;
...
// s[++i] = c; see below
...
s[i++] = '\0';
并修复您的EOF错误:
if(c == '\n' && i != 0) {
s[++i] = c;
s[++i] = '\0';
}
到
if(c == '\n')
{
s[i++] = '\n';
}
s[i] = '\0'
在编写处理字符串,数组或其他矢量类型结构的程序时,检查程序的逻辑非常重要。您应该手动执行此操作,并通过它运行一些示例案例,为您的程序提供示例输入并思考会发生什么。
您需要经历的案例是:
在这种情况下,您的边缘案例是:
第一个字符是'x',第二个字符是'\ n',第三个字符是EOF
一行等于lim字符
第一个字符是'x',第二个字符是'\ n',第三个字符是EOF
getLine(line[MAXLINE],MAXLINE])
(s := line[MAXLINE] = '!!!!!!!!!!!!!!!!!!!!!!!!...'
c := undef, i := 0
while(...)
c := 'x'
i := 1
s[1] := 'x' => s == '!x!!!!...' <- first bug found
while(...)
c := '\n'
end of while(...)
if (...)
(c== '\n' (T) && i != 0 (T)) = T
i := i + 1 = 2
s[2] = '\n' => s == '!x\n!!!!'
i := i + 1 = 3
s[3] = '\0' => s == '!x\n\0!!!' <- good, it's terminated
return i = 3
(len = i = 3) > 0) = T (the while eval)
if (...)
len (i = 3) > max = F
max = 3 <- does this make sense? is '!x\n' a line 3 chars long? perhaps. why did we keep the '\n' character? this is likely to be another bug.
printf("%s\n", line) <- oh, we are adding ANOTHER \n character? it was definitely a bug.
outputs "!x\n\n\0" <- oh, I expected it to print "x\n". we know why it didn't.
while(...)
getLine(...)
(s := line[MAXLINE] = '!x\n\0!!!!!!!!!!!!!!!!!!!...' ; <- oh, that's fun.
c := undef, i := 0
while(...)
c := EOF
while terminates without executing body
(c == '\n' && i != 0) = F
if body not executed
return i = 0
(len = i = 0 > 0) = F
while terminates
program stops.
所以你看到这个简单的过程,可以在你的头脑中或(最好)在纸上完成,可以在几分钟内告诉你程序是否有效。
通过完成其他边缘情况和一些一般情况,您将发现程序中的其他问题。
答案 1 :(得分:0)
从您的问题中确切地说,您使用getLine确实遇到了什么问题(编译错误?运行时错误?),但是您的实现中存在一些错误。而不是
s[++i] = something;
您应该使用后缀运算符:
s[i++] = something;
不同之处在于第一个版本在索引(i + 1)处存储'某事',但第二个版本将在i的索引处存储某些内容。在C / C ++中,数组从0开始索引,所以你需要确保它在第一次通过while循环时在s [0]中存储字符,在第二次传递时存储在s [1]中,依此类推。使用您发布的代码,永远不会分配s [0],这将导致printf()打印出未初始化的数据。
以下getline实现对我有用:
int getLine(char s[], int lim) {
int c;
int i;
i = 0;
while((c = getchar()) != EOF && c != '\n' && i < lim) {
s[i++] = c;
}
if(c == '\n' && i != 0) {
s[i++] = c;
s[i++] = '\0';
}
return i;
}
答案 2 :(得分:0)
通过执行++ i而不是i ++,你没有在getLine()中为s [0]赋值!
另外,在循环结束时指定'\ 0'时,你是不必要的增量,你应该总是指定BTW,所以从条件中取出它。
答案 3 :(得分:0)
还要向函数添加返回类型(int main和int getLine)
答案 4 :(得分:0)
注意溢出 - 你最后分配给s [i],限制为i == lim,因此你可能会分配给[MAXLINE]。这将是 - 等待它 - 堆栈溢出,是的。