4

I'm trying to make a little program to calculate standard deviation for practice. My problem seems to be the first while statement in my main function.

I’m a little rusty at this and I can’t figure out why I don’t leave the while statement after the user hits enter.

Don’t mind my greenness. Still learning.

#include <stdio.h>
#include <math.h>
#define arraySize 100
double standardDeviation(int, double*);
int main(void){
    double array[arraySize];
    double result;
    int i=0;
    int count=0;
    printf("Enter up to %d data separated by spaces then hit enter:\n\n",arraySize);
    while(i<arraySize && array[i]!='\n'){
        scanf("%lf",&array[i]);
            i++;
            count++;
            }

    result=standardDeviation(count, array);

    printf("The standard deviation of your data is: %lf",result);

    return 0;
}

double standardDeviation(int count, double* firstDatum){
    int i=0,j=0;
    double standDev=0;
    double standDevArray[arraySize];
    double sum=0,sum2=0;
    double mean=0,variance=0;
    while(i<count){
        sum=sum + firstDatum[i]; 
        //printf("%lf", sum);
        i++;
    }
    mean=sum/count;
    //printf("The mean is: %lf", mean);

    while(j<count){
           standDevArray[j] = (mean  - firstDatum[j]) * (mean - firstDatum[j]);
           sum2=sum2+standDevArray[j];
           j++;
    }   
    variance=sum2/count;
    standDev=sqrt(variance);
    return standDev;
 }
6
  • Look at value of i, hence value of array[i] when comparing with newline. Commented Dec 20, 2019 at 6:31
  • 2
    array[i] is a double. While it isn't wrong to compare that with '\n', it is weird and unusual — write 13.0 rather than '\n', probably (but even more likely, that test is superfluous). Also, the value of i is one beyond the last initialized entry in array — you've got undefined behaviour (UB) in your code. You should be checking the result of the scanf() call, too. Commented Dec 20, 2019 at 6:34
  • 4
    The user hitting enter doesn't terminate your loop because the %lf format skips white space, including newlines. You might (probably would) exit the loop if you typed 13 as a value. Detecting newlines in scanf() is hard. You have to be doing character input (%c, %s, %[…]) to get a newline into your program's data. Commented Dec 20, 2019 at 6:40
  • while(i<arraySize && scanf("%lf",&array[i]) == 1) { ... } Commented Dec 20, 2019 at 8:04
  • 1
    @JonathanLeffler '\n' is typically 10, not 13. ('\r' is typically 13.) Commented Dec 21, 2019 at 2:22

3 Answers 3

1

There is no reason to ask the user for the number of entries. You ask the user for a line of input, you read the line of input into a buffer using fgets (or POSIX getline), you then scan through the buffer converting the numbers entered into double values using either strtod (preferred), or using sscanf and an offset to the next value to read.

You have done a good job protecting your array bounds with while (i < arraySize ..., all you need to do is add a second condition while a valid conversion is preformed. For example:

#define MAXC 2048
...
int main(void) {

    char buf[MAXC];                     /* buffer to hold line of input */
    double array[arraySize], result;    /* your array and result */
    int i = 0, offset = 0, used;        /* i, offset in buf, chars used */

    printf ("Enter up to %d data separated by spaces then hit enter:\n\n",
            arraySize);
    if (!fgets (buf, MAXC, stdin)) {    /* read/validate line of input */
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }

    while (i < arraySize && /* while in bounds && valid conversion */
            sscanf (buf + offset, "%lf%n", &array[i], &used) == 1) {
        offset += used;     /* update offset with chars used in conversion */
        i++;                /* increment index */
    }

    result = standardDeviation (i, array);  /* compute/display result */

    printf ("The standard deviation of your data is: %lf\n",result);

    return 0;
}

Now you simply display your prompt, the user enters up to 100 values, and you read the values into your array and preform you calculations. Here the buffer size of 2K allows ~19-characters per-value. If that is insufficient, then use a 4K buffer and provide for ~40-chars per-value.

Additionally, there is no need for your stdDevArray or to declare separate loop counter variables in your standardDeviation() function. Since C99, you can declare the loop variable as part of the loop definition. There is nothing wrong with using the stdDevArray, it is simply not required. Spacing your code in a consistent manner also helps with the readability. If you eliminate the separate loop variables and the unneeded stdDevArray, you can tweak your function as follows:

double standardDeviation (int count, double *firstDatum)
{
    double  standDev = 0,
            sum = 0, sum2 = 0,
            mean= 0, variance = 0;

    for (int i = 0; i < count; i++)
        sum += firstDatum[i]; 

    mean = sum / count;

    for (int i = 0; i < count; i++)
        sum2 += (mean  - firstDatum[i]) * (mean - firstDatum[i]);

    variance = sum2 / count;
    standDev = sqrt(variance);

    return standDev;
}

Note the += operator is just a short-hand convenience operator. Instead of writing sum = sum + firstDatum[i];, you can simply write sum += firstDatum[i];

Let me know if you have further questions.

Sign up to request clarification or add additional context in comments.

Comments

0

2 errors in this piece of code, one of there causes an Undefined Behavior.

First of all you compare a double(array[i]) with a char ('\n').

The second one is the index "i". In the while loop you first do scanf and assign the i-th element of the array, the increment i with the operation i++ e after that in next iteration you compare a not initialized i-th element of the array with somenthing. Pay attention at the moment of comparison your index is already incremented and you do not assign nothing to that element and this causes an undefined behavior.

5 Comments

Comparing a double with a char doesn't cause undefined behavior; since char is an integer type, it is converted to a double.
Yes, i badly explain myself. I meant the program in general cause an undefined behavior caused by the second error.
So for the first error, though not undefined, the '\n' is never read into the array of doubles by scanf, thus i need to find another way to exit the loop from user input? And for the second error, are you saying I should change i++ to ++i? Why though? And I did I DID initialize i to 0. See a few lines up.
@exnihilo A quibble: '\n' is of type int, not char. (That doesn't affect the behavior.)
@KeithThompson -- of course; that was sloppy of me ;)
0

I made the following adjustments to the main function. I simply predetermined the number of data entries based on the user input, and it works fine. It’s comforting to know that my function worked on it’s first call and gave me the correct value for standard deviation.

But a little discomforting to know i had to ask user for the amount of entries. I think the program would be a little more user friendly if i could enter data and then terminate when i reach the end of the list. Especially with larger data sets that a person doesn’t know how many data they are entering. It’s a little tough to use arrays with option of terminating with a value outside of bounds, because limiting the values of the entries also limits the functionality of the function. Do think if someone wanted to make a program such as this, linked lists would be more suited to this?

#include <stdio.h>
#include <math.h>
#define arraySize 100
double standardDeviation(int, double);
int main(void){
    double array[arraySize];
    double result;
    int userSize;
    int i=0;
    int count=0;
    printf("Enter how many data will be entered up to a maximum of %d\n\n",arraySize);
    scanf("%d",&userSize);
    printf("Enter your data:\n\n");
        while(i<userSize && i<arraySize){
        scanf("%lf",&array[i]);
            i++;
            count++;
            }


    result=standardDeviation(count, array);

    printf("The standard deviation of your data is: %lf",result);


    return 0;
}

    double standardDeviation(int count, double* firstDatum){
        int i=0,j=0;
        double standDev=0;
        double standDevArray[arraySize];
        double sum=0,sum2=0;
        double mean=0,variance=0;
        while(i<count){
            sum=sum + firstDatum[i]; 
            //printf("%lf", sum);
            i++;
        }
        mean=sum/count;
        //printf("The mean is: %lf", mean);

        while(j<count){
               standDevArray[j] = (mean  - firstDatum[j]) * (mean - firstDatum[j]);
               sum2=sum2+standDevArray[j];
               j++;
        }   
        variance=sum2/count;
        standDev=sqrt(variance);
        return standDev;
     }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.