sla*_*axx 34 c kernighan-and-ritchie
我一直在研究一些关于C的书,试图得到我的C腿(海腿!得到它?!).我刚从K&R书中完成了练习1-9,其参考是"编写一个程序将其输入复制到其输出中,用一个空格替换一个或多个空格的每个字符串." 我对我的代码发生了什么问题,但是 -
#include <stdio.h>
//Copy input to output. Replace each string of multiple spaces with one single space
int main(int argc, char *argv[]){
int ch, lch; // Variables to hold the current and last characters, respectively
/* This loop should 'put' the current char, then store the current char in lc,
* loop back, 'get' a new char and check if current and previous chars are both spaces.
* If both are spaces, do nothing. Otherwise, 'put' the current char
*/
for(ch = getchar(); (ch = getchar()) != EOF; lch = ch){
if(ch == ' ' && lch == ' ')
;
else putchar(ch);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这主要是有效的,除了第一个字符输入.例如,如果第一行输入是
"This is a test"
Run Code Online (Sandbox Code Playgroud)
我的代码输出
"his is a test".
Run Code Online (Sandbox Code Playgroud)
在删除第一个字符输入后,程序始终如一地工作以满足练习的要求.
有人能让我知道我在循环中犯的错误导致了这个问题吗?欢迎任何其他建议.
Am_*_*ful 37
在for循环语句中,您遇到了错误.
for(ch = getchar(); (ch = getchar()) != EOF; lch = ch){...}
Run Code Online (Sandbox Code Playgroud)
在这里,你将第一个字符存储在ch中,然后再次通过再次读取字符输入来测试if(ch!= EOF).
ch=getchar()
从初始化声明中删除; 让它在第二部分.
for(;(ch = getchar()) != EOF; lch = ch){...}
Run Code Online (Sandbox Code Playgroud)
此外,您必须在运行之前初始化您的lch,因为在循环的第一次迭代中进行比较之前,lch将不会存储任何值.所以,我们lch=0
先做好初始化.
for(lch = 0; (ch = getchar()) != EOF; lch = ch){...}
Run Code Online (Sandbox Code Playgroud)
考虑在编译器中启用警告,它可能会检测并警告此问题,因此您可以修复它.
以上将解决您的问题.
(感谢Blue Moon和hyde帮助我修改答案.)
ale*_*o_o 16
在循环初始化中调用getchar两次:
for(ch = getchar(); (ch = getchar()) != EOF; lch = ch)
Run Code Online (Sandbox Code Playgroud)
相反,你应该在初始化中调用它一次(获取第一个char),然后在迭代结束时调用它(以获取下一个字符):
int ch, lch = 0; // avoid using uninitialized variable
for(ch = getchar(); ch != EOF; lch = ch)
{
if(ch == ' ' && lch == ' ')
;
else putchar(ch);
ch = getchar();
}
Run Code Online (Sandbox Code Playgroud)
UPD:感谢Blue Moon和shekhar suman用lch指出问题
das*_*ght 13
问题是你的循环的第一次迭代调用了getchar
两次 - 一次是在初始化ch
变量时,另一次是在检查ch
时EOF
.
删除ch = getchar()
将解决此问题:
for( lch = '?' ; (ch = getchar()) != EOF; lch = ch) {
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,您需要lch
使用除space之外的任何值进行初始化.
您getchar()
在循环开始之前调用一次,然后在for
条件中每次迭代调用一次.您检索的第一个字符因此被丢弃.
lch
在比较之前,您还需要在循环之前进行初始化.根据您在字符串的第一个字符是空格时要执行的操作:
' '
将通过"预匹配" 来修剪前导空间.您的循环标题变为(在第二种情况下):
for(lch = 'a' /*arbitrary*/; (ch = getchar()) != EOF; lch = ch)
Run Code Online (Sandbox Code Playgroud)
感谢shekar suman关于未初始化的单挑lch
.
改变这个循环
for(ch = getchar(); (ch = getchar()) != EOF; lch = ch){
if(ch == ' ' && lch == ' ')
;
else putchar(ch);
}
Run Code Online (Sandbox Code Playgroud)
以下方式
for( lch = EOF; ( ch = getchar() ) != EOF; lch = ch )
{
if ( ch != ' ' || lch != ' ' ) putchar( ch );
}
Run Code Online (Sandbox Code Playgroud)
否则在循环开始时你会读两次字符.
在我看来,作业还描述了另一项任务
"编写一个程序将其输入复制到其输出中,用一个空格替换一个或多个空格的每个字符串."
你应该用一个空格替换每一行空白.:)上面显示的循环不执行此任务.
小智 5
除非任务是使用 for 循环来完成,否则如果您尝试获得更简洁的代码,那么学习该语言会更好。只需告诉自己代码的作用,例如将等效的 while 循环与 for 循环进行比较:
//initialize lch to prevent undefined behaviour
//if the first character is a space, it will be printed
lch = 'A';
// as long as you can read characters
while((ch = getchar()) != EOF) {
// if either the current character or the previous one is not a space
if(ch!=' ' || lch!=' ') {
//print it
putchar(ch);
}
// remember the current for the next round
lch = ch;
}
Run Code Online (Sandbox Code Playgroud)
一旦理解了 while 结构,您还可以将其转换为 hacky for 循环,但为什么要这样做呢?while 更容易阅读,编译器不会关心,因为它会以相同的方式编译两者。(大概)