Thread: Loop Error with program HELP!!!!!

  1. #1
    Registered User
    Join Date
    Jun 2017
    Posts
    2

    Loop Error with program HELP!!!!!

    While loop is not looping the amount of times the user enters and when calculating average grade the output is incorrect. please tell me what I'm doing incorrectly?



    Code:
    #include <stdio.h>
    
    int main(void)
    
    {
    
    /* Declaration of Variables */
    /*--------------------------*/
    
        int    grade_counter = 0, counter[11], n = 0, i = 2;
        float  grade[100], sum = 0.0, average;
        char c;
    
    /* Output purpose of program being to calculate averages of user input grades */
    /*----------------------------------------------------------------------------*/
    
    printf("\nThis program will calculate the average of the grades you enter!\n");
    
    /* Prompt user to enter total number of grades user wishes to average */
    /*--------------------------------------------------------------------*/
    
        while(grade_counter <1 || grade_counter >10)
        {
            counter[i] = -1;
    printf("\nTo begin, please enter the total number of grades to process (1-10): ");
            scanf("%d", &grade_counter);
            while((c = getchar() != '\n') && c != EOF);
    
    /* Ensure grad is between 1 and 100. If not reprompt. */
    /*----------------------------------------------------*/
    
            if(grade_counter <1 || grade_counter >10)
    printf("*** Invalid Total Entered ***\n");
            else
                ++counter[grade_counter];
        }
    
    /* Instruct user to enter user specified number of grades and then prompt for grade to be averaged */
    /*-------------------------------------------------------------------------------------------------*/
    
    printf("\nNow enter the %i grades to be averaged.\n", grade_counter);
    
    printf("\nEnter grade #%i (0-100): ",n+=1);
        scanf("%f", &grade[n]);
        while(( c=getchar() != '\n') && c != EOF);
    
        while(n = 1, n = grade_counter, ++n, grade_counter++ < 10)
        {
            sum += grade[n];
    printf("\nEnter grade #%i (0-100): ", i++);
            scanf("%f", &grade[n]);
            while(( c=getchar() != '\n') && c != EOF);
    
    /* Ensure grad is between 1 and 100. If not reprompt. */
    /*----------------------------------------------------*/
    
            if(grade[n] <0 || grade[n] >100)
            {
    printf("*** Invalid Grade Entry ***.\n");
                continue;
            }
    
            grade_counter++;
    
        }
    
        average = sum / grade_counter;
    printf("The average of the %i grades entered is %f.", grade_counter, average);
    
        if(average >= 90)
    printf("You have a letter grade of A.\n");
        else if (average >=80)
    printf("You have a letter grade of B.\n");
        else if (average >=70)
    printf("You have a letter grade of C.\n");
        else if (average >=60)
    printf("You have a letter grade of D.\n");
        else
    printf("You have a letter grade of E.\n");
    
        getchar();
    }
    Last edited by Salem; 06-26-2017 at 12:20 AM. Reason: removed train-wreck font/color abuse

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > counter[i] = -1;
    What is i here?
    As far as I can see, it's the only place you use i, and it's value is 2.
    So one counter is always being reset to -1.

    > ++counter[grade_counter];
    All the other counters are garbage when you increment them.

    TIP: initialise all your arrays to 0 by doing the following.
    Code:
    int counter[11] = { 0 };
    > while(n = 1, n = grade_counter, ++n, grade_counter++ < 10)
    Write out in words what you think this is doing.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2017
    Location
    Quetzaltenango
    Posts
    82
    Quote Originally Posted by TechyTaf View Post
    While loop is not looping the amount of times the user enters and when calculating average grade the output is incorrect. please tell me what I'm doing incorrectly?
    You don't need the
    Code:
    int counter[11];
    int i = 2;
    char c;
    or any getchar();

    I suggest one for loop for filling your grade array, and another for loop for computing the average.

    If you separate the data entry validation into functions, it will simplify main(), making it much easier to understand.

    In my working version of this program, I have these functions:
    Code:
    int get_valid_grade_counter();
    float get_valid_score(int n);
    int calculate_letter_grade(float average);
    My main() has 29 lines of code, 9 of which are printf() and 4 lines of comments. I was going to post the for loops, but if vBulletin has a spoiler tag, I don't know what it is.

  4. #4
    Registered User
    Join Date
    Apr 2017
    Location
    Quetzaltenango
    Posts
    82
    Quote Originally Posted by Salem View Post
    >
    TIP: initialise all your arrays to 0 by doing the following.
    Code:
    int counter[11] = { 0 };
    That is interesting that the unspecified values are initialized to zero when you only specify the zeroth one.

    But I think the only array he needs is one to hold the grade scores. And since the user will be inputting all those, there is no need to initialize them.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > That is interesting that the unspecified values are initialized to zero when you only specify the zeroth one.
    Initialisers work like this.
    Code:
    int counter[11];  // you have 11 integers of junk
    int counter[11] = { 0 };  // you have 11 integers, all zero
    int counter[11] = { 1, 2, 3, 4, 5 };  // the remaining six values are zero.
    > But I think the only array he needs is one to hold the grade scores. And since the user will be inputting all those, there is no need to initialize them.
    Quite possibly, but the cost of initialising them is tiny compared to the amount of time wasted bug-hunting when things go pear shaped.

    Initialising things out of habit makes for a much more predictable programming life later on.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Apr 2017
    Location
    Quetzaltenango
    Posts
    82
    Quote Originally Posted by Salem View Post
    >
    Initialising things out of habit makes for a much more predictable programming life later on.
    Code:
    #include <stdio.h>
    int main(void) {
      int a = 0;
      int b;
    
    
      putchar(a);
      putchar(b);
    }
    
    cc -ggdb -Wall -Wextra -Wpedantic -std=gnu99 -O0    initial.c   -o initial
    initial.c: In function ‘main’:
    initial.c:7:3: warning: ‘b’ is used uninitialized in this function [-Wuninitialized]
       putchar(b);
       ^

    I think it better to only initialize to something that I intend the use. That way the compiler can warn me if I missed something, like in the putchar(b). In the putchar(a), I have hidden my error from the compiler.

  7. #7
    Registered User
    Join Date
    Apr 2017
    Location
    Quetzaltenango
    Posts
    82
    Quote Originally Posted by christophergray View Post
    or any getchar();
    I was wrong about this. I have
    Code:
        //dispose of non-numeric and bad input    
    char ch;
    while ((ch = getchar()) != '\n')
      putchar(ch);
    in my program.

    Code:
    int get_valid_grade_counter();
    int get_valid_grade_counter(void);

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by christophergray View Post
    I think it better to only initialize to something that I intend the use. That way the compiler can warn me if I missed something, like in the putchar(b). In the putchar(a), I have hidden my error from the compiler.
    The compiler can tell you that you initialized things you didn't use as well:
    Code:
    #include <stdio.h>
    
    int main(void) {
        int a = 'a', b = 'b';
        putchar(a);
        return 0;
    }
    
    C:\Users\jk>gcc -c -Wall  sandbox.c
    sandbox.c: In function 'main':
    sandbox.c:4:15: warning: unused variable 'b' [-Wunused-variable]
      int a = 'a', b = 'b';
    I guess you could say that there are always ways to hide your mistakes from the compiler. To offer a different perspective on this though, initialization leads to predictable code, which leads to bugs that can be reproduced and subsequently fixed.

    Not nulling pointers for example can lead to double free exploits...
    Last edited by whiteflags; 07-14-2017 at 12:27 AM. Reason: better quality link found

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > I think it better to only initialize to something that I intend the use.
    How about only declaring things you intend to use?

    If you didn't intend to use either a or b, then at least you would always get a consistent \0 in your output.

    Only you (the programmer) can decide that putchar(a) is actually wrong, but at least the result will be consistently wrong. That much gives you something to work with when trying to debug the damn thing.

    Anybody going to the trouble of using -Wall -Wextra -Wpedantic wouldn't be writing that kind of sloppy code to begin with.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Apr 2017
    Location
    Quetzaltenango
    Posts
    82
    whiteflags wrote:
    >initialization leads to predictable code, which leads to bugs that can be reproduced and subsequently fixed.


    Salem wrote:
    >but at least the result will be consistently wrong


    Hmm. Maybe I haven't had problems debugging because I haven't worked on any sizeable programs yet. I have only written little snippets of programs that are exercises in my textbook. It certainly makes sense that to fix a bug, you have to reproduce it.


    It turns out that because of my habit of putting my variable declarations close to the first use of the variable, that I am usually initializing them. For example:
    Code:
     
      // Prompt for grades to be averaged
      printf("\nNow enter the %d grade", GRADE_COUNTER);
      printf("%s", 1 == GRADE_COUNTER ? "": "s");
      printf(" to be averaged.\n\n");
      float get_valid_score(int);
      float grade[GRADE_COUNTER];
      for (int n = 0; n < GRADE_COUNTER; n++) 
        grade[n] = get_valid_score(n);
    
      // Compute average
      float sum = grade[0];
      for (int n = 1; n < GRADE_COUNTER; n++)
        sum += grade[n];
      assert((int)sum <= 100 * GRADE_COUNTER);
      const float AVERAGE = sum / GRADE_COUNTER;
    Last edited by christophergray; 07-14-2017 at 12:17 PM. Reason: repair display of code

  11. #11
    Registered User
    Join Date
    Apr 2017
    Location
    Quetzaltenango
    Posts
    82
    Quote Originally Posted by whiteflags View Post
    Not nulling pointers for example can lead to double free exploits...
    I am working through Steve Prata's C Primer Plus, 6 ed. Just started chapter 9, and malloc isn't mentioned until chapter 12. So I don't understand this example. But I bookmarked it to look at it after I finish chapter 12.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Loop Error with program HELP!!!!!
    By TechyTaf in forum C Programming
    Replies: 1
    Last Post: 06-26-2017, 12:18 AM
  2. Replies: 1
    Last Post: 03-27-2017, 08:05 PM
  3. Program using while loop, swtich, and for loop
    By Tre Holland in forum C Programming
    Replies: 5
    Last Post: 11-04-2014, 12:03 AM
  4. Replies: 3
    Last Post: 08-21-2012, 11:50 PM
  5. Replies: 10
    Last Post: 09-24-2010, 01:09 AM

Tags for this Thread