1

I am doing an assignment. I have done the code but when I look back, I found that I have missed the one entering the score into valid and invalid stack.

So have I tried to modify the code but the modified code will compile but not run. I don't know why. Can someone help me. Thanks a lot.

/*
Question 1
This program uses an array applications.
*/

#include<stdio.h>
#include<stdlib.h>



//declare struct node as STK
struct node
{
    int top;
    int element[100];
};  

struct node *valid,*invalid;//declare two stack for valid score and invalid score


int main()
{

valid->top=-1;//create empty stack for valid score
invalid->top=-1;
int size, score[size]; //variables for array purposes
int tempMin=100, tempMax=0; //variables for lowest and highest marks
int i,total=0,validCounter=0,invalidCounter=0,countH1=0,countH2=0,countH3=0,countH4=0,countH5=0; //variables for counting purposes
float average; //variable for average

printf ("STUDENTS MARK ENTERING SESSION\n");
printf ("Enter total number of student: ");
scanf ("%d", &size);
printf("\n");

/*Get Marks form User*/
printf ("Enter MID-SEMESTER Test Score:\n");

for (i=0;i<size;i++)
{
    printf("Test Score #%d: ",i+1);
    scanf ("%d",&score[i]);
    if((score[i]<0) ||(score[i]>100))
    printf("Error:Invalid score entered!\n");
}

printf ("\nThe MID-SEMESTER Test Score");


for (i=0;i<size;i++)
{
    if ((score[i]>=0) && (score[i]<=100))
    {
        valid->element[++valid->top]=score[i];//write the score into valid stack
        printf("%d ",score[i]);
        total+=score[i];
        validCounter=validCounter+1;

        if (score[i]<=tempMin)
        {
            tempMin=score[i];
        }

        if (score[i]>=tempMax)
        {
            tempMax=score[i];
        }
    }
}
/*Print Valid Score*/
printf ("\n\nValid score: ");
if(valid->top==-1)
printf("Empty valid score stack");
else
{
    for(i=valid->top;i>=0;i--)
    printf("%d\t",valid->element[i]);
    printf("\n");
}


for (i=0;i<size;i++)
{
    if ((score[i]<0) || (score[i]>100))
    {
        invalid->element[++invalid->top]=score[i];//write the score into invalid stack
        printf("%d ",score[i]);
        invalidCounter=invalidCounter+1;
    }
}
/*Print Invalid Score*/
printf ("\nInvalid score: ");
if(invalid->top==-1)
printf("Empty invalid score stack");
else
{
    for(i=invalid->top;i>=0;i--)
    printf("%d\t",invalid->element[i]);
    printf("\n");
}

/*Print Average Score*/
average=total/validCounter;
printf("\nAverage score: %.2f", average);

/*Print Lowest Score*/
printf ("\nLowest score: %d", tempMin);

/*Print Highest Score*/
printf ("\nHighest score: %d", tempMax);

/*Print Histogram*/
for (i=0;i<size;i++)
{
    if ((score[i]>=80) && (score[i]<=100))
    {
        countH1=countH1+1;
    }
    else if ((score[i]>=60) && (score[i]<=79))
    {
        countH2=countH2+1;
    }

    else if ((score[i]>=50) && (score[i]<=59))
    {
        countH3=countH3+1;
    }
    else if ((score[i]>=30) && (score[i]<=49))
    {
        countH4=countH4+1;
    }
    else if ((score[i]>=0) && (score[i]<=29))
    {
        countH5=countH5+1;
    }
}
printf ("\nHistogram: ");
printf ("\n\t[80-100]: %d", countH1);
printf ("\n\t[60-79]:  %d", countH2);
printf ("\n\t[50-59]:  %d", countH3);
printf ("\n\t[30-49]:  %d", countH4);
printf ("\n\t[0-29]:   %d", countH5);

/*Print Number of Invalid Score*/
printf("\nTotal number of invalid score: %d", invalidCounter);
}
Dr Rob Lang
  • 6,659
  • 5
  • 40
  • 60
TeoPeiShen
  • 43
  • 1
  • 7
  • 1
    Welcome to S-O. When posting a question, please include a description about what your code is meant to do and what error you got. – Dr Rob Lang Mar 01 '18 at 10:26
  • `int size, score[size];` here you use the uninitialized variable `size` – Jabberwocky Mar 01 '18 at 10:33
  • And you will have another problem here: `average = total / validCounter;` `total` and `validCounter` are `int`s. Àn `int` divided by an `int` will result in an `int`. You need `average = (float)total / validCounter;` And many more problems: `valid` is an uninitialized pointer. Giving up. – Jabberwocky Mar 01 '18 at 10:36
  • no, the problem is lies on i assigned -1 to top in struct valid and invalid. Before i included the modified code(valid and invalid stack) the code works perfectly. – TeoPeiShen Mar 01 '18 at 11:20

2 Answers2

2

This is enough for your program to invoke Undefined Behaviour:

// 1
struct node *valid,*invalid;//declare two stack for valid score and invalid score


int main()
{

// 2
valid->top=-1;//create empty stack for valid score
invalid->top=-1;

At (1), you declare two pointers to struct node, but let them unintialized. As they have static storage, the compiler will default initialize them to NULL.

At (2), you dereference the NULL pointers which is formally UB.

A quick fix could be:

struct node _valid, _invalid;
struct node valid = &_valid, invalid = &_invalid;

but you should wonder whether the indirection is relevant...

And there are other problems as you have been told in comments:

  • int size, score[size]; uses the uninitialized variable size
  • probably others ...
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • how about this? valid=(struct node *)malloc(sizeof(struct node)); I add this both for struct node valid and invalid but cannot work too. Please explain to me. – TeoPeiShen Mar 01 '18 at 11:23
0

When you want to manipulate on structures pointed by pointers, those structures should exist in the memory.

struct node *valid,*invalid; // Two pointers pointing to NULL

int main()
{
valid->top=-1;    //  run time error: NULL->top (dereferencing NULL)
invalid->top=-1;  //  run time error: NULL->top
//...
}

Possible solution, allocate memory on the heap or stack:

struct node *valid,*invalid; // Two pointers pointing to NULL

int main()
{
    // 1.
    // dynamically allocate memory for the `struct node` structure on the heap:

    valid = malloc(sizeof(struct node)); // no need to do a cast :(struct node *)
    invalid = malloc(sizeof(struct node)); // no need to do a cast :(struct node *)

    valid->top=-1;    // OK
    invalid->top=-1;  // OK
    //...

    // 2. OR use structures allocated on the stack:
    struct node valid_node;
    struct node invalid_node;

    valid = &valid_node;        // initialize pointer to the structure
    invalid = &invalid_node;    // initialize pointer to the structure 

   //....
}

Note: Do I cast the result of malloc?

Another problem which you have is here:

int size, score[size]; //variables for array purposes

scanf ("%d", &size);

size should have a valid value when you declare the int score[size];

Change the code to:

int size;
//..
scanf ("%d", &size);
int score[size]; //variables for array purposes

Edit, answer to the comment question:

The uninitialized local variables get an undefined values during run-time. When you define *valid,*invalid locally they are allocated on the stack. size is put on the stack as well but in different place now!. Since size is not initialized it contains whatever happens to be in that location on the stack. It could be a accidentally a reasonable value, 0or negative value. In your case the random value is no good and program will crash. This is called UB (Undefined Behavior). Defining *valid, *invalid globally does not solve the problem. It was just luck. size must be initialized to the proper value to ensure proper program behavior.

sg7
  • 6,108
  • 2
  • 32
  • 40
  • why dun need to cast (struct node *)? – TeoPeiShen Mar 01 '18 at 12:01
  • Btw, I found that when i declare struct node *valid locally(means inside the int main())the code crash and cannot work. Did you know why? – TeoPeiShen Mar 01 '18 at 12:20
  • The crash has nothing to do with pointers declared inside. It is related to undefined `size` of the array `score`. When `score[size]`; is define `size` is unknown. – sg7 Mar 01 '18 at 13:09
  • you are right. the program works well after declare score[size] after getting the size value. But how come i declare struct node *valid,*invalid globally also solve the problem. Please enlighten me. Thanks for your help. you are better than my lousy tutor. – TeoPeiShen Mar 02 '18 at 09:21
  • @TeoPeiShen Thanks! I put the explanation in the answer. It is too long for the comment box. – sg7 Mar 02 '18 at 13:18
  • Thanks you. Maybe it is a luck that program did not crash. – TeoPeiShen Mar 03 '18 at 14:24
  • @TeoPeiShen Yes, It is just a luck! And, if you value my help you can upvote my answer and accept it. I would appreciate it. Thanks! – sg7 Mar 03 '18 at 14:27
  • @TeoPeiShen You did it! Also you can click the ^ arrow. Thanks! – sg7 Mar 03 '18 at 15:17