dsmith
dsmith

Reputation: 33

scanf() only reading first input (number)

I can't really explain it except that scanf() is only reading the first value, and then the calculations are made based off of that.

int main() {
    int i, students = 0;
    char name[20];
    int tests;
    float test_score;
    int test_sum = 0;
    char letter_grade;
    double test_average;

    printf("Number of students: ");
    scanf("%d", &students);

    for (i = 0; i < students; i++) {
        printf("\nStudent name %d: ", i + 1);
        scanf(" %s", &name);
        fflush(stdin);

        printf("Number of test(s) for %s: ", name);
        scanf("%d", &tests);
        fflush(stdin);

        printf("Enter %d test score(s) for %s: ", tests, name);
        if (i < students) {
            scanf("%f", &test_score);
            test_sum += test_score;
            test_average = test_sum / (float)tests;
        }
        printf("Average test score: %.2f", test_average);

        fflush(stdin);

    }
    return 0;
}

Say I enter 2 students, the first student with 2 test scores, then enter 45 87. I should be getting 66.00, but I'm getting 22.50. For the second student, I'd enter 3 test scores of 100 55 87, and I get 48.33. Waaayyy off.

I know I'm doing something wrong, but I can't figure out, because I had it working before, but the loop wouldn't continue to the second student.

Upvotes: 3

Views: 1766

Answers (3)

user3629249
user3629249

Reputation: 16540

the posted code contains several problems including

  1. can only enter one test score
  2. random mix of int and float and double variables
  3. incorrect format strings for calls to scanf()
  4. a number of unused variables
  5. failure to check for errors on calls to scanf()
  6. poor variable naming. Variable names should indicate content or usage (or better both)
  7. calling fflush(stdin) is specifically listed as undefined behaviour in the C standard
  8. test_sum is not re-initialized between students

The following proposed code fixes all the above problems and compiles cleanly

#include <stdio.h>
#include <stdlib.h>  // exit(),  EXIT_FAILURE

// prototypes
void flushStdin( void );

int main( void )
{
    int  numStudents = 0;
    char studentName[20];
    int  numTests;

    double test_score;
    double test_sum = 0.0;
    //char   letter_grade;
    double test_average;

    printf("Number of students: ");
    if( 1 != scanf("%d", &numStudents) )
    { // then scanf failed
        perror( "scanf for number of students failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf successful

    flushStdin();

    for (int i = 0; i < numStudents; i++)
    {
        printf("\nStudent name %d: ", i + 1);
        if( 1 != scanf(" %s", studentName) )
        { // then scanf failed
            perror( "scanf for student name failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful

        flushStdin();

        printf("Number of test(s) for %s: ", studentName);
        if( 1 != scanf("%d", &numTests) )
        { // scanf failed
            perror( "scanf for number of tests failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful

        test_sum = 0.0;
        printf("Enter %d test score(s) for %s: ", numTests, studentName);
        for( int j=0; j<numTests; j++ )
        {
            if( 1 != scanf("%lf", &test_score) )
            { // then scanf failed
                perror( "scanf for test score failed");
                exit( EXIT_FAILURE );
            }

            // implied else, scanf successful

            flushStdin();

            test_sum += test_score;
        }

        test_average = test_sum / numTests;
        printf("Average test score: %.2lf", test_average);
    }
    return 0;
} // end function: main


void flushStdin()
{
    int ch;
    while( (ch = getchar() ) != EOF && '\n' != ch);
}

Upvotes: 1

al0011
al0011

Reputation: 164

if (i < students) {
     scanf("%f", &test_score);
     test_sum += test_score;
     test_average = test_sum / (float)tests;
}

Should be :

test_sum = 0;
for (int j = 0; j < tests; j++) {
    scanf("%f", &test_score);
    test_sum += test_score;
}
test_average = test_sum / (float)tests;

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249153

You always need to check the return value of scanf() to see how many tokens it read. If it fails to read, you need to take corrective action.

It's not clear why you'd need fflush(stdin) every time.

Upvotes: 1

Related Questions