C语言 给予附加输出的程序中出错

dffbzjpn  于 2022-12-03  发布在  其他
关注(0)|答案(2)|浏览(168)
#include <stdio.h>
#include <math.h>

int main()
{
    int i;
    int j;
    int base;
    int height;
    int side;
    int up;
    int down;
    int output[1001];
    
    for (i = 0; i < 1000; i++)
    {
        char type = getchar();
        
        if(type == 'P')
        {
            scanf("%d", &side);
            
            output[i] = side * side;
        }
        else if (type == 'S')
        {
            scanf("%d %d", &base, &height);
            
            output[i] = 0.5 * base * height;
        }
        else if (type == 'T')
        {
            scanf("%d %d %d", &up, &down, &height);
            
            output[i] = height * (up + down) / 2;
        }
        else if(type == '0')
        {
            break;
        }
    }
    
    for(j = 0; j < i; j++)
    {
        {
            printf("%d\n", output[j]);
        }
    }
    
    return 0;
}

我想要的是在我输入'0'后,程序停止请求输入然后给予输出。总体来说它是工作的,但是有一个错误,在每个输出中,总是有一行'0'。

样品输入:

P 5
S 10 10
T 10 10 10
0

我想要的输出:

25
50
100

我现在对这段代码的输出:

25
0
50
0
100
0

我猜是

else if(type == '0')
        {
            break;
        }

这使得这个错误,但我不确定,我不知道如何解决这个问题

vyswwuz2

vyswwuz21#

问题是这些线条

scanf("%d", &side);
scanf("%d %d", &base, &height);
scanf("%d %d %d", &up, &down, &height);

will not extract the newline character at the end of the line
因此,在下一次循环迭代中,对getchar的调用将提取新行字符,而对scanf的调用将失败,因为下一个字符是字母而不是数字。这意味着只有一次循环迭代后对getchar的调用才会真正提取新行的第一个字符。
通过在debugger中逐行运行程序,可以清楚地看到此错误,因为调试器将显示在第二次循环迭代中type的值将是\n(ASCII代码10)。
要修复此错误,最简单的解决方案是在每次调用scanf后添加一个对getchar的调用,这将丢弃输入流中的换行符。
一个更健壮的解决方案不使用scanf,而是使用函数fgets来始终精确读取一行输入,并使用sscanf来解析输入:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
    int output[1000];
    char line[200];
    int i;

    //attempt to read one line of input per loop iteration
    for ( i = 0; ; i++ ) //infinite loop
    {
        char *p;

        //protect against buffer overflow
        if ( i == sizeof output / sizeof *output )
        {
            fprintf( stderr, "Too many lines!\n" );
            exit( EXIT_FAILURE );
        }

        //attempt to read one line of input
        if ( fgets( line, sizeof line, stdin ) == NULL )
        {
            fprintf( stderr, "Error reading input!\n" );
            exit( EXIT_FAILURE );
        }

        //attempt to find newline character in the line
        p = strchr( line, '\n' );

        //verify that entire line was read and remove the
        //newline character, if it exists
        if ( p == NULL )
        {
            //a missing newline character is probably acceptable
            //when end-of-file has been reached, for example when
            //standard input is being piped from a file.
            if ( !feof( stdin ) )
            {
                fprintf( stderr, "Line too long for input buffer!\n" );
                exit( EXIT_FAILURE );
            }
        }
        else
        {
            //remove the newline character by overwriting it with
            //a terminating null character
            *p = '\0';
        }

        if( line[0] == 'P' )
        {
            int side;

            if ( sscanf( line+1, "%d", &side ) != 1 )
            {
                fprintf( stderr, "Error parsing input!\n" );
                exit( EXIT_FAILURE );
            }

            output[i] = side * side;
        }
        else if ( line[0] == 'S' )
        {
            int base, height;

            if ( sscanf( line+1, "%d %d", &base, &height ) != 2 )
            {
                fprintf( stderr, "Error parsing input!\n" );
                exit( EXIT_FAILURE );
            }

            output[i] = 0.5 * base * height;
        }
        else if ( line[0] == 'T' )
        {
            int up, down, height;

            if ( sscanf( line+1, "%d %d %d", &up, &down, &height ) != 3 )
            {
                fprintf( stderr, "Error parsing input!\n" );
                exit( EXIT_FAILURE );
            }

            output[i] = height * (up + down) / 2;
        }
        else if ( line[0] == '0' )
        {
            //break out of infinite loop
            break;
        }
    }
    
    for ( int j = 0; j < i; j++ )
    {
        printf( "%d\n", output[j] );
    }
    
    return 0;
}

对于问题中指定的输入,此程序具有所需的输出:

25
50
100
ecbunoof

ecbunoof2#

输入可以更好地可视化为:

P 5\n
S 10 10\n
T 10 10 10\n
0\n

i在遇到一个零 * 之前 * 的每一个换行符时都增加一次。
快速解决方法是在向数组中添加内容时仅递增i

for (i = 0; i < 1000;)
{    
    char type = getchar();    

    if(type == 'P')    
    {    
        scanf("%d", &side);    

        output[i++] = side * side;    
    }    
    else if (type == 'S')    
    {    
        scanf("%d %d", &base, &height);    

        output[i++] = 0.5 * base * height;    
    }    
    else if (type == 'T')    
    {    
        scanf("%d %d %d", &up, &down, &height);    

        output[i++] = height * (up + down) / 2;    
    }    
    else if(type == '0')    
    {    
        break;    
    }    
}

getchar返回EOF时,仍然存在无限循环的问题,并且不检查scanf的返回值以查看调用是否成功地执行了预期的 * 转换 * 次数,从而使您对不确定的值进行操作。
对此进行一些重构:

#include <stdio.h>
#include <stdlib.h>

#define MAX 1001

int get_int(void)
{
    int x;

    if (1 != scanf("%d", &x))
        exit(EXIT_FAILURE);

    return x;
}

int main(void)
{
    int i = 0;
    int output[MAX];

    while (i < MAX) {
        int type = getchar();

        if (EOF == type || '0' == type)
            break;

        int value;
        int up, down, height, side;

        switch (type) {
            case 'P':
                side = get_int();
                value = side * side;
                break;
            case 'S':
                value = 0.5 * get_int() * get_int();
                break;
            case 'T':
                up = get_int();
                down = get_int();
                height = get_int();
                value = height * (up + down) / 2;
                break;
            default:
                continue;
        }

        output[i++] = value;
    }

    for (int j = 0; j < i; j++) {
        printf("%d\n", output[j]);
    }
}

相关问题