简体   繁体   中英

C with structures, pointers and malloc

I am trying to write a c program that uses malloc for a struct, then uses another function to scan the struct. Afterward, the alphanumeric values of the struct use malloc as well. In the end, it calculated the average of the float values of the struct.

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

#define MAX_ARRAY 20
#define MAX_STRUCT_ARRAY 30
#define MIN_STRUCT_ARRAY 0
#define NULL_CHAR '/0'
#define NULL_NUM 0
#define MAX_MARKS 10

struct students
{   char name[MAX_ARRAY];
    int id;
    float marks;
};
typedef struct students studentsDef;

void scanStruct(int numofStructs,struct students listOfstudents);
float mesosOros(int numofStructs,float grades[MAX_STRUCT_ARRAY]);
int main()
{
    int structNum;
   studentsDef* pStudents = NULL;

    do{
        printf("Dwse ton arithmo ton mathiton: ");
        scanf("&d",&structNum);
        if(structNum > MAX_STRUCT_ARRAY || structNum < MIN_STRUCT_ARRAY)
        {
            printf("Oriste arithmo domwn apo %d ews %d. \n",MIN_STRUCT_ARRAY,MAX_STRUCT_ARRAY);
        }
    }while(structNum > MAX_STRUCT_ARRAY || structNum < MIN_STRUCT_ARRAY);

    pStudents=(studentsDef*)malloc(structNum * sizeof(studentsDef));
    if(pStudents==NULL)
    {
        printf("Adunati i dunamiki desmefsi mnimis. \n");
    }
    else
    {
        scanStruct(structNum,*pStudents);
        mesosOros(structNum,*pStudents.marks);
    }
    return 0;
}

void scanStruct(int numofStructs,struct students listOfstudents)
{
    int i,j,sizeOfChar;
    for(i=0;i < numofStructs;i++)
    {
        do{
            printf("Dwse plithos haraktirwn tou onomatos: ");
            scanf("%d",&sizeOfChar);
            if((sizeOfChar<MIN_STRUCT_ARRAY) || (sizeOfChar>MAX_ARRAY))
            {
                printf("Apodekti eisagwgi haraktirwn ews %d.\n",MAX_ARRAY);
            }
        }while((sizeOfChar<MIN_STRUCT_ARRAY) || (sizeOfChar>MAX_ARRAY));
//        listOfstudents[i].name = (char*)malloc((sizeOfChar + 1) * sizeof(char));
        printf("Onoma mathiti: ");
        scanf("%s", listOfstudents[i].name);

        do{
            printf("dwse to id tou mathiti: ");
            scanf("%d",&listOfstudents[i].id);
            if((listOfstudents[i].id < NULL_NUM) || (listOfstudents[i].id == NULL_NUM))
            {
                printf("Adunatio gia arnitiko i mideniko id.\n");
            }
        }while((listOfstudents[i].id < NULL_NUM) || (listOfstudents[i].id == NULL_NUM));

        do{
            printf("dwse bathmo: ");
            scanf("%f",&listOfstudents[i].marks);
            if((listOfstudents[i].marks < NULL_NUM) || (listOfstudents[i].marks == NULL_NUM) || listOfstudents[i].marks > MAX_MARKS)
                {
                    printf("Adunatio gia arnitiko i mideniko id");
                }
        }while((listOfstudents[i].marks < NULL_NUM) || (listOfstudents[i].marks == NULL_NUM) || listOfstudents[i].marks > MAX_MARKS);
    }
}

float mesosOros(int numofStructs,float grades[MAX_STRUCT_ARRAY])
{
    int i;
    for(i=0; i<numofStructs;i++)
    {
        grades[i]+=0;
    }
    return grades[i]/numofStructs;
}

So far I am unable to take advantage of malloc in the second function and also can't pass the struct through the function calls. Thanks in advance. Sorry for any eyesores I am new to structures.

Try this code, it may get you started.

Further below is a patch file you can use to change the code sample into newmain.c and it quickly explains each change. Not all are significant to your question and not all will produce results required. Hoping that it helps, a little bit.

Good luck!

main < input is one way to redirect input from the file input to the program main , the symbol < is used for redirection. The output from this specific run is shown too.

gcc -o main main.c
main < input


Dwse ton arithmo ton mathiton: structNum: 1
Dwse plithos haraktirwn tou onomatos: sizeOfChar: 10
10
Onoma mathiti: listOfstudents[i].name: ABCD EFGH
dwse to id tou mathiti: listOfstudents[i].id: 1
dwse bathmo: listOfstudents[i].marks: 9.000000
RES: 9.000000

Here is the file input , contents. I choose the format, your format needs may be different, CSV, space separated values, and so on. Hope this is close enough to be helpful.

1
10
ABCD EFGH
1
9.0

This is the code, it produces the output shown above when the input is redirected to stdin for the scanf function to read data into the malloc memory.

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

#define MAX_ARRAY 20
#define MAX_STRUCT_ARRAY 30
#define MIN_STRUCT_ARRAY 0
#define NULL_CHAR '/0'
#define NULL_NUM 0
#define MAX_MARKS 10

struct students
{   char name[MAX_ARRAY];
    int id;
    float marks;
};
typedef struct students studentsDef;
typedef struct students* studentsDefPTR;

void scanStruct(int numofStructs, studentsDefPTR listOfstudents);
float mesosOros(int numofStructs, studentsDefPTR listOfstudents);
int main()
{
    int structNum;
    studentsDefPTR pStudents = NULL;

    do{
        printf("Dwse ton arithmo ton mathiton: ");
        scanf("%d%*c",&structNum);
        if(structNum > MAX_STRUCT_ARRAY || structNum < MIN_STRUCT_ARRAY)
        {
            printf("Oriste arithmo domwn apo %d ews %d. \n",MIN_STRUCT_ARRAY,MAX_STRUCT_ARRAY);
        }
    }while(structNum > MAX_STRUCT_ARRAY || structNum < MIN_STRUCT_ARRAY);
    printf("structNum: %d\n",structNum);

    pStudents=(studentsDefPTR)malloc(structNum * sizeof(studentsDef));
    if(pStudents==NULL)
    {
        printf("Adunati i dunamiki desmefsi mnimis. \n");
    }
    else
    {
        scanStruct(structNum,pStudents);
        printf( "RES: %f\n", mesosOros(structNum,pStudents));
    }
    return 0;
}

void scanStruct(int numofStructs,studentsDefPTR listOfstudents)
{
    int i,j,sizeOfChar;
    for(i=0;i < numofStructs;i++)
    {
        do{
            printf("Dwse plithos haraktirwn tou onomatos: ");
            scanf("%d%*c",&sizeOfChar);
            printf("sizeOfChar: %d\n",sizeOfChar);
            if((sizeOfChar<MIN_STRUCT_ARRAY) || (sizeOfChar>MAX_ARRAY))
            {
                printf("Apodekti eisagwgi haraktirwn ews %d.\n",MAX_ARRAY);
            }
        }while((sizeOfChar<MIN_STRUCT_ARRAY) || (sizeOfChar>MAX_ARRAY));
        printf("%d\n",sizeOfChar);
        printf("Onoma mathiti: ");
        memset(listOfstudents[i].name,0,MAX_ARRAY);
        scanf("%[^\n]s%*c",listOfstudents[i].name);
        printf("listOfstudents[i].name: %s\n",listOfstudents[i].name);

        do{
            printf("dwse to id tou mathiti: ");
            scanf("%d",&(listOfstudents[i].id));
            printf("listOfstudents[i].id: %d\n",listOfstudents[i].id);
            if((listOfstudents[i].id < NULL_NUM) || (listOfstudents[i].id == NULL_NUM))
            {
                printf("Adunatio gia arnitiko i mideniko id.\n");
            }
        }while((listOfstudents[i].id < NULL_NUM) || (listOfstudents[i].id == NULL_NUM));

        do{
            printf("dwse bathmo: ");
            scanf("%f%*c",&listOfstudents[i].marks);
            printf("listOfstudents[i].marks: %f\n",listOfstudents[i].marks);
            if((listOfstudents[i].marks < NULL_NUM) || (listOfstudents[i].marks == NULL_NUM) || listOfstudents[i].marks > MAX_MARKS)
                {
                    printf("Adunatio gia arnitiko i mideniko id");
                }
        }while((listOfstudents[i].marks < NULL_NUM) || (listOfstudents[i].marks == NULL_NUM) || listOfstudents[i].marks > MAX_MARKS);
    }
}

float mesosOros(int numofStructs, studentsDefPTR listOfstudents)
{
    int i;
    float total = 0;
    for(i=0; i<numofStructs;i++)
    {
        total += listOfstudents[i].marks;
    }
    return total/numofStructs;
}

Review

The lines that begin with hash # are comments about the specific code change that follows. Save the patch to a file main.patch and apply to code sample main.c like this patch -o newmain.c -i main.patch main.c the output file will be newmain.c .

# Adding string.h b/c using memset to init name string
2a3
> #include <string.h>
# Creating typedef for pointer to struct students for readability
16a18
> typedef struct students* studentsDefPTR;
# Changing function arguments to accept pointer to struct students
# this allows the functions to access allocated memory b/c the function
# is told the address where the memory was allocated
18,19c20,21
< void scanStruct(int numofStructs,struct students listOfstudents);
< float mesosOros(int numofStructs,float grades[MAX_STRUCT_ARRAY]);
---
> void scanStruct(int numofStructs, studentsDefPTR listOfstudents);
> float mesosOros(int numofStructs, studentsDefPTR listOfstudents);
# insignifcant change, these are both equal and valid
23c25
<    studentsDef* pStudents = NULL;
---
>     studentsDefPTR pStudents = NULL;
# ensuring scanf reads newline, may not be the right thing, depends on input
# format, I choose to put each value on a newline, not significant to question
27c29
<         scanf("&d",&structNum);
---
>         scanf("%d%*c",&structNum);
# printing value read, good practice for ensuring initial coding does
# what is expected and is using the values you expect
32a35
>     printf("structNum: %d\n",structNum);
# insignificant change, statements are equal, calling attentiong to PTR
34c37
<     pStudents=(studentsDef*)malloc(structNum * sizeof(studentsDef));
---
>     pStudents=(studentsDefPTR)malloc(structNum * sizeof(studentsDef));
# functions need the address of allocated memory
# pStudents is enough and holds the value returned by malloc
# this is a design change, my choice to make this problem 
# easier for me, it may not be what is needed
41,42c44,45
<         scanStruct(structNum,*pStudents);
<         mesosOros(structNum,*pStudents.marks);
---
>         scanStruct(structNum,pStudents);
>         printf( "RES: %f\n", mesosOros(structNum,pStudents));
# changing scanStruct function to utilize pointer to allocated memory
# the allocated memory comes from malloc which provides the address to
# the first allocated struct in argument listOfstudents
47c50
< void scanStruct(int numofStructs,struct students listOfstudents)
---
> void scanStruct(int numofStructs,studentsDefPTR listOfstudents)
# ensuring scanf reads newline, may not be the right thing, depends on input
# format, I choose to put each value on a newline, not significant to question
# printing value read, good practice for ensuring initial coding does
# what is expected and is using the values you expect
54c57,58
<             scanf("%d",&sizeOfChar);
---
>             scanf("%d%*c",&sizeOfChar);
>             printf("sizeOfChar: %d\n",sizeOfChar);
# oops, this is a duplicate
60c64
< //        listOfstudents[i].name = (char*)malloc((sizeOfChar + 1) * sizeof(char));
---
>         printf("%d\n",sizeOfChar);
# initialize the name string before setting, maybe consider initializing
# entire allocation after malloc instead, coders choice
#
# ensuring scanf reads newline, may not be the right thing, depends on input
# format, I choose to put each value on a newline, not significant to question
#
# printing value read, good practice for ensuring initial coding does
# what is expected and is using the values you expect
62c66,68
<         scanf("%s", listOfstudents[i].name);
---
>         memset(listOfstudents[i].name,0,MAX_ARRAY);
>         scanf("%[^\n]s%*c",listOfstudents[i].name);
>         printf("listOfstudents[i].name: %s\n",listOfstudents[i].name);
# ensuring scanf reads newline, may not be the right thing, depends on input
# format, I choose to put each value on a newline, not significant to question
#
# printing value read, good practice for ensuring initial coding does
# what is expected and is using the values you expect
66c72,73
<             scanf("%d",&listOfstudents[i].id);
---
>             scanf("%d",&(listOfstudents[i].id));
>             printf("listOfstudents[i].id: %d\n",listOfstudents[i].id);
# ensuring scanf reads newline, may not be the right thing, depends on input
# format, I choose to put each value on a newline, not significant to question
#
# printing value read, good practice for ensuring initial coding does
# what is expected and is using the values you expect
75c82,83
<             scanf("%f",&listOfstudents[i].marks);
---
>             scanf("%f%*c",&listOfstudents[i].marks);
>             printf("listOfstudents[i].marks: %f\n",listOfstudents[i].marks);
# changing mesosOros function to utilize pointer to allocated memory
# the allocated memory comes from malloc which provides the address to
# the first allocated struct in argument listOfstudents
84c92
< float mesosOros(int numofStructs,float grades[MAX_STRUCT_ARRAY])
---
> float mesosOros(int numofStructs, studentsDefPTR listOfstudents)
# new local scope value to hold total of all marks
86a95
>     float total = 0;
# total up all marks into local variable
89c98
<         grades[i]+=0;
---
>         total += listOfstudents[i].marks;
# return computed result, maybe what is needed, not sure
# not significant to question though
91c100
<     return grades[i]/numofStructs;
---
>     return total/numofStructs;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM