0

Okay so the prompt was:

"Write a simple program (to demonstrate use of an array) that asks a user to type in numbers and keep typing in numbers until the user enters -1 or the total number of numbers entered reaches 20. Your program will stop asking for new input based on either condition above. Once one of the above conditions are met, the program will output all numbers entered as follows: 1. 888 2. 999 3. 4 …..and so on. Lastly, the program needs to display the sum of all values entered, excluding the -1 used to terminate the user input loop. The array should be used to store the user's inputs, and display them back before the program terminates."

Now, I have most of the prompt completed. It stops at 20 entered variables and displays them and the sum correctly. However, no matter how hard I try, I can't get it to register -1 as an exit. Nor can I get the bulleted list to start from 1. and end at 20. Everything else works just fine.

#include <stdio.h>
#define NUMBER_INPUTS 20 

int main(void){
    double userInput[NUMBER_INPUTS] = { 0 };
    int i = 0;

    while (i < NUMBER_INPUTS){
        printf("Enter number: \n", i);
        scanf("%lf", &userInput[i]);
        i++;        
    }

    for(i=0; i<NUMBER_INPUTS; i++)
        printf("%i. %.1lf \n", i, userInput[i]);    

    double total=0;
    for(i=0; i<NUMBER_INPUTS; i++)
        total+=userInput[i];
    printf("Total: %.1lf \n", total);

    return 0;
}

This is the code that works just fine. I've tried different do-whiles in different places to register the -1 but it messes up the output list AND doesn't stop the run.

#include <stdio.h>
#define NUMBER_INPUTS 20    

int main(void){
    double userInput[NUMBER_INPUTS] = { 0 };
    int i = 0;

do{
    while (i < NUMBER_INPUTS){
        printf("Enter number: \n", i);
        scanf("%lf", &userInput[i]);
        i++;        
    }
}while (userInput[i] != -1);

    for(i=0; i<NUMBER_INPUTS; i++)
        printf("%i. %.1lf \n", i, userInput[i]);    

    double total=0;
    for(i=0; i<NUMBER_INPUTS; i++)
        total+=userInput[i];
    printf("Total: %.1lf \n", total);

    return 0;
}

Like this? Just stops at the 20th variable entered. Doesn't matter if I've entered a -1 it just keeps going.

And for the list I attempted to use

i=i+1

to get the list from 1. to 20. to try and bump the i variable up one but for some reason that just shorted the output list to only show 20. and the total? I don't know what I'm doing wrong and would appreciate some input. Thank you.

Jupiter
  • 1
  • 2
  • "I don't know what I'm doing wrong". And we can't either unless you show the code that is not working as you expect. – kaylum Nov 24 '19 at 05:53
  • @kaylum You know what you're right – Jupiter Nov 24 '19 at 05:57
  • *After Your Edit* - You need to ***check the return*** of `scanf("%lf", &userInput[i]);` (and every input function used) to ***validate*** you received the input. You also need to read [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) and [Why Are Floating Point Numbers Inaccurate?](https://stackoverflow.com/questions/21895756/why-are-floating-point-numbers-inaccurate). – David C. Rankin Nov 24 '19 at 06:03
  • @DavidRankin-ReinstateMonica I think you may have misunderstood the prompt or maybe misunderstood me because the total isn't the problem. It stops at 20 like I need it to. It outputs all 20 numbers I've entered like I need it to. It's just not displaying them how I want nor is it stopping when I enter -1. Where would I need to put the `if (userInput[i] == -1` for it to correctly register and not mess up the rest of my code? – Jupiter Nov 24 '19 at 06:04
  • I did at first. That's why I deleted that comment and erased the `20` check. You should be OK, but be very careful in comparison on *floating-point* numbers with exact values. (the point of the two links). You need to preserve the value of `i` after you leave the read loop (that is the number of array elements filled). `int n = i;` will work. Then in your print loop. `for (i = 0; i < n; i++)`. As you have it, you are attempting to print `NUMBER_INPUTS` every time. If the user enters `-1` after 3 inputs -- that's not going to work. – David C. Rankin Nov 24 '19 at 06:07
  • You need to check both conditions on each loop. A the moment you are reading all 20 numbers before the -1 check is done. Something like: `do { ....} while(i < NUMBER_INPUTS && userInput[i-1] != -1)`. That is the logic but it may not actually work well. See @DavidRankin-ReinstateMonica links about comparing floating points. – kaylum Nov 24 '19 at 06:08
  • Another alternative is to check `userInput[i]` inside the reading loop and call `break` to exit the loop if it is `-1`. – kaylum Nov 24 '19 at 06:10

1 Answers1

1

Be very careful in comparison on floating-point numbers with exact values. (the point of the two links). While double can represent -1 exactly, don't fall into the habit of believing that floating-point numbers can represent any value exactly -- they can't. See: Is floating point math broken? and Why Are Floating Point Numbers Inaccurate?

To stop reading at the input of -1, you need to preserve the value of i (the number of elements) that have a valid double stored when you leave the read loop (that is the number of array elements filled). int n = i; will work (or just use the separate counter n and save i for use as a loop variable). Then in your print loop. for (i = 0; i < n; i++). As you have it, you are attempting to print NUMBER_INPUTS every time. If the user enters -1 after 3 inputs -- that's not going to work.

In order to use any input function correctly, you must validate the return. (this is especially true with scanf with contains many pitfalls for the new C programmer) Otherwise on a matching-failure, your array element will be left indeterminate, character extraction from stdin will cease leaving the offending characters in stdin unread just waiting to bite you again on your next attempted input. Instead -- validate, validate, validate. Lest ye violate Commandment No. 6. Example:

        if (scanf ("%lf", &userInput[n]) != 1) {    /* validate input */
            fputs ("error: invalid double input.\n", stderr);
            return 1;
        }

Putting the rest together, and giving an example of checking a floating-point value within a tolerance of +/- 1E-5, you could do:

#include <stdio.h>

#define NUMBER_INPUTS 20    

int main (void) {

    double userInput[NUMBER_INPUTS] = { 0 }, total = 0;
    int i = 0, n = 0;

    while (n < NUMBER_INPUTS){
        fputs ("Enter number: ", stdout);
        if (scanf ("%lf", &userInput[n]) != 1) {    /* validate input */
            fputs ("error: invalid double input.\n", stderr);
            return 1;
        }
        /* check for -1 (with +/- 1E-5 tolerance) */
        if (userInput[n] > -1.00001 && userInput[n] < -0.99998)
            break;
        total += userInput[n];
        n++;
    }

    putchar ('\n');
    for(i = 0; i < n; i++)
        printf("%d. %.1lf\n", i + 1, userInput[i]);    

    printf ("\nTotal: %.1lf \n", total);

    return 0;
}

Example Use/Output

$ ./bin/total
Enter number: 10
Enter number: 20
Enter number: 30
Enter number: 40
Enter number: 50
Enter number: -1

1. 10.0
2. 20.0
3. 30.0
4. 40.0
5. 50.0

Total: 150.0

Look things over and let me know if you have further questions. You were quite close.

Edit - updated output element indication to i + 1 to meet your requirement of Showing The Numbered List Starting From 1.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Good answer! Though I'm guessing the OP may have over-read the original requirements. There's nothing there that says the inputs will be floats. All the examples are just ints. Based on the level of the question I would say that the intention is just to read whole numbers. – kaylum Nov 24 '19 at 06:32
  • Yes, I was just going by the `double` type for the inputs. I was suspicious that they may want integer input, but the `printf` format string and the declaration of `userInput` suggested they really want `double` -- so I went with it `:)` – David C. Rankin Nov 24 '19 at 06:35