0

Trying to make a program that prints data entered into a file.

Everything is working all and good apart from the Calculating Average for marks entered.

I can't seem to figure out how to do it, even though it should be simple I just cant get my head around it.

The error I am currently getting is:

"temp->mark = temp->mark + studentArray[j];" (Invlalid operands to 
 binary + (have 'float' and 'char *').

Much appreciated if someone could help me. I have tried the following

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

struct student{
    char name[30];
    int id;
    float mark;
};

int count = 0;
void student_update(char *stuadd);
void display(char *stuadd);

void main(int argc, char *studentArray[100])
{
    int choice;
    while(1)
    {
        printf("Welcome to Student Archives\n\n");
        printf("1. Display Students' Details\n");
        printf("2. Calculate average of all students’ marks \n");
        printf("3. Add new student to the record \n");
        printf("4. Quit Program\n");
        scanf("%d",&choice);

        switch(choice)
        {
        case 1:display(studentArray[100]);
            break;
        case 2:
            break;
        case 3:
            student_update(studentArray[100]);
            break;
        case 4: printf("Program Terminated.\n"); 
            exit(0);
        default: printf("Wrong Choice. Enter again\n");
            break;
        }
    }
}

void display(char *stuadd)
{
    FILE *fptr;
    char ch;
    int rec = count;
    fptr = fopen("stuadd.txt", "r");
    struct student *temp = (struct student *)malloc(sizeof(struct student));
    if (fptr == NULL)
        printf("File does not exist.");
    else
    {
        while (rec)
        {            
            fread(temp->name, 50, 1, fptr);
            printf(" %s\n", temp->name);
            fread(&temp->id, sizeof(int), 1, fptr);
            printf("%d", temp->id);
            fread(&temp->mark, sizeof(int), 1, fptr);
            printf("%.2f", temp->mark);

            rec--;
        }
    }
    fclose(fptr);
    free(temp);
    free(temp->name);
}

void calculateAverage(char *studentArray[100])
{
    struct student *temp = (struct student *)malloc(sizeof(struct student));
    int j;
    float avg;

    temp->mark  = avg = 0;

    for(j = 0; j < 100; j++)
    {
        temp->mark = temp->mark + studentArray[j];
    }

    avg = (float)temp->mark / j;

    printf("Average of students' total marks are: %.2f",avg);
}

void student_update(char *stuadd)
{
    FILE *fptr;
    fptr = fopen("stuadd.txt", "a+");
    struct student *temp = (struct student *)malloc(sizeof(struct student));

    if (fptr == NULL)
        printf("\nError.");
    else
    {
        printf("\nEnter the students' name\n");
        scanf(" %[^\n]s", temp->name);

        printf("Enter the students' ID\n");
        scanf("%d", &temp->id);

        printf("Enter the students' mark\n");
        scanf("%f", &temp->mark);

        fprintf(fptr, "%s %d %.2f", temp->name, temp->id, temp->mark);

        count++;
    }

    fclose(fptr);
    free(temp);
    free(temp->name);
}
David C. Rankin
  • 69,681
  • 6
  • 44
  • 72
Deano
  • 19
  • 4
  • 4
    We can start with basics, `void main(int argc, char *studentArray[100])` is an invalid invocation of `main()`, The proper declarations for `main` are `int main (void)` and `int main (int argc, char **argv)` (which you will see written with the equivalent `char *argv[]`). **note:** `main` is a function of `type int` and it returns a value. See: [C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570)](http://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.1p1). See also: [See What should main() return in C and C++?](http://stackoverflow.com/questions/204476/) – David C. Rankin Aug 04 '18 at 03:52
  • 1
    Your `stuadd` variables are unused. – melpomene Aug 04 '18 at 04:04
  • 2
    `free(temp); ... temp->name` has undefined behavior. You're accessing elements of a freed structure. – melpomene Aug 04 '18 at 04:05
  • 2
    `free(temp->name);` has undefined behavior. `temp->name` is an array, not a pointer (and it was not returned from `malloc`). – melpomene Aug 04 '18 at 04:06
  • 2
    `sizeof(int)` is the wrong number of bytes to read into a variable of type `float` (`temp->mark`). – melpomene Aug 04 '18 at 04:06
  • 2
    You `fclose(fptr)` even if the open failed and `fptr` is null, which I'm pretty sure has undefined behavior, too. – melpomene Aug 04 '18 at 04:08
  • 2
    Did you intend `studentArray` to be an array of students? Because that's not what it is in your code. – melpomene Aug 04 '18 at 04:09
  • 2
    It's a pretty long list, not to mention if somebody happens to enter `"one"` as the `choice`... Keep that `[Ctrl+C]` handy.. The use of `fread` is problematic instead of `fgets` and then parsing with `sscanf` (or just reading/validating the space-separated-values with `fscanf`) given how they are written to file with `fprintf`... – David C. Rankin Aug 04 '18 at 04:13

1 Answers1

3

The posted code does not compile!

under ubuntu linux, using:

gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" (in directory: /home/richard/Documents/forum)

the compiler outputs the following:

untitled.c:16:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 void main(int argc, char *studentArray[100])
      ^~~~

untitled.c: In function ‘main’:
untitled.c:16:15: warning: unused parameter ‘argc’ [-Wunused-parameter]
 void main(int argc, char *studentArray[100])
               ^~~~

untitled.c: In function ‘display’:
untitled.c:48:10: warning: unused variable ‘ch’ [-Wunused-variable]
     char ch;
          ^~

untitled.c:45:20: warning: unused parameter ‘stuadd’ [-Wunused-parameter]
 void display(char *stuadd)
                    ^~~~~~

untitled.c: In function ‘calculateAverage’:
untitled.c:83:33: error: invalid operands to binary + (have ‘float’ and ‘char *’)
         temp->mark = temp->mark + studentArray[j];
                      ~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~

untitled.c:86:29: warning: conversion to ‘float’ from ‘int’ may alter its value [-Wconversion]
     avg = (float)temp->mark / j;
                             ^

untitled.c: In function ‘student_update’:
untitled.c:91:27: warning: unused parameter ‘stuadd’ [-Wunused-parameter]
 void student_update(char *stuadd)
                           ^~~~~~

Compilation failed.

There are some other problems, like:

free(temp);
free(temp->name);

That is accessing a pointer into allocated memory after the allocated memory has been passed to free() The result is indefined behavior. Suggest:

free(temp->name);
free(temp);

Regarding the following statements

FILE *fptr;
fptr = fopen("stuadd.txt", "a+");
struct student *temp = (struct student *)malloc(sizeof(struct student));

if (fptr == NULL)
    printf("\nError.");

Always check for an error indication immediately after the call to the C library function.

output error messages to stderr, not stdout

When the error indication is from a C library function, then immediately call perror(); to output both your error message AND the text reason the system thinks the error occurred, all to stderr

when calling any of the heap allocation functions: malloc calloc realloc, 1) the returned type is void* which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. 2) always check (!=NULL) the returned value to assure the operation was successful. Suggest:

FILE *fptr;
fptr = fopen("stuadd.txt", "a+");

if ( !fptr )
{
    perror("fopen failed");
    exit( EXIT_FAILURE );
}

// implied else, fopen successful

struct student *temp = malloc(sizeof(struct student));
if( !temp )
{
    perror( "malloc failed" );
    exit( EXIT_FAILURE );
}

// implied else, malloc successful

regarding:

scanf(" %[^\n]s", temp->name);

That call to scanf() is nonsense. Since the input format specifier %[^\n] will stop input from stdin when it encounters a newline sequence, there is no possible way for the next char in stdin to be a s When calling any of the scanf() family of functions, always check the returned value to assure the operation was successful. when using the input format specifiers %s and/or %[...] always include a MAX CHARACTERS modifier that is one less than the length of the input buffer to avoid any possibility of buffer overflow (and the resulting undefined behavior). Suggest removing the trailing s in the format string and check the return value and limiting the total number of characters that can be input, as in:

 if( scanf(" %29[^\n]", temp->name) != 1 )
 {
     fprintf( stderr, "scanf failed to input the student name\n" );
     exit( EXIT_FAILURE );
 }

regarding:

for(j = 0; j < 100; j++)
{
    temp->mark = temp->mark + studentArray[j];
}

there is no array studentArray[] so this will never produce the desired results.

regarding the error message:

avg = (float)temp->mark / j;
  untitled.c:83:33: error: invalid operands to binary + (have ‘float’ and ‘char *’)
         temp->mark = temp->mark + studentArray[j];

of course a 'float` value cannot be added to a pointer to a char array. What were you actually trying to accomplish?

All the above is just the 'tip of the iceburg' of problems in the posted code. Suggest using a debugger and stepping through your code to determine the many problems

user3629249
  • 15,593
  • 1
  • 16
  • 17
  • The bigger question is "If you are going to the trouble to allocate for each student in `calculateAverage` and `student_update`, why not have `student_update` return the pointer so all students can be held in memory in `main()`, used/queried/etc.. and then written once when done?" (good effort) – David C. Rankin Aug 04 '18 at 06:45
  • I accidently uploaded the wrong code... My proper one is similar but with a few alterations. I don't understand how you're seeing all these errors. I don't get any apart from the calculation i try to do. We have been told to use mingw msys to compile our code and use gcc -o "run" "c program" – Deano Aug 04 '18 at 07:16
  • @Deano **Always** compile using `gcc -o "run" "c program" -Wall -Wextra --std c11` – Spikatrix Aug 04 '18 at 07:26
  • I'd also add `-pedantic` and `-Wshadow` to catch a few more common problems. – David C. Rankin Aug 04 '18 at 07:47
  • Never even knew you could do that... Wow that helps so much! Why don't we get taught this in lectures – Deano Aug 06 '18 at 01:04