简体   繁体   中英

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.
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). 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. 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. After the first call to scanf() , you will have the number of input items to follow. Then a loop can execute further calls to scanf() until there is no more input to read.

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.

#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.

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 . After the bar graphs have been displayed, the 4 will still remain in the input stream. A subsequent call to scanf() would pick up this 4 , instead of whatever input the code is expecting. 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.

The idiomatic solution is to clear the input stream by reading all remaining characters in the input stream using 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 . The loop reads and discards the characters in the input stream until a newline or EOF is reached. 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.

To avoid further problems with malformed input, check the value returned by the call to scanf() . This function returns the number of successful assignments made during the call as an int value (or may return 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). This leads to undefined behavior when the code later attempts to use num_values . By checking to see whether scanf() has returned a value of 1 as expected, this situation can be avoided.

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. 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. 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. So the next time the control encounters a scanf statement it takes in the second value that you entered before.

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. I have used here a combination of if statement and 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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