So i'm new to C and i have a problem with struct, so when i run the program it goes to the_struct2 asks for first name and thats it. why does it stop working? is there a way to make the code more efficient? and is there a way to ask the user to enter number of students which records will be entered to define the number of inputs instead of making it exactly 6 based on structures. I read something regarding the Global variable but couldn't find out how to use it with structures.

P.S the purpose of the program is to take students last name, first name and score and save them so the user could call one of the functions listed at the end print statement (which i am working on still).

Thank you in advance.

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

struct the_struct
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
struct the_struct2
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
struct the_struct3
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
struct the_struct4
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
struct the_struct5
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
struct the_struct6
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
    int main ()
 {
int i;
struct the_struct *ptr;
printf("Enter First Name \n");
scanf("%s",ptr->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr->LastName);
printf("Enter Score? \n");
scanf("%s",ptr->Score);
printf("%s %s %s",ptr->FirstName,ptr->LastName,ptr->Score);
//_____________________________________________________________
struct the_struct2 *ptr1;
printf("Enter First Name \n");
scanf("%s",ptr1->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr1->LastName);
printf("Enter Score? \n");
scanf("%s",ptr1->Score);
printf("%s %s %s",ptr1->FirstName,ptr1->LastName,ptr1->Score);
//__________________________________________________________________
struct the_struct3 *ptr2;
printf("Enter First Name \n");
scanf("%s",ptr2->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr2->LastName);
printf("Enter Score? \n");
scanf("%s",ptr2->Score);
printf("%s %s %s",ptr2->FirstName,ptr2->LastName,ptr2->Score);
//____________________________________________________________________
struct the_struct4 *ptr3;
printf("Enter First Name \n");
scanf("%s",ptr3->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr3->LastName);
printf("Enter Score? \n");
scanf("%s",ptr3->Score);
printf("%s %s %s",ptr3->FirstName,ptr3->LastName,ptr3->Score);
//___________________________________________________________________
struct the_struct5 *ptr4;
printf("Enter First Name \n");
scanf("%s",ptr4->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr4->LastName);
printf("Enter Score? \n");
scanf("%s",ptr4->Score);
printf("%s %s %s",ptr4->FirstName,ptr4->LastName,ptr4->Score);
//_________________________________________________________________
struct the_struct6 *ptr5;
printf("Enter First Name \n");
scanf("%s",ptr5->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr5->LastName);
printf("Enter Score? \n");
scanf("%s",ptr5->Score);
printf("%s %s %s",ptr5->FirstName,ptr5->LastName,ptr5->Score);
//Starting the function for entries.
printf("Enter the command you want to proceed to.\nprint record (press 1)\nadd new records (press 2)\ndelete record (press 3)\nSearch by last name (press 4)\nSort by score(press 5)\nSort by last name( press 6)\nFind Median score(press 7)\nExit program (press 0)");


      return 0;
}
Member Avatar for MonsieurPointer

Yes, you can make the code more efficient.

First of all, all your structs contain the same members.
Consider the following: you would like to define 6 integers. Would you write this:

int1 myint1;
int2 myint2;
int3 myint3;
...

or this?

int myint1;
int myint2;
int myint3;
...

Either you define all your variables from the same type (the_struct), or better yet, make an array of the_struct:

the_struct my_structs[6];

Another fatal error is that you are using pointers to your structures, but you are not allocating memory for them! This will lead to your program crashing.

Also, you need to take a look on how the function scanf works. Your program is telling me that you do not know how pointers work. I would recommend that you tackle the basics of that first before continuing.

And it also looks like you are using pointers in the members of your structures when it looks like you did not intend to.

struct the_struct
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};

FirstName and LastName are an arrays of pointers to char, did you in fact mean to use an array of char, since that is what you use to hold a string in C?
Score is an array of pointers to int, did you actually mean an array of int to hold several scores for a single person?

so i re-wrote the struct as MonsieurPointer suggested, and yes i realize i have a problem with pointers but i read all kind of books, websites and still can't understand it fully. also i made all struct the same type but i don't know how to switch it into arrays, didn't take it in class.
-it would be easier to use arrays in this code, but the problem is that the assignment clearly stated that; You must use pointers for this lab. No arrays, no structures. For example, if you need an array of floats to hold the scores, do not use float score[15]. Rather use float score, then use dynamic memory allocation to hold required memory. You must use memory optimally, that is if you have only 6 scores, you must point to a memory chunk of sizeof(float)6 bytes.;

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

void print_records (int);
void add_new_records (int);
void delete_records (int);
void search_by_last_name (int);
void sort_by_score (int);
void sort_by_last_name (int);
void find_median_score (int);
void Exit_program (int);

the_struct my_struct
{
 char *FirstName[20];
 char *LastName[32];
 int  *Score[20];
};
the_struct my_struct2
{
 char *FirstName2[20];
 char *LastName2[32];
 int  *Score2[20];
};
the_struct my_struct3
{
 char *FirstName3[20];
 char *LastName3[32];
 int  *Score3[20];
};
the_struct my_struct4
{
 char *FirstName4[20];
 char *LastName4[32];
 int  *Score4[20];
};
the_struct my_struct5
{
 char *FirstName5[20];
 char *LastName5[32];
 int  *Score5[20];
};
the_struct my_struct6
{
 char *FirstName6[20];
 char *LastName6[32];
 int  *Score6[20];
};
    int main ()
 {
int i;
struct the_struct *ptr;
printf("Enter First Name \n");
scanf("%s",ptr->FirstName);
printf("Enter Last Name \n");
scanf("%s",ptr->LastName);
printf("Enter Score? \n");
scanf("%s",ptr->Score);
printf("%s %s %s",ptr->FirstName,ptr->LastName,ptr->Score);
//_____________________________________________________________
struct the_struct2 *ptr1;
printf("Enter First Name \n");
scanf("%s",ptr1->FirstName2);
printf("Enter Last Name \n");
scanf("%s",ptr1->LastName2);
printf("Enter Score? \n");
scanf("%s",ptr1->Score2);
printf("%s %s %s",ptr1->FirstName2,ptr1->LastName2,ptr1->Score2);
//__________________________________________________________________
struct the_struct3 *ptr2;
printf("Enter First Name \n");
scanf("%s",ptr2->FirstName3);
printf("Enter Last Name \n");
scanf("%s",ptr2->LastName3);
printf("Enter Score? \n");
scanf("%s",ptr2->Score3);
printf("%s %s %s",ptr2->FirstName3,ptr2->LastName3,ptr2->Score3);
//____________________________________________________________________
struct the_struct4 *ptr3;
printf("Enter First Name \n");
scanf("%s",ptr3->FirstName4);
printf("Enter Last Name \n");
scanf("%s",ptr3->LastName4);
printf("Enter Score? \n");
scanf("%s",ptr3->Score4);
printf("%s %s %s",ptr3->FirstName4,ptr3->LastName4,ptr3->Score4);
//___________________________________________________________________
struct the_struct5 *ptr4;
printf("Enter First Name \n");
scanf("%s",ptr4->FirstName5);
printf("Enter Last Name \n");
scanf("%s",ptr4->LastName5);
printf("Enter Score? \n");
scanf("%s",ptr4->Score5);
printf("%s %s %s",ptr4->FirstName5,ptr4->LastName5,ptr4->Score5);
//_________________________________________________________________
struct the_struct6 *ptr5;
printf("Enter First Name \n");
scanf("%s",ptr5->FirstName6);
printf("Enter Last Name \n");
scanf("%s",ptr5->LastName6);
printf("Enter Score? \n");
scanf("%s",ptr5->Score6);
printf("%s %s %s",ptcgr5->FirstName6,ptr5->LastName6,ptr5->Score6);
//Starting the function for entries.
printf("Enter the command you want to proceed to.\nprint record (press 1)\nadd new records (press 2)\ndelete record (press 3)\nSearch by last name (press 4)\nSort by score(press 5)\nSort by last name( press 6)\nFind Median score(press 7)\nExit program (press 0)");


      return 0;
}

Oh, I think that there's a definite issue with the code as written, then. First off, the code is wrong syntactically; if it compiles, I would be surprised. You are declaring all of the structures incorrectly. The correct syntax would be like this:

struct the_struct
{
    char *FirstName;
    char *LastName;
    int  *Score; 
};

struct the_struct *my_struct1, *mystruct2, *mystruct3, *mystruct4;

However, there is a much more serious misunderstanding of the assignment itself. The real purpose is to use dynamic memory allocation, rather than creating several structures locally.

pay closer atention to the original answer from MnsrPtr! You need an array of pointers of whatever size (number) of students in the group:
e.g--#define MAX_SIZE 20
Note that you are already using arrays in your Struct "member" fields, so don't get confused with "not being allowed to use arrays".

Actually, Richard, I suspect that that would not be the correct solution to the problem. Indeed, I have a pretty good idea of where this is going.

DkgMarine: Could you please post the whole problem statement? If I don't miss my guess, what your real assignment is is to work with linked lists.

commented: yes, after seeing the actual problem, I see that I mis-understood the direction entirely! +0

i don't think we are allowed to use linked list, we're covering how to use pointers with structs, thats why i have a problem knowing what to do and somehow the assignment is due 04/24!
P.S we covered pointers last week so barely enough time to think about it!

OK, that clarifies quite a bit. I think what you need is to define the struct type as I explained, and declare a single pointer to that type; then, once you have the number of entries, you would use calloc() to allocate the array of structures dynamically:

struct SCORE_T
{
    char *FirstName;
    char *LastName;
    int  Score; 
}

int name_size;
char *buffer;
struct SCORE_T *scores;

buffer = malloc(21); /* allocate buffer of 20 chars + delimiter */

/* later ... */

scores = calloc(sizeof(SCORE_T), num_scores);

Don't forget to free() everything you allocate at the end.

Now, you may be wondering what this buffer variable is about. That is to hold the input for the names. You would read in the name to the buffer, then get the size of the string with strlen(). Then you would allocate the actual space for the string, like so:

scanf("%20s", buffer);
buffer[20] = '\0';     /* ensure that it is delimited */
name_size = strlen(buffer);
score[i].FirstName = malloc(name_size + 1);
strcpy(buffer, score[i].FirstName);

You would do the same for LastName.

Member Avatar for MonsieurPointer

It's not exactly good practice to leave out what type malloc needs to allocate.

Rather than this:

score[i].FirstName = malloc(name_size + 1);

I would write this:

score[i].FirstName = (char *)malloc((name_size + 1) * sizeof(char));

You can even put everything on one line if you wish:

score[i].FirstName = (char *)malloc((strlen(buffer) + 1) * sizeof(char));

Also, since you are dealing with pointers, always make sure to initialize them to NULL before using them - otherwise there is a good possibilty that they are going to point to some random address!

EDIT: It is also not a bad idea to check if memory was really allocated. To do so, just check against NULL.

It's not exactly good practice to leave out what type malloc needs to allocate.

Rather than this:

score[i].FirstName = malloc(name_size + 1);

I would write this:

score[i].FirstName = (char *)malloc((name_size + 1) * sizeof(char));

I can not agree with this. Firstly malloc does not allocate types, it allocates raw data it is the program that decides how to treat that data. malloc handles this correctly by returning void*, ie data without a type, which the C compiler, again correctly, can convert to any other pointer type. If your compiler is producing errors then you most likely are compiling your code with a C++ compiler. In this case you should either get a differenet compiler/add the switch that tells the compiler this is C or alternitively use new; note that I do understand that what you should do and what you can do are sometimes different things.

However what is not good practice is putting in unnecessary casts. A cast switches off all the type checking a compiler might do, it is like waving a big flag at the compiler saying "You don't need to bother checking any of this because I know exactly what I am doing". In my experience more often than not the compiler knows what it is doing better then most programmers particularly new ones and I have seen too many problems caused by programmers who didn't know any better fixing a problem with a cast.

Member Avatar for MonsieurPointer

Perhaps I chose a wrong wording to put my point across.
I am not forcing the malloc to choose a particular type, I am merely indicating the correct block size for the memory. In this case, it's char. To make sure that it is comptabile with the variable type (char *), I am casting the return of malloc (which you correclty indicated as void*).

A cast switches off all the type checking a compiler might do, it is like waving a big flag at the compiler saying "You don't need to bother checking any of this because I know exactly what I am doing".

I do know what I'm doing. I know I have to allocate memory for a char*!

and I have seen too many problems caused by programmers who didn't know any better fixing a problem with a cast.

I wouldn't call this fixing a problem, but rather avoiding one (like potential compiler errors). It is perfectly safe to cast it!

so after alot of reading and understanding you guy's posts, i got it to take in the name and scores! Thanks alot!!
but i have a small question, if i want to sort them by score or search by last name what is the best way to solve it or write it?

this is the latest code;

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

struct the_struct
{
 char FirstName[20];
 char LastName[32];
 int  Score[20];
};
int main ()
 {
int i,n;
struct the_struct *ptr[100];
printf("how many students?\n");
scanf("%d",&n);

for (i = 0; i < n; ++i)
{

   ptr[i] = malloc(sizeof(struct the_struct));
   printf("Enter First Name \n");
   scanf("%s",ptr[i]->FirstName);
   printf("Enter Last Name \n");
   scanf("%s",ptr[i]->LastName);
   printf("Enter Score? \n");
   scanf("%s",ptr[i]->Score);
   printf("%s %s %s\n",ptr[i]->FirstName,ptr[i]->LastName,ptr[i]->Score);
    }
printf("Enter the command you want to proceed to.\nprint record (press 1)\nadd new records (press 2)\ndelete record (press 3)\nSearch by last name (press 4)\nSort by score(press 5)\nSort by last name( press 6)\nFind Median score(press 7)\nExit program (press 0)");
 }

You want to sort all the structures by score? If yes, which score? Say each instance of the structure contains 20 scores, which of those 20 scores do you want to use to sort all the structures?

Or do you just want to sort all the scores within each instance of the structure. That's pretty straight forward -- add a Sort() function and pass the array of scores to it so that Sort() can sort them.

To search by Name (or any other field) you need a Search() function.

Note that putting all this in main() is a very BAD idea -- use functions to make the code more readable and understandable.

Actually since this is C and the structures are also in an array you could just use qsort to sort them.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.