Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么我的代码打印超过空字符?_C - Fatal编程技术网

C 为什么我的代码打印超过空字符?

C 为什么我的代码打印超过空字符?,c,C,我最近开始通过K&R学习C,第二版。我试图解决练习1-18,其中有以下描述:编写一个程序,从每行输入中删除尾随空格和制表符,并完全删除空白行 以下是我的尝试(使用MAXLINE=10调试程序): #包括 #定义MAXLINE 10/*最大输入行大小*/ int getline(char[],int); int main() { int len;/*当前线路长度*/ 字符行[最大行];/*当前输入行*/ 而((len=getline(line,MAXLINE))>-1) 如果(len>0) pri

我最近开始通过K&R学习C,第二版。我试图解决练习1-18,其中有以下描述:编写一个程序,从每行输入中删除尾随空格和制表符,并完全删除空白行

以下是我的尝试(使用
MAXLINE=10
调试程序):

#包括
#定义MAXLINE 10/*最大输入行大小*/
int getline(char[],int);
int main()
{
int len;/*当前线路长度*/
字符行[最大行];/*当前输入行*/
而((len=getline(line,MAXLINE))>-1)
如果(len>0)
printf(“%s”,第行);
返回0;
}
/*getline:将一行读入s,不带尾随空格,返回长度*/
int getline(字符s[],int lim)
{
int i,c,j;
i=j=0;
while(j0){
s[i]=c;
++一,;
}
s[i]='\0';
如果(c==EOF)
返回-1;
返回i;
}
所以我的基本想法是,我不停地把阅读字符填入行中,但也要跟踪(过去一个)最后一个非尾随空白字符的位置。然后我在这里放置了空字符,其思想是
printf(“%s”,whatever)
将实际打印任何内容,直到遇到第一个空字符为止


程序的行为与预期一致,包含9个或更少的字符(包括结尾的
\n
)。然而,它不断打印输入更多的字符,我不明白为什么。例如,我的输入为
1234567891\n
的程序实际上会打印回
1234567891\n
(是的,它甚至会更改行!)。我遗漏了什么?

我不知道这是否是全部答案,但我认为您需要:

 char line[MAXLINE+1].. this
这是因为您读取的是10,但数组需要额外的空空间


另外,我会尝试提高代码的可读性。可能将一些事情拆分为函数,将一些事情作为单独的步骤进行。6个月后,当你早已忘记了代码应该做什么时,你会感谢自己。

当输入为“123456789”,后跟一个换行符时:

  • while(j0循环为false
  • 然后
    s[i]='\0';
    追加一个空字符,然后
    getline
    返回到
    main
  • 此时,
    line
    的开头包含一个空字符。当
    main
    打印此字符时,不会打印任何内容
结论:设计有缺陷。
getline
设计用于在行为空的情况下通过不追加换行来抑制完全空白行(
i
在测试过程中为零
if(c='\n'&&i>0)
),但由于缓冲区大小而未完全处理的行的开头和续行都会调用它。当调用它进行行的续行并且该行正好在换行符处继续时,它会将其视为完全空行,并禁止追加换行符

一种补救方法是在
getline
中添加一个参数,告知它是为新行的开始还是为行的继续调用它,然后在(c='\n'&&i>0)时适当地修改测试


设计中的另一个缺陷是,如果一行在
getline
由于缓冲区已满而停止处理之前包含空格和/或制表符,它们将丢失,因为
getline
写入一个空字符来标记部分行的非空白部分的结尾,并返回到
main
,从而忘记了关于挂起的空格和/或制表符,这可能是需要的,因为行的后续部分包含非空白字符。

j
减去1以允许空字符的空间?@Barmar是的,但我认为这会影响它:
如果(c='\n'&&I>0){s[I]=c;++I;}
@JL2210:但只有当
\n
出现在9个字符之后时,数组才会溢出,这在问题中投诉的输入案例中不会发生。(一个有10个,第一次调用处理为9,第二次调用处理为2个,另一个有8个)。非常奇怪的是,他同时分配
s[j]=c
s[i]=c
c='\n'
@JL2210:实际上,它永远不会溢出数组。如果读取九个字符时没有看到
'\n'
,则第一个循环退出(由于
jn与您的问题无关,但您难道不知道您的
while
循环是一个奇怪的
for
循环吗?可能是相关的,您应该尝试以更清晰的方式编写代码。我还建议使用更多的空格来分隔运算符和操作数,这有助于读取它。使用
for
循环可能会lp.我还建议给变量取更好的名称,我读了一会儿才意识到
I
可能只是
total\u length
。你确定
12345678\n
是失败的,而不是
123456789\n
MAXLINE
是10吗?对于
123456789\n
,你的程序处理九个字符在
getline
中的ers,然后由于
j
测试而退出循环。最后读取的字符是
9
,因此它不追加换行符。它追加一个空字符并返回,主例程打印
123456789
,不带换行符。然后再次调用
getline
。然后
getline
reads
\n
并将其视为空行,因为
i>0
为false,它不追加换行符。它追加空字符并返回此空字符串。因此,
getline
旨在完全抑制空行,但程序失败,因为它使用
getline
来处理这两个星行一行的t和一行的续行,并且
getline
无法知道它正在处理一个已经非空白行的续行。您需要重新考虑设计
 char line[MAXLINE+1].. this