Having a fatal error code - corrupted heap - c

New picture from an external compiler.. the exit code is ok?
enter image description here
This is the full code. I'm having a trouble program blows away after printing the wanted output to the screen. I guess it's a problem with the way I allocated memory for the array of structs, and the .name field of each struct in a for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
rewind(stdin);
gets(str);
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
scanf_s("%d", &p[i].marks[j]);
}
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
int i, sum=0;
for (i = 0; i < 4; i++)
sum += s->marks[i];
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
if ((s->avg) > 85)
Print_One(s);
}

Gonna point out everything fishy I see for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
// This is wrong. Remove the &...
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
// Consider checking size for a sane value.
// Ok, allocate an array of students.
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
// These 2 lines scare the heck out of me. I'd really do this differently.
// gets is the devil and the see:
// https://stackoverflow.com/questions/20052657/reversing-stdin-in-c
// for why this may not work well.
rewind(stdin);
gets(str);
// What if str is not a terminated string? Then 1 char of 0? Guess this is ok. Hope it doesn't overflow on the copy below though (consider fixed max size and not using a temporary)
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
// Do a fast copy of up to 50 chars. I'd really want to verify this output to be sure it works.
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
// Hope this inputs the way you want.
scanf_s("%d", &p[i].marks[j]);
}
// This should work, but I prefer more explicit pointers.
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
// What if s is Null?
int i, sum=0;
// 4 is a magic number. Make this a constant.
for (i = 0; i < 4; i++)
sum += s->marks[i];
// This won't be as accurate as you want. Consider an integer solution.
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
// What if s is Null? What about s->name?
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
// What if s is Null?
if ((s->avg) > 85)
Print_One(s);
}
Note: While going through this code, I did not see any "red flags" except for the & on the size and perhaps the gets/rewind calls. I'd still add null asserts to your functions and also walk through it with a debugger to be sure that everything is as you expect. Honestly, there is enough going on here that I'd prefer the debugger help to my quick trace of the code while I was writing comments.
Update
If I change all your scanf_s to scanf() calls, replace your gets() / rewind() calls to a simple scanf("%s", str) call, and change your funky strcpy_s() function to a simpler strcpy() or strncpy() call, your program does not seem to crash for me. My money is that the strcpy_s() call is corrupting RAM while doing its "fast" copy.

Related

C - numbers not entering in the "if condition", dont know why

So, basically, I was instructed to make a function that asks the user for a size, and then creates an array with elements chosen by the user...
for example: size:4 , input:10 20 30 40, created array = {10,20,30,40}.
Then next step the user is to apply some function for this created array. Example:
For example, if the user chooses letter 'A' the function "add1" will be applied and all elements of the array will be increased in one unit, so with an input example of {10,20,30,40}, the output will be {11,21,31,41}.
My code is not working, why? Someone can help me? I've used the debugger and the function is not entering in the "if condition".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* add1(int* array, int size)
{
int *novo;
novo = malloc(size*sizeof(int));
for (int i = 0; i < size; i++){
*(novo + (i)) = *(array + i)+1;
}
return novo;
};
int* add2(int* array, int size)
{
int *novo;
novo = malloc(size*sizeof(int));
for (int i = 0; i < size; i++){
*(novo + (i)) = *(array + i)+2;
}
return novo;
};
void print1(int* array, int size)
{
for (int i = 0; i < size; i++)
{
printf("%i\n", *(array+i));
}
};
int main(void)
{ int i, elemento, size;
char *new;
printf("Insert Size:\n");
scanf("%i", &size);
int newArray[size];
printf("Insert Elements:\n");
for (i = 0; i < size; i++)
{
scanf("%i", &elemento);
newArray[i] = elemento;
}
printf("Select option:\n");
scanf(" %c", &new);
if (new == 'A') {
int* result;
result = add1(&newArray, size);
print1(result, size);
} else if (new == 'B') {
int* result;
result = add2(&newArray, size);
print1(result, size);
} else if (new == 'C') {
} else if (new == 'D') {
}
}
Change:
char *new;
to
char new;
as
scanf(" %c", &new);
is expecting a character and as the code stands new is an undefined character pointer. So passing a pointer to a undefined pointer is not good.
PLEASE SWITCH ON YOUR COMPILER WARNINGS AND THIS WOULD BE PICKED UP!
new is not a good variable name. As it leads to confusion with C++ keyword
Check the return values for scanf- see the manual page for that
Perhaps using switch instead of if new == 'A' .....

C strcmp segmentation fault

#include <string.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct bank
{
char an;
char name;
char type;
int bal;
};
int main()
{
int i=0,n;
printf("Enter the number of accounts\n");
scanf("%d",&n);
struct bank a[n];
printf("Enter the details of the users\n");
for(i=0;i<n;i++)
{
scanf("%s%s%s%d",a[i].an,a[i].name,a[i].type,&a[i].bal);
}
printf("The details of the users are\n");
for(i=0;i<n;i++)
{printf("%s\n%s\n%s\n%d\n\n",a[i].an,a[i].name,a[i].type,a[i].bal);}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s",atype);
char typ[10];
char s[]="savings";
char c[]="current";
int result,res1,res2;
result = strcmp(atype,s);
if(result == 0)
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res1 = strcmp(typ,s);
if(res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
} else
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res2 = strcmp(typ,c);
if(res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
}
}
so basically ik its my homework but i did everythimg and i still cannot resolve the segmentation fault.please help
i think its something to do with strcmp() function but oh well
i checked all the sources but couldnt really find any fix.
any help would be appreciated.
For starters:
This
typ[10] = ...
accesses typ one past its valid memory. This invokes undefined behaviour, so anything can happen from then on.
In C array indexing is 0-based. So for char[10] the highest allowed index would be 9. Access the 1st element would be done by using 0.
You have made 2 mistakes here .
First your struct bank declaration was wrong. You forgot to declare name an and type as string. You declared it as just character(char).It should be like :-
struct bank
{
char an[100]; // assuming 100 is max size of input strings
char name[100];
char type[100];
int bal;
};
second you cannot do typ[10] = a[i].type; you should use strcpy() Something like this :-
strcpy(typ,a[i].type);
So this corrected code will work :-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct bank // change made 1
{
char an[100];
char name[100];
char type[100];
int bal;
};
int main()
{
int i = 0, n;
printf("Enter the number of accounts\n");
scanf("%d", &n);
struct bank a[n];
printf("Enter the details of the users\n");
for (i = 0; i < n; i++)
{
scanf("%s%s%s%d", a[i].an, a[i].name, a[i].type, &a[i].bal);
}
printf("The details of the users are\n");
for (i = 0; i < n; i++)
{
printf("%s\n%s\n%s\n%d\n\n", a[i].an, a[i].name, a[i].type, a[i].bal);
}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s", atype);
char typ[10];
char s[] = "savings";
char c[] = "current";
int result, res1, res2;
result = strcmp(atype, s);
if (result == 0)
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 2
res1 = strcmp(typ, s);
if (res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
else
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 3
res2 = strcmp(typ, c);
if (res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
}
So your mistake was not with strcmp()

How can I create a dynamic array in a procedure in C?

I'm new to this fantastic site and I found it very useful in many occasions, but now I'm dealing with a problem which I can't seem to solve.
I'm a beginner C student and I'm studying dynamic memory allocation.
I want to create a dynamic array of, let's say, integers, allocating memory for it inside a procedure, not in the main function.
This works:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *numbers; // pointer to create a dynamic array
int *test; // pointer to test realloc function
int c;
size_t i = 0;
unsigned int dim; // array's length
// allocate memory for the 1st number
numbers = malloc(sizeof(*numbers));
if (numbers == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
printf("Insert the 1 number: ");
scanf("%d", &numbers[0]);
++i;
/* allocate memory for the other numbers,
* until the user inputs EOF
*/
while (!feof(stdin)) {
test = realloc(numbers, (sizeof(*numbers) * (i + 1)));
if (test == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
numbers = test;
printf("Insert the %u number: ", i + 1);
scanf("%d", &numbers[i]);
++i;
}
}
dim = --i;
// print the array, 5 numbers per line
for (i = 0; i < dim; ++i) {
if (i % 5 == 0) {
puts("");
}
printf("%d ", numbers[i]);
}
puts("");
}
getchar();
return 0;
}
But I want to do this (which doesn't work):
#include <stdio.h>
#include <stdlib.h>
void get_numbers(int **numbers, unsigned int *dim);
int main()
{
int *numbers; // pointer to create a dynamic array
size_t i = 0;
unsigned int dim; // array's length
get_numbers(&numbers, &dim);
// print the array, 5 numbers per line
for (i = 0; i < dim; ++i) {
if (i % 5 == 0) {
puts("");
}
printf("%d ", numbers[i]);
}
puts("");
getchar();
return 0;
}
void get_numbers(int **numbers, unsigned int *dim)
{
int *test; // pointer to test realloc function
int c;
size_t i = 0;
// allocate memory for the 1st number
*numbers = malloc(sizeof(*numbers));
if (*numbers == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
printf("Insert the 1 number: ");
scanf("%d", &numbers[0]); // Maybe the error is here
++i;
/* allocate memory for the other numbers,
* until the user inputs EOF
*/
while (!feof(stdin)) {
test = realloc(*numbers, (sizeof(*numbers) * (i + 1)));
if (test == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
*numbers = test;
printf("Insert the %u number: ", i + 1);
scanf("%d", &numbers[i]);
++i;
}
}
*dim = --i;
}
}
Do I need to use a pointer to a pointer to int, right?
I know I made some mistakes but I can't figure out how to fix them.
Thanks in advance for your replies!
Bye,
Fabio Nardelli
In the first block of code, numbers is of type int*.
In the second block of code, numbers is of type int**.
You have not fixed all the places that need to be fixed because of that change.
My suggestion:
Change the input argument to numbersPtr.
Create a local variable int* numbers.
Before you return from the function, set *numbersPtr to number.
void get_numbers(int **numbersPtr, unsigned int *dim)
{
int* numbers;
...
*numbersPtr = numbers;
}
It will be better to change get_numbers to return numbers.
int* get_numbers(unsigned int *dim)
{
int* numbers;
...
return numbers;
}
and change its usage as:
numbers = get_numbers(&dim);

get name and marks of students with structs

I've got a task to get no. of students, get their name and marks and output the students which has average over 85.
The problem: After I enter blabla 99 98 95 90, I don't get the appropriate message. what I get is just some kind random of average instead. I mean, Print_One() isn't executed after that input. (Failing to print the average above 85)
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
typedef struct {
char *name;
int marks[4];
float avg;
} student;
student *Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void exStudents(student *s, int size);
int main() {
int size, i;
student *arr;
printf("\nEnter the number of students: \n");
scanf("%d", &size);
arr = Create_Class(size);
exStudents(arr, size);
for (i = 0; i < size; i++)
free(arr[i].name);
free(arr);
getch();
}
student *Create_Class(int size) {
int i, j;
int idStud, nameStud, markStud;
student *classStudent;
classStudent = (student*)malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
int sizeOfName;
printf("Please enter your name: \n");
flushall();
gets(classStudent[i].name);
sizeOfName = strlen(classStudent[i].name);
/*
if (classStudent[i].name > 50) {
classStudent[i].name = realloc(classStudent[i].name, 51);
classStudent[i].name[51] = '\0';
} else {
classStudent[i].name = realloc(classStudent[i].name, sizeOfName + 1);
}
*/
printf("Please enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
void Avg_Mark(student *s) {
int i, numOfMarks = 4, sum = 0;
for (i = 0; i < numOfMarks; i++) {
sum += s->marks[i];
}
s->avg = (sum / 4.0);
}
void Print_One(student *s) {
printf("The average of %s is %f", s->name, s->avg);
}
void exStudents(student *s, int size) {
int flag = 1;
while (size > 0) {
if (s->avg > 85) {
Print_One(s);
flag = 0;
}
s++;
size--;
}
if (flag)
printf("\n There're no students with above 85 average.");
}
If your input is like this:
1
blabla
99 98 95 90
The first newline after 1 is still in the input buffer when your program reaches get, so an empty line is read and then the scanfs will fail.
An easy fix could be to read the first number using this format:
scanf("%d ", &size);
// note ^ the space will consume the newline
But, as #chqrlie pointed out, "it will continue to read bytes from stdin until it sees one that is not whitespace. This will require the user to respond to the next question before the prompt is written."
A better idea is to read the name using another scanf, but limiting the maxium number of chars read to the allocated size and adding a space at the beginning of the format string to consume all pending whitespaces:
// read max 50 char till a newline and extract the rest of line without storing it
scanf(" %50[^\n]%*[^\n]", classStudent[i].name);
// ^^^ a space at the beginning will also consume trailing spaces or newline
It worked for me. All i did was using
_flushall();
instead of
flushall();

Why I can't input my name with gets?

Here's the part of my code:
Problem: It skips the input of "please enter your name" to "please enter your marks"
What I tried: flushall(); _flushall(); - which worked yesterday somehow, and trying to place these functions between printf,scanf..
student *Create_Class(int size) {
int i, j;
int idStud, nameStud, markStud;
student *classStudent;
classStudent = (student*)malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
printf("Please enter your name: ");
gets(classStudent[i].name);
_flushall(); //tried _flushall() and it worked yesterday.. tried fflush(NULL) too.
printf("\nPlease enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
EDIT: (FULL CODE)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
typedef struct {
char *name;
int marks[4];
float avg;
} student;
student *Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void exStudents(student *s, int size);
int main() {
int size, i;
student *arr;
printf("\nEnter the number of students: \n");
scanf("%d", &size);
arr = Create_Class(size);
exStudents(arr, size);
for (i = 0; i < size; i++)
free(arr[i].name);
free(arr);
getch();
}
student *Create_Class(int size) {
int i, j;
int idStud, nameStud, markStud;
student *classStudent;
classStudent = (student*)malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
int sizeOfName;
printf("Please enter your name: \n");
_flushall();
fgets(classStudent[i].name,50,stdin);
sizeOfName = strlen(classStudent[i].name);
printf("Please enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
void Avg_Mark(student *s) {
int i, numOfMarks = 4, sum = 0;
for (i = 0; i < numOfMarks; i++) {
sum += s->marks[i];
}
s->avg = (sum / 4.0);
}
void Print_One(student *s) {
printf("The average of %s is %f", s->name, s->avg);
}
void exStudents(student *s, int size) {
int flag = 1;
while (size > 0) {
if (s->avg > 85) {
Print_One(s);
flag = 0;
}
s++;
size--;
}
if (flag)
printf("\n There're no students with above 85 average.");
}
As you have already been told in comments, the solution is to use a two-step approach: Read lines first, then scan these lines as appropriate. This reflects how users are going to answer your prompts, namely by providing the information and then hitting enter.
Here's a variant of your code which does that. I've also changed the main function, because it also used scanf and I've added a function to strip white space from the string input by fgets. (This function requires the <ctype.h> header.)
#include <ctype.h>
int main()
{
char line[80];
int size, i;
puts("Enter the number of students:");
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
if (sscanf(line, "%d", &size) == 1 && size > 0) {
student *arr = Create_Class(size);
exStudents(arr, size);
for (i = 0; i < size; i++) free(arr[i].name);
free(arr);
}
return 0;
}
/*
* strip white space from beginning and end of string
*/
char *strip(char *str)
{
size_t l = strlen(str);
while (l > 0 && isspace((unsigned char) str[l - 1])) l--;
str[l] = '\0';
while (isspace((unsigned char) *str)) str++;
return str;
}
/*
* Create students and prompt user for input
*/
student *Create_Class(int size)
{
int i;
student *classStudent = malloc(size * sizeof(student));
for (i = 0; i < size; i++) {
char line[80];
char *p;
int okay = 0;
puts("Please enter your name:");
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
p = strip(line);
classStudent[i].name = malloc(strlen(p) + 1);
strcpy(classStudent[i].name, p);
while (!okay) {
int j = 0;
okay = 1;
puts("Please enter 4 marks:");
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
p = line;
while (p && j < 4) {
char *tail;
int m = strtol(p, &tail, 10);
if (p == tail) break;
if (m < 1 || m > 100) {
puts("Illegal mark.");
okay = 0;
}
classStudent[i].marks[j++] = m;
p = tail;
}
if (j < 4) {
printf("Expected 4 marks, but got %d.\n", j);
okay = 0;
}
}
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
Please refrain from flushing buffers wihout reason. When a new-line character is written, stdout is flushed, so make it a rule to terminate all your strings with a new-line. New-lines at the beginning of strings instead of at the end are a sign of untidy output.
SOLUTION:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
typedef struct { //struct decleration
char *name;
int marks[4];
float avg;
} student;
//functions decleration
student *Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void exStudents(student *s, int size);
int main() {
/*variable declerations*/
int i, size;
char line[80];
student *arr;
/*Input number of students*/
printf("\nEnter the number of students: \n");
fgets(line, sizeof(line), stdin);
sscanf(line, "%d", &size);
/*Get name of students, marks, and calculate average above 85*/
arr = Create_Class(size);
exStudents(arr, size);
/*Free memory*/
for (i = 0; i < size; i++)
free(arr[i].name);
free(arr);
getch();
}
student *Create_Class(int size) { /*Get names of each student, and their 4 marks.*/
/*Variable declerations*/
int i, j;
char line[51];
student *classStudent;
/*Dynamic allocation to assign structure to every student*/
classStudent = (student*)malloc(size * sizeof(student));
/*Get name of students and their 4 marks*/
for (i = 0; i < size; i++) {
/*Variable decleration and dynamic allocation of 51 chars*/
classStudent[i].name = (char*)malloc(51 * sizeof(char));
int numOfmarks = 4;
int sizeOfName;
/*Input name of student*/
printf("Please enter your name: \n");
scanf("%s", classStudent[i].name);
/*Input marks of student*/
printf("Please enter 4 marks: ");
for (j = 0; j < numOfmarks; j++) {
scanf("%d", &classStudent[i].marks[j]);
}
/*Calculate average, and print averages of students above 85*/
Avg_Mark(&classStudent[i]);
}
return classStudent;
}
/*Calculate averages of students*/
void Avg_Mark(student *s) {
int i, numOfMarks = 4, sum = 0;
for (i = 0; i < numOfMarks; i++) {
sum += s->marks[i];
}
s->avg = (sum / 4.0);
}
/*Print average (if bigger than 85)*/
void Print_One(student *s) {
printf("The average of %s is %0.1f\n", s->name, s->avg);
}
/*Check whether the average is bigger than 85*/
void exStudents(student *s, int size) {
int flag = 1; //flag to check if there are any students with avg above 85
while (size > 0) {
if (s->avg > 85) {
Print_One(s); //Print the average
flag = 0; //We found atleast one student with avg > 85
}
s++; //Advance to next student
size--;
}
if (flag)
printf("\n There're no students with above 85 average.");
}
The problem in your code is that scanf does not consume the new-line returned by the user in:
scanf("%d", &size);
So when the program reaches:
fgets(classStudent[i].name,50,stdin);
the remaining new-line in stdin is received before the user can type anything.
A solution is to replace the initial scanf call by fgets and atoi calls.
char size_str[5];
fgets(size_str,5,stdin);
size = atoi(size_str);
A combination of fgets and sscanf also works also fine in general to first process user inputs and then convert it.
The variant with sscanf is:
char size_str[5];
fgets(size_str,5,stdin);
sscanf(size_str,"%d\n",&size);
Note that it might be safe to stop the program if the value entered is too large. Here we allow from 0 up to 999.
Note also that you have to do the same change some lines below.
instead of:
scanf("%d", &classStudent[i].marks[j]);
write:
char mark_str[5];
fgets(mark_str,5,stdin);
sscanf(mark_str,"%d\n",&classStudent[i].marks[j]);
Hope this helps.

Resources