Ilan Aizelman WS
Ilan Aizelman WS

Reputation: 1632

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.");
}

Upvotes: 2

Views: 183

Answers (2)

Bob__
Bob__

Reputation: 12779

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

Upvotes: 2

user5455540
user5455540

Reputation:

It worked for me. All i did was using

_flushall();

instead of

flushall();

Upvotes: 1

Related Questions