我遇到了C语言程序的问题,我认为for
循环是罪魁祸首,但我不确定。该函数用于获取已经通过反向函数传递的char[]
,并将其写入不同的char[]
,并删除所有尾随空白字符。也就是说,位于' '
和任何其他字符之间的任何'\t'
或'\n'
字符都不应该是输出的一部分。
如果没有尾随空白字符,则可以完美地工作,就像重写输入char[]
的精确副本一样。但是,如果有,则根本没有输出。
该计划如下:
#include<stdio.h>
#define MAXLINE 1000
void trim(char output[], char input[], int len);
void reverse(char output[], char input[], int len);
main()
{
int i, c;
int len;
char block[MAXLINE];
char blockrev[MAXLINE];
char blockout[MAXLINE];
char blockprint[MAXLINE];
i = 0;
while ((c = getchar()) != EOF)
{
block[i] = c;
++i;
}
printf("%s", block); // for debugging purposes
reverse(blockrev, block, i); // reverses block for trim function
trim(blockout, blockrev, i);
reverse(blockprint, blockout, i); // reverses it back to normal
// i also have a sneaking suspicion that i don't need this many arrays?
printf("%s", blockprint);
}
void trim(char output[], char input[], int len)
{
int i, j;
i = 0;
j = 0;
while (i <= len)
{
if (input[i] == ' ' || input[i] == '\t')
{
if (i > 0 && input[i-1] == '\n')
for (; input[i] == ' ' || input[i] == '\t'; ++i)
{
}
else
{
output[j] = input[i];
++i;
++j;
}
}
else
{
output[j] = input[i];
++i;
++j;
}
}
}
void reverse(char output[], char input[], int len)
{
int i;
for (i = 0; len - i >= 0; ++i)
{
output[i] = input[len - i];
}
}
我应该注意,这是一个不允许使用字符串函数的类赋值,因此为什么它如此迂回。
答案 0 :(得分:1)
更改
for (i; input[i] == ' ' || input[i] == '\t'; ++i);
到
for (; i <= len && (input[i] == ' ' || input[i] == '\t'); ++i);
使用第一种方法,如果空白位于末尾,则循环将无限循环。不知道你怎么没有得到一个越界访问异常,但那是你的C / C ++。
编辑由于Arkku在评论中提到,请确保您的字符数组仍然以NUL终止(\0
字符),您可以检查该案例。确保你没有从最后修剪NUL角色。
答案 1 :(得分:1)
(从评论转到答案)
我的猜测是问题超出了这个功能,并且是由于在所描述的问题情况下输出比输入短。由于您将字符串的长度作为参数传递,因此需要在trim
之后计算字符串的长度,因为它可能已更改...
例如,将不正确的长度传递给reverse
会导致终止NUL字符(可能还有一些剩余的空格)最终出现在字符串的开头,从而使输出显示为空。
修改:在看到包含reverse
代码的已编辑问题后,除了上述问题之外,您的reverse
会将终止NUL作为第一个字符反向字符串,它使它成为空字符串(在某些情况下,你的第二个reverse
将它放回去,所以你没有打印出第一个reverse
的输出就看不到它。请注意,input[len]
包含'\0'
,而不是字符串本身的最后一个字符。
编辑2 :此外,在使用之前,您实际上并未终止block
中的字符串。可能是未初始化的数组经常包含用于终止字符串的零的情况,但是为了使程序正确,您绝对需要在输入循环之后立即用block[i] = '\0';
终止它。同样,您需要确保reverse
和trim
的输出的NUL终止(在trim
的情况下,在我看来,这已经发生作为具有循环条件的副作用{ {1}}而不是i <= len
,但这并不是好代码的标志,很难说明。)
答案 2 :(得分:1)
将main()
函数简单地声明为main()
是一种不应使用的过时样式。该函数必须声明为int main(void)
或int main(int argc, char *argv[])
。
您的输入过程不会终止您的输入。这意味着您正在使用的不是“字符串”,因为根据定义,C字符串是char
的数组,最后一个元素是空字符('\ 0')。相反,你得到的是char
的简单数组。只要你期望这样,这确实是你的代码传递数组长度,但你也试图用printf()
打印它,这需要C字符串,而不是简单数组char。
你的reverse()
函数有一个off-by-one错误,因为你没有考虑到C数组是零索引的事实,所以你正在反转的东西总是比你的实际长一个字节输入
这意味着,如果您致电reverse(output, input, 10)
,您的代码将首先将input[10]
的值指定为output[0]
,但input[10]
是一个过去数据的结尾,并且由于在开始填充数组之前没有初始化数组,因此这是一个不确定的值。在我的测试中,巧合的是,这个不确定的值在很多时候都会出现零值,这意味着output[0]
会被填充为null('\0'
)。
您需要从索引中减去一个input
而不是实际值。 reverse()
函数中的循环终止条件也是错误的,作为补偿,该条件应为len - i > 0
,而不是len - i >= 0
。
您的trim()
功能不必要地复杂。此外,它也有不正确的循环条件来补偿reverse()
中的逐个错误。循环应该是while ( i < len )
,而不是while ( i <= len )
。
此外,trim()
函数可以减小数据的大小,但是您没有提供保留该信息的方法。 (我在Arkku的回答评论中看到你已经对此进行了纠正。很好。)
一旦你修复了这个问题而没有跟踪你的数据的大小变化,以及从{{末尾复制不确定数据(巧合的是,为空)的一个一个错误的错误当您执行第二个blockout
时,{1}}数组的{1}}数组,并修复blockprint
中不正确的reverse()
条件和不正确的{{1} <=
中的条件,并且在将字节数组传递给trim()
之前将其终止,您的程序将起作用。