Stop a for loop when user is finished entering input in c

前端 未结 5 1424
梦如初夏
梦如初夏 2021-01-20 21:27

First of all, thank you for the assist!

I\'m new to the C language (and programming in general) and I\'m trying to write a program wherein the user inputs data point

相关标签:
5条回答
  • 2021-01-20 21:33

    You have received a number of good answers to your question, and there are several more ways to take input of doubles and stop on "done". Since you are learning C, always, ALWAYS (in case it wasn't clear), check the return of scanf to validate the number of conversions you expected actually took place.[1] (this also provides your way to end input on "done" (or any non-double entered causing scanf to return less than 1)

    As noted in the comment, arrays are zero based in C. When you are taking input, you will want to use count as your array-index, rather than i (in this case if you exit the read on each failure -- it doesn't matter, but you could just as easily prompt again for additional input and increment count only on a successful return from scanf) Back to your question. If you set up your read loop to continually loop until there is a scanf failure, you can make use of a temporary variable to initially capture the input value, and only assign the value to your array and increment your index on success. e.g. (with a constant MAXD = 1048)

    for (;;) {  /* loop until scanf input fails (with 'done') */
    
        double tmp;  /* block scope declarations are fine */
    
        printf (" data[%4d]: ", count);
    
        if (count < MAXD && scanf(" %lf", &tmp) == 1)
            data[count++] = tmp;
        else
            break;
    } 
    

    (you can even move a copy of the prompt above the loop, and move the one above after the if (....) {...} to eliminate the prompt when the array limit (MAXD) is reached -- that's left as an exercise)

    In the example above you have 2 conditions you enforce before storing a value. (1) you limit the number of values your user can store to MAXD, and (2) you only store a value if a valid conversion to double takes place in scanf. You leave the loop if either of the conditions fails (which if you enter "done" as a double-value, it will).

    Putting the pieces together and dropping a few additional tips in the comments, you could test with something like the following:

    #include <stdio.h>
    
    enum { MAXD = 1048 };   /* declare constants instead of using magic numbers */
    
    int main (void) {
    
        double data[MAXD] = {0};    /* in ISO C declarations come before code */
        int i, count = 0;           /* initializing variable saves debug time */
    
        printf ("\n Welcome! \n\n Please enter each data point. "
                "Enter 'done' when finished.\n\n");
    
        for (;;) {  /* loop until scanf input fails (with 'done') */
    
            double tmp;  /* block scope declarations are fine */
    
            printf (" data[%4d]: ", count);
    
            if (count < MAXD && scanf(" %lf", &tmp) == 1)
                data[count++] = tmp;
            else
                break;
        } 
    
        printf ("\n %d values entered:\n\n", count);
    
        for (i = 0; i < count; i++)
            printf ("  data[%4d] : %.2lf\n", i, data[i]);
    
        return 0;   /* main() is type 'int' and returns a value */
    }
    

    Example Use/Output

    $ ./bin/scanfdoubles
    
     Welcome!
    
     Please enter each data point. Enter 'done' when finished.
    
     data[   0]: 1.1
     data[   1]: 1.2
     data[   2]: 1.3
     data[   3]: 1.4
     data[   4]: 1.5
     data[   5]: 1.6
     data[   6]: done
    
     6 values entered:
    
      data[   0] : 1.10
      data[   1] : 1.20
      data[   2] : 1.30
      data[   3] : 1.40
      data[   4] : 1.50
      data[   5] : 1.60
    

    Look things over and let me know if you have any questions.

    footnotes:

    1. while you can use scanf to take user-input in C, you are better off using a line-oriented function (like fgets) and then parsing the complete line (with, e.g. sscanf). The allows you to both (1) validate the read (e.g. the return of fgets) and then (2) separately validate the value entered by the user. This decoupling of your read, and your parsing has many advantages.

    0 讨论(0)
  • 2021-01-20 21:37

    For your task the loop of gathering input should control not only keyword, but also number if inputs. I suggest to do this as follows:

    #include <stdio.h>
    #include <string.h>
    #define NUM_OF_DATA 1048
    
    int main(void) 
    {
        printf("\n Welcome! \n\n Please enter each data point. Enter 'done' when finished.\n\n");
        double data[NUM_OF_DATA];
        int i; // counter of entered numbers
        char str[5] = { 0 }; // string to read 'done' or other word from input
        for (i = 0; i < NUM_OF_DATA; i++) // the first index of data in array is 0 (the last NUM_OF_DATA-1)
        {
            printf("Data[%i]: ", i);
            if (1 == scanf("%lf", &data[i])) // if number was successfully read
                continue; // go to next iteration
            // if some problem was with reading a loat number
            // read the string
            scanf("%4s", str); // read not more than 4 characters from input
            if ( strcmp(str, "done") == 0) 
            {
                break; // stop input if 'done' was entered
            }
            // clean input buffer before next input
            while (getchar() != '\n');
            // correct counter in case of wrong input
            i--;
        }
        // output the number of correct inputs
        printf("%d numbers were entered.\n", i);
        // do something with data
        // taking in account, that i is not index of the last element, 
        // but the number of elements (indexes are 0 ... i-1)
        // ...
        return 0;
    }
    

    This for loop stops in two cases:

    1) when data array is full,

    2) when 'done' without quotes entered.

    Additional feature is skipping of incorrect input (try how it works).

    0 讨论(0)
  • 2021-01-20 21:39
    • Your data is of type double. It can't scan a literal "done".

    Instead use EOF for checking end of input.

    while(scanf("%lf",&data[i]) != EOF) {
        ...
    }
    

    Another way:

    while(scanf("%lf",&data[i]) == 1) {
        ...
    }
    
    • Another thing, initialize count to zero, i.e. count = 0;
    0 讨论(0)
  • 2021-01-20 21:55

    No element of data[] will ever be 'done' (they're floats). If you want to scanf() directly, you'll need to choose a double value that ends the sequence (commonly zero or -1 or something). If that won't work, you can either use something like:

    1. Use fgets() to pull a string, then strncmp() to check for the terminating value and sscanf() to pull out the double, or:
    2. Have the user use Ctrl-D to terminate and check the scan value for EOF.

    Oh, and strictly speaking you have an upper limit of entries. You should check i to make sure that you don't exceed that. Never assume your input won't exceed boundaries. sizeof() on a statically-allocated variable or some #defined macro to track that.

    0 讨论(0)
  • 2021-01-20 21:55

    Bottom line: don't use scanf.

    Use something like

    char inputline[100];
    
    i = 0;
    
    while(fgets(inputline, sizeof(inputline), stdin) != NULL) {
        if(strncmp(inputline, "done", 4) == 0) break;
        data[i++] = atof(inputline);
    }
    

    scanf is hard enough to use even when all your inputs are the numbers you expect. If the input might be either a number or the word "done", scanf will never work. But reading a line of text, as here, is generally easier and more flexible.

    P.S. You also have to worry about the possibility that the user enters more than 1048 numbers.

    0 讨论(0)
提交回复
热议问题