新手C阵列问题的功能

时间:2010-01-26 17:23:36

标签: c arrays function

我买了一本名为“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;
}

5 个答案:

答案 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'

理论

在编写处理字符串,数组或其他矢量类型结构的程序时,检查程序的逻辑非常重要。您应该手动执行此操作,并通过它运行一些示例案例,为您的程序提供示例输入并思考会发生什么。

您需要经历的案例是:

  • 几个一般情况
  • 所有边缘情况

在这种情况下,您的边缘案例是:

  • 第一个角色是EOF
  • 第一个字符是'x',第二个字符是EOF
  • 第一个字符是'\ n',第二个字符是EOF
  • 第一个字符是'x',第二个字符是'\ n',第三个字符是EOF

  • 一行等于lim字符

  • 一行有一个少于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]。这将是 - 等待它 - 堆栈溢出,是的。