2017-06-14 284 views
-1

我正在使用Xcode 8学习C,编译器在执行while或for循环后不运行任何代码。这是一个错误?我该如何解决它?执行while或for循环后没有代码执行C

在下面printf("code executed after while-loop");提供的例子中从未执行

#include <stdio.h> 

int getTheLine(char string[]); 

int getTheLine(char string[]) { 

    char character; 
    int index; 
    index = 0; 

    while ((character = getchar()) >= EOF) { 

    string[index] = character; 
    ++index; 
    } 

    printf("code executed after while-loop"); 
    return index; 
} 

int main(int argc, const char * argv[]) { 

    char string[100]; 
    int length = getTheLine(string); 
    printf("length %d\n", length); 

    return 0; 
} 
+0

您可以开始向我们展示您的代码。 –

+2

编译器不应该运行任何代码。它应该将[*翻译单元*](https://en.wikipedia.org/wiki/Translation_unit_(programming))编译成目标文件,然后将其链接到可执行文件中。 IDE然后可以启动一个进程来运行可执行文件。 –

+1

更重要的是,请[阅读关于如何提出好问题](http://stackoverflow.com/help/how-to-ask)并学习如何创建[最小,完整和可验证示例](http ://stackoverflow.com/help/mcve)。 –

回答

2

getchar返回int不是char,和比较EOF应与!=操作者而不是操作者>=来完成。

... 
int character; // int instead of char 
int index; 
index = 0; 

while ((character = getchar()) != EOF) { // != instead of >= 
... 
+0

我最初编写了像你所建议的代码。同样的问题 –

+1

@CristianLăpuşan你的代码与我的修复应用程序在这里工作很好。你的输入是什么?你的平台是什么?请记住:在Linux上,EOF使用Ctrl + D完成,在Windows上使用Ctrl + Z完成。 –

+0

我正在使用Xcode,macOS Sierra。 –

2

这是>= EOF,这将让病情始终true。其原因是,getchar()“有效”的结果将是一个正整数,和一个“非有效”导致像文件结束-将EOF,其是负(参见getchar()):

EOF ... int类型和负值

因此的整数常量表达式,从getchar任何有效的结果将是>EOF,而结束文件的结果将是==EOF,使得>= EOF将总是匹配。

改为写!= EOF

此外,值得注意的是你不串终止字符'\0',使得在​​使用string像一个字符串(例如,将产生不确定的行为(崩溃或别的东西,可能不需要)终止您的字符串。 所以写至少:

while ((character = getchar()) != EOF) { 
    string[index] = character; 
    ++index; 
} 
string[index]='\0'; 

然后还有,你可以写出界,例如如果一个人在你的例子进入100多个字符,但检查这现在是超出了实际问题,这是对的问题。无限循环

+0

如果我提前退出函数,说我在循环后立即插入“if(character == 47){return index;}”,那么代码运行正常 –

+0

@CristianLăpuşan:我想你的意思是“内循环”,因为你的循环永远不会结束;所以“while循环后执行的代码”永远不会被打印,对吧? –

2

符号常数EOF整数常数,类型为int。它(通常)被定义为一个宏,如-1

的问题是,作为(32位)的值-1int具有值0xffffffff和作为(8位)char相同的值将是0xff。这两个值不相等。这反过来意味着你的循环条件将永不为假,导致无限循环。

解决此问题的方法是,所有读取字符的标准函数都将其作为int返回。这意味着您的变量character也需要具有该类型。

重要注意事项:如果普通char是有符号或无符号类型,这是一个编译器实现细节。如果它是有符号的,那么与int的比较将导致符号扩展char值在比较中被提升时。这意味着signed char与值0xff将扩展到int0xffffffff。这意味着如果char已签名,那么比较就会起作用。

这意味着您的编译有charunsigned char。所以推广到intunsigned char0xff将为0x000000ff


至于为什么-1变得0xffffffff是因为如何负数的计算机上通常表示,其中一种叫two's complement


您的代码中还有另外两个缺陷。

首先是因为循环是无限的,你会去方式string阵列的界限,导致未定义行为(以及可能的崩溃迟早)。解决方法是添加一个条件,以确保index永远不会达到100(在数组的特定情况下,应该真正作为参数传递)。

第二个问题是,如果你打算用string数组作为实际字符串,你需要终止它。 C中的字符串实际上被称为null 终止字符串。该终结符是字符'\0'(等于整数0),并且需要放在每个要传递给处理此类字符串的标准函数的字符串的末尾。拥有这个终结符意味着一个100字符数组只能有99个字符,以便能够匹配终结符。这对解决上述问题具有影响。至于如何添加终止符,只需在循环后执行string[index] = '\0';(如果index在当然范围内)。

+0

它不工作.. –

+1

@CristianLăpuşan* *什么*“不工作”?你是否将'character'的类型改为'int'?你在做别的事情吗?你是否尝试过在调试器中的代码?你试过在循环后面添加一个(尾随)换行符到你打印的字符串(因为输出到'stdout'是默认的行缓冲)? –

+0

Upvoted为你带来的所有细节。但只是为了理解:在((char)-1 ==(int)-1'中不会整体提升)确保'(char)-1'实际上是扩展的到'0xffffffff'? –