我认为C-Infinite循环?

时间:2014-02-19 22:38:53

标签: c arrays function loops infinite-loop

我遇到了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];
    }
}

我应该注意,这是一个不允许使用字符串函数的类赋值,因此为什么它如此迂回。

3 个答案:

答案 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';终止它。同样,您需要确保reversetrim的输出的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()之前将其终止,您的程序将起作用。