简体   繁体   English

扫描未知数量的输入并在 C 中打印条形图

[英]Scan unknown number of inputs and print bar chart in C

I am at a loss.我很茫然。 Attached a picture of the problem that I've been working on for at least 6 hours and can't figure out.附上一张我已经研究了至少 6 个小时但无法弄清楚的问题的图片。
To summarize what the problem is asking--read an input of integers off one line only.总结一下问题是什么——只从一行读取整数输入。 The first number in the line specifies how many numbers will follow(anywhere from 1 to 40 numbers).该行中的第一个数字指定将跟随多少个数字(从 1 到 40 个数字)。 Then use the following numbers and create bar charts at the very bottom with "*" corresponding to the numbers entered.然后使用以下数字并在最底部创建条形图,其中“*”对应于输入的数字。 Like I said, read the attached picture, it'll make more sense.就像我说的,阅读附图,它会更有意义。 I can get the program to work but only if I have the user input the numbers on separate lines.我可以让程序运行,但前提是我让用户在不同的行中输入数字。 Also I know how to do it using an array.我也知道如何使用数组来做到这一点。 However we are NOT allowed to use arrays.但是我们不允许使用数组。 Can only use for loops, any variation of while loops, nested loops, if statements, pow function, int float and double, switch statement, getchar(), scanf(), and logical operators.只能使用 for 循环、while 循环的任何变体、嵌套循环、if 语句、pow 函数、int float 和 double、switch 语句、getchar()、scanf() 和逻辑运算符。 I posted my code but its useless.我发布了我的代码,但它没用。 Any help would be greatly appreciated.任何帮助将不胜感激。

问题的图片

//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

The stdin input stream is typically buffered in C, so whatever input is in the stream after the user presses Enter will be available to scanf() until that input is exhausted. stdin输入流通常在 C 中缓冲,因此在用户按下Enter后流中的任何输入都可用于scanf()直到该输入用完为止。 After the first call to scanf() , you will have the number of input items to follow.在第一次调用scanf() ,您将拥有要跟随的输入项的数量。 Then a loop can execute further calls to scanf() until there is no more input to read.然后循环可以执行对scanf()进一步调用,直到没有更多的输入可供读取。

Note that more robust code should check the value returned by the call to scanf() to guard against malformed input and rare input failure events.请注意,更健壮的代码应该检查调用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;
}

Sample program interaction:示例程序交互:

>$ ./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

Potential Pitfalls潜在的陷阱

Since input remains in the input stream until it is read by some function call, subsequent calls to scanf() may pick up previous, unread, input values, leading to unexpected (and possibly undefined) behavior.由于输入一直保留在输入流中,直到它被某个函数调用读取,因此对scanf()后续调用可能会选择以前的、未读的输入值,从而导致意外(可能未定义)的行为。

For example, if the bar chart program loops to allow the user to enter another data set after displaying the results for the first one, it is possible for problems to arise.例如,如果条形图程序在显示第一个数据集的结果后循环允许用户输入另一个数据集,则可能会出现问题。 Suppose the user has entered more data than indicated by the first number: 3 1 2 3 4 .假设用户输入的数据比第一个数字所指示的多: 3 1 2 3 4 After the bar graphs have been displayed, the 4 will still remain in the input stream.显示条形图后, 4仍将保留在输入流中。 A subsequent call to scanf() would pick up this 4 , instead of whatever input the code is expecting.随后对scanf()调用将选择这个4 ,而不是代码期望的任何输入。 Try commenting out the call to clear_stream() in the code below and see what happens when the input line contains more items than expected.尝试在下面的代码中注释掉对clear_stream()的调用,看看当输入行包含的项目多于预期时会发生什么。

The idiomatic solution is to clear the input stream by reading all remaining characters in the input stream using getchar() :惯用的解决方案是通过使用getchar()读取输入流中的所有剩余字符来清除输入流:

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

The variable c needs to be an int rather than a char to ensure that the value returned by getchar() (which is an int and may be EOF , typically -1 ) can be held in c .变量c需要是int而不是char以确保getchar()返回的值(它是一个int并且可能是EOF ,通常是-1 )可以保存在c The loop reads and discards the characters in the input stream until a newline or EOF is reached.循环读取并丢弃输入流中的字符,直到到达换行符或EOF The getchar() function returns EOF in the rare event of an error, but a user may also enter EOF , so this value must be explicitly tested for to avoid a possible infinite loop. getchar()函数在极少数发生错误的情况下返回EOF ,但用户也可能输入EOF ,因此必须显式测试此值以避免可能的无限循环。

To avoid further problems with malformed input, check the value returned by the call to scanf() .为避免格式错误的输入出现更多问题,请检查调用scanf()返回的值。 This function returns the number of successful assignments made during the call as an int value (or may return EOF ).此函数将调用期间成功分配的次数作为int值返回(或可能返回EOF )。 If the user has entered a letter instead of a number for the initial value indicating the number of values in the dataset, no value is stored in num_values (and so the value of num_values remains indeterminate).如果用户为初始值输入了一个字母而不是数字来表示数据集中值的数量,则num_values不会存储任何值(因此num_values的值保持不确定)。 This leads to undefined behavior when the code later attempts to use num_values .当代码稍后尝试使用num_values时,这会导致未定义的行为。 By checking to see whether scanf() has returned a value of 1 as expected, this situation can be avoided.通过检查scanf()是否按预期返回值1 ,可以避免这种情况。

The code below allows the user to enter a line of data, preceded by the number of data items.下面的代码允许用户输入一行数据,前面是数据项的数量。 If the user enters -1 (or any value less than 1, or non-numeric input) for the number of items, the program exits.如果用户为项目数输入-1 (或任何小于 1 的值,或非数字输入),则程序退出。 Also, if the user has entered non-numeric input within the data items, a graph for that input item is simply not displayed.此外,如果用户在数据项中输入了非数字输入,则不会显示该输入项的图形。

#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');
}

Sample program interaction:示例程序交互:

>$ ./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

I think this will work.我认为这会奏效。 You don't need to create 41 variables.您不需要创建 41 个变量。 You can enter as many values as you want but if the scanf statement takes in only one value it will take the first value and the rest of the values will stay in queue.您可以输入任意数量的值,但如果scanf语句只接受一个值,它将采用第一个值,其余值将保留在队列中。 So the next time the control encounters a scanf statement it takes in the second value that you entered before.因此,下次控件遇到scanf语句时,它会采用您之前输入的第二个值。

In your question, you have to first enter the number of values that follow.在您的问题中,您必须首先输入后面的值的数量。 You can use this to learn how many times you have run the scanf statement in a loop.您可以使用它来了解在循环中运行 scanf 语句的次数。 I have used here a combination of if statement and goto .我在这里使用了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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM