为什么此代码在输入和输出行之间打印随机字符?

时间:2019-08-04 05:03:36

标签: c arrays printf character

我正在尝试编写一个程序(用C语言编写),其中输入是反向的,并逐行反向打印。在大多数情况下,代码实际上就是这样做的。麻烦的是,对于我的某些输入(大部分),我将在控制台的输入和输出之间得到一个随机字符或多余的换行符。

例如,我启动程序,在控制台中输入“ testing”,并在按Enter键后返回“ gnitseT”。这已经成功发生,这是我的期望。看起来像这样:


测试

gnitseT


但是当我在控制台中输入“ Hello”时,它看起来像这样:


你好

g(意外)

olleH


或者,如果我在控制台中输入“ running”,而不是在输入和输出行之间出现意外的“ g”,我会得到一个额外的换行符。


运行

在这里换行

此处多余的换行符(意外)

gninnuR


#include <stdio.h>




void reverse(int length, char s[])
{
    int i;

    for (i = length; i >= 0; i--)
    {
        printf("%c", s[i]);
    }
    printf("\n");

}


int main(void)
{
    char smain[2000];
    int c;
    int i;

    i = 0;
    while ((c = getchar()) != EOF)
    {
        smain[i] = c;
        i++;
        if (c == '\n')
        {
            reverse(i, smain);
            i = 0;
        }
    }

    return 0;
}

预期的行为是程序在按Enter键之后将反向输入输出到控制台。

有时候,尤其是在程序的开始,它会完美地运行。

然后,它开始给我输入和输出之间的随机字符,或者开始给我额外的换行符。

我希望它能以相反的顺序打印输入,而在输入和输出之间不会出现任何意外的奇数字符。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您的直接问题是您正在阅读并尝试使用

在存储在数组中的字符末尾打印一个字符
for (i = length; i >= 0; i--) {
    printf("%c", s[i]);
}

为什么?您将length个字符添加到smain中的main()中。在C语言中,数组是基于基于零的。字符串中的字符来自0 -> length-1 string 中的 nul-character 位于s[length],但是在这里您永远不会添加< em> nul-termination 字符,因此该索引处的值就是不确定的)。如果该元素尚未初始化(它不会出现在您的第一个单词或等于或大于您当时输入的最长单词的任何后续单词上),则由于尝试读取而导致未定义行为并从数组中未初始化的元素中打印不确定的值。终端输出不确定的方式是 undefined -可能会导致打印G

要解决此问题,请循环for (i = length - 1; i >= 0; i++)或非常简单:

while (length--)
    printf ("%c", s[length]);

putchar ('\n');     /* don't printf a single-character */

注意:不要调用可变参数printf函数来输出单个字符,这就是putchar()的目的)

完全放入并固定逻辑,这样就不必在要反转的每个单词中添加和打印'\n',您可以这样做:

#include <stdio.h>

#define MAXC 2048   /* if you need a constant, #define one (or more) */

void reverse(int length, char s[])
{
    while (length--)
        printf ("%c", s[length]);

    putchar ('\n');     /* don't printf a single-character */
}


int main (void) {

    char smain[MAXC];
    int c, i = 0;

    while ((c = getchar()) != EOF) {
        if (c == '\n') {
            reverse(i, smain);
            i = 0;
        }
        else
            smain[i++] = c;
    }
    if (i)  /* protect against file with no POSIX end-of-file */
        reverse (i, smain);

    return 0;
}

注意if {...} else {...}逻辑以防止添加'\n'

使用/输出示例

$ printf "Hello\nGoodbye\n" | ./bin/prnrevlines
olleH
eybdooG

例如,在没有POSIX eof的情况下,哪个也可以正常工作

$ printf "Hello\nGoodbye" | ./bin/prnrevlines
olleH
eybdooG

答案 1 :(得分:0)

第29行

++i;

这意味着“ i”现在的长度为+1,因此,您已经超出了字符串的范围,可以将程序更改为:

#include <stdio.h>




void reverse(int length, char s[])
{
    int i;

    for (i = length; i >= 0; i--)
    {
        printf("%c", s[i]);
    }
    printf("\n");

}


int main(void)
{
    char smain[2000];
    int c;
    int i;

    i = 0;
    while ((c = getchar()) != EOF)
    {
        smain[i] = c;
        if (c == '\n')
        {
            reverse(i, smain);
            i = 0;
        }
        else i++;
    }

    return 0;
}