扫描未知数量的输入并在C

时间:2018-09-15 15:19:15

标签: c

我很茫然。附上我已经处理了至少6个小时而无法解决的问题的图片。
要总结问题所在,请仅从一行读取整数输入。该行中的第一个数字指定将跟随多少个数字(从1到40个数字的任何位置)。然后使用以下数字,并在最底部创建条形图,并在条形图上输入相应的数字“ *”。就像我说的,阅读所附图片会更有意义。 我可以使该程序正常运行,但前提是我让用户在单独的行中输入数字。我也知道如何使用数组。但是,我们不允许使用数组。只能用于for循环,while循环,嵌套循环,if语句,pow函数,int float和double,switch语句,getchar(),scanf()和逻辑运算符的任何变体。我发布了代码,但是它没有用。任何帮助将不胜感激。

picture of problem

//Homework 4 - Question 3

//main.c


//indicates preprocessor
#include <stdio.h>


//being function main
int main(void){


    //define variables
    int barnum, counter = 1, counter2 = 0, length = 0;


    //prompt for number of bars user wants to input
    printf("--------------------Bar Chart Calculator--------------------\n");
    printf("Enter integers from 1 to 40 for questions below.\n");
    printf("------------------------------------------------------------\n\n");
    printf("Enter the number of bars wanted in chart: ");
    scanf("%d", &barnum);

    printf("Enter the length of each bar, pressing enter after each entry.\n");
    printf("---------Begin entering integers below this line-------------\n");



    //while loop to repeat for specified number of bars
    while (counter <= barnum){
        length = 0;
        counter2 = 0;
        scanf("%d", &length);

        //while loop to print individual * in a single line
        while (counter2 < length) {
            printf("*");
            counter2++;  //increments counter
        }//end counter 2 while loop

        printf("(%d)\n", length);
        counter++;  //increments counter

    }  //end counter while loop


    return 0;  //indicates program ended successfully

}  //end function main

2 个答案:

答案 0 :(得分:1)

stdin输入流通常在C中缓冲,因此用户按下 Enter 之后,流中的任何输入将对scanf()可用,直到该输入耗尽。首次调用scanf()之后,您将可以掌握输入项的数量。然后,循环可以执行对scanf()的进一步调用,直到没有更多输入要读取为止。

请注意,更健壮的代码应检查对scanf()的调用返回的值,以防止格式错误的输入和罕见的输入失败事件。

#include <stdio.h>

int main(void)
{
    int num_values;
    scanf("%d", &num_values);

    for (int i = 0; i < num_values; i++) {
        int val;
        scanf("%d", &val);
        printf("Value %d: %d\n", i, val);
    }

    return 0;
}

示例程序交互:

>$ ./a.out 
6 3 1 4 1 5 9
Value 0: 3
Value 1: 1
Value 2: 4
Value 3: 1
Value 4: 5
Value 5: 9

潜在的陷阱

由于输入保留在输入流中,直到被某个函数调用读取,因此对scanf()的后续调用可能会获取先前的未读输入值,从而导致意外的(可能是未定义的)行为。

例如,如果条形图程序循环显示,以便用户在显示第一个结果后输入另一个数据集,则可能会出现问题。假设用户输入的数据多于第一个数字3 1 2 3 4所指示的数据。条形图显示后,4仍将保留在输入流中。随后对scanf()的调用将获取此4,而不是代码期望的任何输入。尝试在下面的代码中注释掉对clear_stream()的调用,看看输入行包含的项目比预期的多时会发生什么。

惯用的解决方案是通过使用getchar()读取输入流中的所有剩余字符来清除输入流:

int c;
while ((c = getchar()) != '\n' && c != EOF) {
    continue;
}

变量c必须是int而不是char,以确保getchar()返回的值(是int,并且可以EOF,通常-1)可以放在c中。循环读取并丢弃输入流中的字符,直到到达换行符或EOFgetchar()函数在发生错误的极少数情况下会返回EOF,但是用户也可以输入EOF,因此必须明确测试该值,以免发生无限循环。

为避免格式错误的输入进一步造成问题,请检查对scanf()的调用返回的值。此函数以int值的形式返回调用过程中成功分配的次数(或返回EOF)。如果用户输入了字母而不是数字作为表示数据集中值数量的初始值,则num_values中不会存储任何值(因此num_values的值仍然不确定)。当代码稍后尝试使用num_values时,这导致未定义的行为。通过检查scanf()是否已按预期返回值1,可以避免这种情况。

下面的代码允许用户输入一行数据,然后输入数据项的数量。如果用户输入-1(或小于1的任何值,或非数字输入)作为项目数量,则程序退出。另外,如果用户在数据项中输入了非数字输入,则不会显示该输入项的图形。

#include <stdio.h>

void clear_stream(void);
void print_bar(int n);

int main(void)
{
    char *prompt = "Enter the number of values to graph, followed by the values"
                   " (-1 to exit)";
    int num_values;
    puts(prompt);
    int ret_scanf = scanf("%d", &num_values);

    while (ret_scanf == 1 && num_values > 0) {
        for (int i = 0; i < num_values; i++) {
            int val;
            /* print bar if a number was entered */
            if (scanf("%d", &val) == 1) {
                print_bar(val);
            }
        }
        putchar('\n');
        puts(prompt);
        clear_stream();                        // try commenting out this line
        ret_scanf = scanf("%d", &num_values);
    }

    return 0;
}

void clear_stream(void)
{
    int c;
    while ((c = getchar()) != '\n' && c != EOF) {
        continue;
    }
}

void print_bar(int n)
{
    for (int i = 0; i < n; i++) {
        putchar('*');
    }
    putchar('\n');
}

示例程序交互:

>$ ./a.out 
Enter the number of values to graph, followed by the values (-1 to exit)
6 3 1 4 1 5 9
***
*
****
*
*****
*********

Enter the number of values to graph, followed by the values (-1 to exit)
-1

答案 1 :(得分:0)

我认为这会起作用。您无需创建41个变量。您可以输入任意多个值,但是如果scanf语句仅接受一个值,它将接受第一个值,而其余值将保留在队列中。因此,下一次该控件遇到scanf语句时,它将采用您之前输入的第二个值。

在您的问题中,您必须首先输入随后的值数。您可以使用它来了解在一个循环中运行scanf语句的次数。我在这里使用了if语句和goto的组合。

#include <stdio.h>

int main()
{
int i, j, k, l=1;

/* Here variable 'i' stores the first number entered */

printf("Enter intergers from 1 to 40 where first number indicates how many 
numbers follow: ");
scanf("%d", &i);



a : scanf("%d", &j);

for(k=1 ; k<=j; k++)
{
    printf("*");
}

printf("\n");
l++;
if(l<=i)
goto a;

return 0;
}