I've been sitting with this code for three days. The problem is that I have reached the rock bottom and I don't know how I will solve this without any help from you guys. I have a struct with arrays of type char name, surname, persnbr.
struct pers
{
char name[7];
char last_name[10];
char id_nbr[12];
};
I have solved the problem with adding name surname and persnbr in the arrays but now I don't know how to remove them.
This is the queueEn function
void queueEn(person p1){
strcpy(queue[last].name, p1.name);
strcpy(queue[last].last_name, p1.last_name);
strcpy(queue[last].id_nbr, p1.id_nbr);
}
and the queueAdd function
void queueAdd(person person1)
{
if(last<MAX_SIZE_QUEUE){
printf("Name: ");
scanf("%s", person1.name);
printf("Last name: ");
scanf("%s", person1.sur_name);
printf("Id-number: ");
scanf("%s", person1.id_nbr);
last++;
}else {
printf("Queue is full\n");
}
queueEn(person1);
}
This code works excellent.
Now I have the functions queueDe and queueRemove
This is what I've done so far:
void queueDe(person *personPoint){
first = (first + 1)% MAX_SIZE_QUEUE;
*personPoint = queue[first];
strcpy(personPoint->name, queue[first].name);
strcpy(personPoint->last_name, queue[first].last_name);
strcpy(personPoint->id_nbr, queue[first].id_nbr);
}
The thing is that I have to copy the information from array so I assumed that's how you do it. The information will be shown to the user(the person who is the last on the queue(FIFO-structure))
Here is the function remove_from_queue
void queueRemove(person personRem){
if(first < MAX_SIZE_QUEUE){
printf("Name: %s", personRem.name);
printf("Last Name: %s", personRem.last_name);
printf("Id-Number: %s", personRem.id_nbr);
first++;
}else{
printf("Queue is empty");
}
queueDe(&personRem);
}
The variables first and last are equivalent with the end of array and the beginning of array. To delete the last person in the array I have to delete the person on first. Both of the variables are initialized to 0 in the beginning. I've read that I need to initialize the pointer *personPoint to malloc but I don't know how to use it in this specific situation.
When I execute the program and want to delete the person nothing happens.
I'm thankful for an answer.
A circular queue is a reasonable data structure, but you need a clear grasp of your queue 'empty' and queue 'full' conditions. First we will define a circular queue struct, which holds first, last and queue[] array elements,
typedef struct circular_array_queue_s
{
person* queue[MAX_SIZE_QUEUE];
int first;
int last;
} CirQueue;
CirQueue cirq;
Now we can define functions to report whether the queue is empty, full, and to report the count of the number of elements,
int queueEmpty()
{
if( cirq.first == cirq.last ) //queue empty
{
printf("Queue is empty");
return 1;
}
return 0;
}
int queueFull()
{
if( ((cirq.last+1%MAX_SIZE_QUEUE)) == cirq.first ) //queue full
{
printf("Queue is full\n");
return 1;
}
return 0;
}
int queueCount()
{
int count=0;
if( cirq.first<=cirq.last )
count=(cirq.last-cirq.first);
else //if ( cirq.first>cirq.last )
count=(cirq.last+MAX_SIZE_QUEUE)-cirq.first;
return count;
}
The queue operations for enqueue and dequeue are simplified, as you enqueue at the queue last position, and dequeue from the queue first position. Since you have a circular queue, moving the first and last indices is done by incrementing by one, and wrapping at the end (using modulus MAX_SIZE_QUEUE),
person*
queueEn(person* p)
{
//err
if( queueFull() ) { return NULL; } //queue full, fail
cirq.queue[cirq.last] = p;
cirq.last = (cirq.last+1)%MAX_SIZE_QUEUE; //one
return p;
}
person*
queueDe()
{
person* p;
//err
if( queueEmpty() ) { return NULL; } //queue empty, fail
p = cirq.queue[cirq.first];
cirq.queue[cirq.first] = NULL;
cirq.first = (cirq.first+1)%MAX_SIZE_QUEUE;
return p;
}
Walking (iterating) over the entire can be done using a function similar to,
person*
queueIterate()
{
person* p;
int iter;
if( queueEmpty() ) { return NULL; } //queue empty, skip
for( iter=cirq.first; iter!=cirq.last; iter=(++iter)%MAX_SIZE_QUEUE )
{
personPrint(p = cirq.queue[iter]);
}
return p;
}
Adding elements to the queue requires that you create elements to add (malloc), and properly dispose of elements when you remove them (free),
void queueAdd(person person1)
{
if( queueFull() ) { return; } //queue full, cannot add
personRead(&person1);
person* p;
queueEn(personCopy(p=personNew(),&person1));
}
person*
queueRemove(person* personRem)
{
person* p;
if(p = queueDe())
{
if(personRem) {
personCopy(personRem,p); personDel(p);
}
//if you don't give a personRem, you must free person p removed from queue
else
personRem=p;
}
return personRem;
}
You want to test these queue functions,
int
main()
{
person per;
person* perp;
int done=0;
while(!done)
{
queueAdd(per);
if( queueFull() ) done=1;
if( queueCount() >= 3 ) done=1; //just do three
}
queueIterate();
while(!queueEmpty())
{
personPrint(perp=queueRemove(&per));
}
}
Please understand that C strings are null-terminated, so declaring your char[] using an N+1 idiom will clearly communicate the available string size,
typedef struct person_s
{
char name[9+1]; //size to N+1, makes clear the space, "Alexander"(9)
char last_name[10+1]; //room for null-terminator
char id_nbr[12+1]; //you really want to room for null-terminator
} person;
You will find that having functions which encapsulate your member access can make your code more readable, and support a DRY (Dont Repeat Yourself) approach, and hide details which you probably do not want to expose and handle everywhere,
person*
personNew()
{
person* pnew;
if( !(pnew=malloc(sizeof(person))) ) return NULL;
strncpy(pnew->name, ">name", sizeof(pnew->name));
strncpy(pnew->last_name, ">last_name", sizeof(pnew->last_name));
strncpy(pnew->id_nbr, ">id_nbr", sizeof(pnew->id_nbr));
return(pnew);
}
void personDel(person* p)
{
if( !p ) return; //fail, must have valid pointer
free(p);
return;
}
person*
personCopy(person* pd, person* ps)
{
if(!pd || !ps) return;
strncpy(pd->name, ps->name, sizeof(pd->name));
strncpy(pd->last_name, ps->last_name, sizeof(pd->last_name));
strncpy(pd->id_nbr, ps->id_nbr, sizeof(pd->id_nbr));
return(pd);
}
Here are functions to set the member values (often called setters or mutators),
person*
personName(person* p1, char* name)
{
if(!p1 || !name) return p1;
strncpy(p1->name, name, sizeof(p1->name));
return(p1);
}
person*
personLastName(person* p1, char* last_name)
{
if(!p1 || !last_name) return p1;
strncpy(p1->last_name, last_name, sizeof(p1->last_name));
return(p1);
}
person*
personIdNbr(person* p1, char* id_nbr)
{
if(!p1 || !id_nbr) return p1;
strncpy(p1->id_nbr, id_nbr, sizeof(p1->id_nbr));
return(p1);
}
And here are functions to read and print your person struct,
person*
personRead(person* personp) //two
{
if(!personp) return personp;
//you really should allow for more space here
char name[99+1];
char last_name[99+1];
char id_nbr[99+1];
printf("Name: "); scanf("%s", name);
printf("Last name: "); scanf("%s", last_name);
printf("Id-number: "); scanf("%s", id_nbr);
personName(personp,name);
personLastName(personp,last_name);
personIdNbr(personp,id_nbr);
return(personp);
}
void personPrint(person* personp) //five
{
if(!personp) return personp;
printf("Name: %s,", personp->name);
printf("Last Name: %s,", personp->last_name);
printf("Id-Number: %s\n", personp->id_nbr);
}
Note that I used malloc/free and person (pointer to person struct) throughout. You need to learn about pointers if you want to program in C.*
Related
My first problem is that I have problem to make that for loop and implement it into the code and somehow finish my program.
My second problem is compiler showing problem in this: memset(database,0,SIZE*sizeof(struct student)); type specifier missing, defaults to 'int'
And at the end of program i have problem with memcpy(database.name,name,size_of_name); member reference base type 'struct student [100]' is not a structure or union
There are my structure and functions:
#define SIZE 100
struct student {
char name[SIZE];
int votes;
};
struct student database[SIZE];
memset(database,0,SIZE*sizeof(struct student));
int size = 0;
int find_student(struct student* students,int size, const char* name){
// for loop,which take all entries in database
// if it find same name, then reutrn his index
//otherwise reuturn -1;
int i;
for(i=0; i<SIZE;i++){
// how to make that loop
}
return -1;
}
int compare(const void* p1, const void* p2){
struct student* s1 = (struct student*)p1;
struct student* s2 = (struct student*)p2;
// s1->votes
// s1->name
return 0;
}
And there is my code what I already did( sorry for my grammar):
char line[SIZE];
memset(line,0,SIZE);
char* r = fgets(line,SIZE,stdin);
if (r == NULL){
printf("End of input");
return (-1);
}
char* end = NULL;
int value = strtol(line,&end,10);
if (value == 0){
printf("Convertion was not sucessful");
return (-1);
}
// helping array
char name[SIZE];
// set on zero
memset(name,0,SIZE);
// get begining of a name = one position after space
char* beginning_name = end + 1;
// Size of name is number of signs to end of string
// minus end of line
int size_of_name = strlen(beginning_name) - 1;
if (size_of_name > 0){
// copy
memcpy(name,beginning_name,size_of_name);
// At the end is saved string with name
// without end of line and with zero at the end
}
else {
// failed to read a name
printf("Failed to read a name");
return (-1);
}
int id = find_student(database,size,name);
if (id< 0){
// copy it to last place in array
memcpy(database.name,name,size_of_name);
// increase number of entries
size+=1;
}
else {
// there I need add to votes,something like votes++;
}
}
Sorry for formating but I am new at stackoverflow.
Basicaly what i want is to read a file in these case im using the stdin as my file FILE *f=stdin;
the files contains something like these
2019 - Frog and Mouse
1982 - Water and gelly
3025 - Sugar
...
I want to be able to read and print the names and the total number of characters of the names
so far i have created a structure and a list
typedef struct struct_data_uc{
int *uc_number;
char *uc_name;
} S_data_uc;
typedef struct List_uc_data{
S_data_uc uc_data;
struct List_uc_data *next;
} L_uc_data;
L_uc_data* UC_add(L_uc_data *list, L_uc_data data_uc){
L_uc_data *new;
new=(L_uc_data*)malloc(sizeof(L_uc_data));
if(new!=NULL){
(*new)=data_uc;
new->next=list;
return new;
}
return list;
}
then i created the functions to read the list and show the results and also ree the list
void UC_free(L_uc_data *list){
L_uc_data *aux;
while(list!=NULL){
aux=list->next;
free(list);
list=aux;
}
}
void UC_read(L_uc_data *data_uc, FILE *fin, FILE *fout){
char str[MAXSTR];
if(fout!=NULL)
fscanf(fin,"%d - %c",&data_uc->uc_data.uc_number,&data_uc->uc_data.uc_name);
void UC_Show(L_uc_data *data_uc, FILE *fout, int prompt){
if(prompt==0){
fprintf(fout,"%d - %c\n",
data_uc->uc_data.uc_number,
data_uc->uc_data.uc_name);
}else{
fprintf(fout,"%d - %c\n",
data_uc->uc_data.uc_number,
data_uc->uc_data.uc_name);
}
}
than my main
int main(){
FILE *f=stdin;
L_uc_data *list=NULL, *i, data_uc;
UC_read(&data_uc, stdin, stdout);
list=UC_add(list,data_uc);
for(i=list;i!=NULL;i=i->next)
UC_Show(i,f,0);
return 0;
}
but the program wont seems to work, any help?
There are quite a few errors in your code. I've tried to fix without modifying the original code too much. See the comments for details.
typedef struct struct_data_uc{
int uc_number; // Changed from int *
char *uc_name;
} S_data_uc;
typedef struct List_uc_data{
S_data_uc uc_data;
struct List_uc_data *next;
} L_uc_data;
// Allocate a new L_uc_data and insert into list
L_uc_data* UC_add(L_uc_data *list, int number, const char *name)
{
L_uc_data *new = malloc(sizeof(L_uc_data));
if (new != NULL) {
new->uc_data.uc_number = number;
// Need strdup here to alloc mem and copy
new->uc_data.uc_name = strdup(name);
new->next = list;
return new;
}
return list;
}
// Free the entire list
void UC_free(L_uc_data *list)
{
while (list) {
L_uc_data *aux = list->next;
// Free the mem from strdup
free(list->uc_data.uc_name);
free(list);
list = aux;
}
}
// Reads the entire file and returns a new list
L_uc_data * UC_read(FILE *f)
{
char line[MAXSTR];
L_uc_data *the_list = NULL;
// Using fgets to get the entire line, then sscanf to parse
while (fgets(line, MAXSTR, f)) {
int number;
char name[MAXSTR];
// Remember to check the return from sscanf
if (2 == sscanf(line, "%d - %[^\n]", &number, name)) {
// Add to list
the_list = UC_add(the_list, number, name);
}
}
return the_list;
}
// Print the entire list
void UC_show(L_uc_data *list, FILE *fout)
{
while (list) {
fprintf(fout, "%d - %s\n", list->uc_data.uc_number, list->uc_data.uc_name);
list = list->next;
}
}
int main()
{
L_uc_data *list = UC_read(stdin);
UC_show(list, stdout);
UC_free(list);
return 0;
}
You're making (at least) 2 mistakes. First, you are passing stdin as the argument to UC_Show, where an attempt is made to write to it. 2nd, you are not checking the value returned by printf, which is almost certainly going to indicate an error and set errno to EBADF to tell you exactly what the error is. You cannot write to stdin.
I am trying to make a C program to count the number of frequency of words in a document and to split the document up into N parts with each part being counted by a different thread. Everytime I run the program, I get back nonsensical data, but if I run it without the threads I get back the data that I expect.
Here is the Struct named BinarySearchTree.h
typedef struct {
char *num; /*! The contents of the <tt>Item</tt>.<br>Type: <tt>int</tt>*/
int count;
} Item; /*! \typedef Item
* \struct A struct represent one item.
*/
typedef struct node {
Item info; /*! A struct with a one <tt>int</tt> on it. */
struct node * left;
struct node * right;
} Tree;
typedef struct passargs {
char *File;
Tree *t;
int splitStart;
int splitEnd;
int i;
int a;
char words[512][512];
} pass;
Here is the main code named **BinarySearchTree.c*:
#include "BinarySearchTree.h"
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
// Code for integer based BST from: https://gist.github.com/ArnonEilat/4611213
Tree * add(Tree* nod, char *number) {
if (nod == NULL) {
printf("Thread number %ld\n", pthread_self());
printf("\nMaking new node for %s\n", number);
nod = (Tree*) malloc(sizeof (Tree));
if (nod == NULL) {
return NULL;
}
nod->info.num = number;
nod->info.count=1; //Increment the value if the same word is found
nod->left = NULL;
nod->right = NULL;
return nod;
}
if (strcmp(nod->info.num, number)==0) {
printf("%s==%s ",nod->info.num,number);
printf("\t%s:%d ",nod->info.num,nod->info.count);
// ++nod->info.count;
nod->info.count++;
printf("->%d\n ",nod->info.count);
return nod;
}
if (strcmp(nod->info.num, number)>0){
printf("%s>%s ",nod->info.num,number);
nod->left = add(nod->left, number);
} else {
printf("%s<=%s ",nod->info.num,number);
nod->right = add(nod->right, number);
}
return nod;
}
void printInorder(Tree* nod) {
if (nod == NULL) {
return;
}
printInorder(nod->left);
printf(" %s: %d ", nod->info.num, nod->info.count);
printInorder(nod->right);
}
void freeTree(Tree *root) {
if (root == NULL) {
return;
}
freeTree(root->left);
freeTree(root->right);
free(root);
}
int newLines(char* File){ //Count the number of new lines in the file. Split based on those not word count
int newLines=0;
char buffTemp[5120];
FILE *fp1 = fopen(File, "r");
while(1)
{
if(fgets(buffTemp, 512, fp1) ==NULL)
break;
else{
newLines++;
}
}
fclose(fp1);
return newLines;
}
//This function reads the file and adds each entry to the tree, or increments if same word is present
Tree* read(pass* info){
const char *delims = " \n"; //Deliminate by newlines and spaces
char *token;
int splitCounter=0;
FILE *fp = fopen(info->File, "r");
char buff[512];
int aT=info->a; //Putting variables into local ones
int iT=info->i;
int splitEnd = info->splitEnd;
int splitStart = info->splitStart;
char words[512][512];
memcpy(words, info->words, 512);
Tree* nod=info->t;
while(1 && splitCounter<splitEnd) //While the file does not end and we have not reached the end of the split
{
fgets(buff, 512, fp);
splitCounter++;
if(buff == NULL)
break;
else if (splitCounter>splitStart){
printf("\t %s\n", buff);
token = strtok(buff, delims); //Split via the tokens and put them into buff
while (token!=0) {
strcpy(words[iT], token);
iT += 1;
token = strtok(NULL, delims);
}
}
}
for (;aT<iT;aT++){
nod=add(nod, (char *)words[aT]); //Add each word to the tree
}
printf("\n");
fclose(fp);
info->t=nod;
memcpy(info->words,words,512);
info->i=iT;
info->a=aT;
return nod;
}
int main() {
Tree* t = NULL;
pass args;
args.t=t;
args.i=0;
args.a=0;
args.splitStart=0; //These splits are used to tell each thread where to look in the file
args.splitEnd=0;
args.File="/home/dib/CLionProjects/deleteme/readFile"; //Address of the file to be read
int numLines=newLines(args.File);
printf("\nnewLines %d\n",numLines);
int split;
printf("How many splits/threads would you like to create?\n");
scanf("%d", &split);
int iterator=numLines/split;
printf("iterator %d:", iterator);
const int NUMTHREADS= numLines/iterator + (numLines % iterator != 0);
unsigned int p;
// This for loop shows how I hope the threads would work. Uncomment the below block to see it work
for (p=0; p<NUMTHREADS; p++){
args.splitStart=args.splitEnd;
if (args.splitEnd+iterator>numLines) args.splitEnd=numLines;
else args.splitEnd+=iterator;
read(&args);
}
pthread_t th[NUMTHREADS];
int threads[NUMTHREADS];
//This is my attempt at using threads to solve the same problem as the above for loop
// for(p=0; p< NUMTHREADS; p++){
// threads[p] = p;
// args.splitStart=args.splitEnd;
// if (args.splitEnd+iterator>numLines) args.splitEnd=numLines;
// else args.splitEnd+=iterator;
// printf("split end: %d",args.splitEnd);
// pthread_create(&th[p], NULL, &read, &args);
// }
printInorder(args.t);
freeTree(args.t);
exit(0);
}
And finally the document I have been using as a test case named readFile:
five five five one two
two three three four four
three six seven six six
four six five seven seven
seven seven seven seven six
five four six
I tried implementing the solution found here : passing struct to pthread as an argument
but did not know what thread_handles was, and could not get it to work though the problem faced in that link is similar. So am I also just having a problem with memory allocation or is it something completely different?
I have a problem writing a code that should read usernames and put them in list. Every username should be connected to the number of times it has been entered. The problem occurs when entering the second username, my code places that username in the variable called first (where the first is kept). I guess I've done something wrong with the pointers, but I cannot find what. I am confused, in the end of one while loop the first one is the real first one, and when the program enters while again, variable first changes. How could that be? Please help me.
Thank you :)
typedef struct _user
{
char *name;
int counter;
struct _user *next;
} user;
int main() {
char userName [10];
int found = 0, go_on = 1;
user *first = NULL, *temp, *new;
while (go_on == 1) {
printf ("Username: ");
scanf("%s", userName);
if (first) {
// printf ("The first one in list: %s\n", first->name); - this prints the name of last username entered
for (temp = first; temp; temp = temp->next) {
if (strcmp (temp->name, userName) == 0) {
temp->counter++;
found = 1; }
if (found== 1) break;}
if (!found) {
new = (user*) malloc (sizeof(user));
new->name = userName;
new->counter = 1;
temp = new;
temp->next = NULL; } }
else {
new = (user*) malloc (sizeof(user));
new->name = userName;
new->counter = 1;
first = new;
first->next = NULL; }
printf ("Go on? (1/0)");
scanf("%d", &go_on);
printf ("Current list: ");
for (temp=first; temp; temp = temp->next)
printf("%s %d\n", temp->name, temp->counter);
//printf ("The first one in list: %s\n", first->name); - this prints the correct first
}
}
Your error, I think, is the userName array. You should allocate a new one for each element in your linked list. When you write new->name = userName;, you are not copying the name to the struct, you are making the struct point to your userName[10] array. As such every struct's actual "name" is storing only the single last name scanf-ed. That being said...
I generally prefer to write that kind of code with dedicated tools instead of logically embedding them in a loop construct:
Keeping your struct:
typedef struct _user
{
char *name;
int counter;
struct _user *next;
} user;
I would create a function that, given a properly constructed Sll returns a matching element:
function user *user_match_name(user *user_head, const ch *name)
{
user *cur_user = NULL;
/* look for a match */
for (cur_user = user_head ; cur_user ; cur_user = cur_user->next)
if(!strcmp(name,cur_user->name) return cur_user;
/* no match */
return NULL;
}
Then I usually prefer to have an Sll element builder:
function user *create_user(const ch *name)
{
user *new_user;
if(!(new_user = malloc(sizeof(user))))
printf("Error in allocation"); /* or better malloc error handling */
/* IMPORTANT: PROVIDE MEMORY FOR THE NAMES!!! */
if(!(new_user->name = malloc(sizeof(char)*256))) /* sizeof(char) is useless but I like to explicit it like that. And 256 should be enough a buffer could be better made */
printf("Error in allocation"); /* or better malloc error handling */
strncpy(new_user->name, name,256); /* not sure if I got the argument order right... */
new_user->counter = 0; /* or 1 depending on your prefered convention */
new_user->next = NULL;
return new_user;
}
It ease the debugging like you wouldn't believe! Then it's just a matter of rewriting your main function:
int main() {
char userName [10];
int found = 0, go_on = 1;
user *user_head = NULL, *new_user,*temp;
while (go_on == 1) {
printf ("Username: ");
scanf("%s", userName);
if( (new_user = user_match_name(user_head,userName)) )
++new_user->counter
else
new_user = create_user(userName);
/* Here we push on the Sll */
if(user_head){
new_user->next = user_head;
user_head = new_user;
} else {
user_head = new_user;
}
printf ("Go on? (1/0)");
scanf("%d", &go_on);
printf ("Current list: ");
for (temp = user_head; temp; temp = temp->next)
printf("%s %d\n", temp->name, temp->counter);
//printf ("The first one in list: %s\n", first->name); - this prints the correct first
}
}
Ahhhhhh! Much easier to read. Be mindful of: 1) I didn't compile check the code. The important ideas are there, leverage them. 2) Even in your previous implementation, you are white space vulnerable but that's somewhat another topic.
Or you could cimply fix it by doing:
typedef struct _user
{
char name[10];
int counter;
struct _user *next;
} user;
and strncpy(new->name,userName,10) instead of assigning the pointer.
I have been busy with a question from a C book. The question is simple but it has some specific parts.
I would like to ask a question about arrays.
My question is about the best way with creating an array of a structure. The question wants these all;
Firstly create an array of structure. Secondly, create a linked list which connects these arrays with a restp pointer.
I want to divide my question into sub parts. First part is array of structure...
How can I create an array of a structure. I've made a research about this. And here is my way:
I'm creating a structure for my array of structure:
struct student{
int id;
struct courseList_node_s *restp;
};
And my linked list for completing rest of question:
typedef struct courseList_node_s{
char course[6];
int credit,
section;
struct courseList_node_s *restp;
}courseList_node_t;
I have implemented some function to handle this student schedule.
In my get_studentList function;
I declared my array as this;
struct student *ansp[size];
And making memory allocation;
ansp[i] = malloc(sizeof(struct student));
And lastly assigning a value;
ansp[i]->id =id;
Now, my problem is while creating an array, I couldn't make it as an ordered array. For instance, the user can type 1111, 1222, 1232, and then 1011. So, my first element of array which is ansp[0] = 1011, and ansp[1] = 1111.
I couldn't figure out.
Can you give me an algorithm which consist these(Creating an ordered array of structure).
Lastly, sorry for my bad English and I may made some grammatical mistakes...
Thanks in advance.
To order the elements, you will need to sort them. In C, you probably want to use qsort (in C++ there are easier ways). You will need to define a comparison function on struct student * and call qsort on your array with it.
See this example for inspiration. Note that your array is an array of structure pointers, the example is an array of direct structures (which is maybe what you wanted anyway?).
Can you give me an algorithm which consist these(Creating an ordered array of structure).
If you want to create an orderd array of structures, you probably want to build a tree.
There are libraries for that, but to learn and understand, you can Google 'Binary trees in C' or something like that, e.g.:
http://www.macs.hw.ac.uk/~rjp/Coursewww/Cwww/tree.html
Trees will allow your user to insert non-sorted values and retrieve them in sorted order (also, search them more quickly).
I'd solved the problem with helps #Keith Randall and
lserni
I have implemented both binary search tree and array of structure.
First way, sorting array with qsort:
I had to create a compare function:
int compare(const void *p1, const void *p2){
return (* (struct student **) p1)->id - (* (struct student **) p2)->id;
}
And my other helper functions;
void get_studentList(struct student **listp,int size){
int id,i;
struct student *ansp[size];
for(i=0;i<size;i++){
printf("Enter student's id to exit enter -1> ");
scanf("%d", &id);
ansp[i] = malloc(sizeof(courseList_node_t));
ansp[i]->id = id;
ansp[i]->restp = NULL;
}
qsort (ansp, size, sizeof(struct student *), compare);
for(i=0;i<size;i++){
listp[i] = ansp[i];
}
}
courseList_node_t * insert_studentSchedule(courseList_node_t *headp, int size){
courseList_node_t *cur_nodep;
if(headp == NULL){
cur_nodep = scan_course();
headp = cur_nodep;
} else {
headp->restp = insert_studentSchedule(headp->restp,size);
}
return (headp);
}
And my display function;
void display_schedule(struct student **headp, int size){
courseList_node_t *cur_nodep;
int i = 0;
while(i< size){
cur_nodep = headp[i]->restp;
printf("Student id > %d\n", headp[i]->id);
while(cur_nodep != NULL){
printf("Course name> %s\t", cur_nodep->course);
printf("Course credit> %d\t", cur_nodep->credit);
printf("Course section> %d\n", cur_nodep->section);
cur_nodep = cur_nodep->restp;
}
i++;
}
}
Second way, Binary Search Tree:
I changed typedef parts of my header file as this:
typedef struct tree_node_s{
int id;
struct courseList_node_s *restp;
struct tree_node_s *leftp, *rightp;
}tree_node_t;
And my macro to formalize a standart pattern in dynamic allocation of nodes:
#define TYPED_ALLOC(type) (type *)malloc(sizeof(type))
And my implementation of creating a binary search tree:
/*
* Insert a new id in a binary search tree.
* Pre: rootp points to the root node of a binary search tree
*/
tree_node_t * get_studentTree(tree_node_t *rootp, int newId)
{
if (rootp == NULL){
rootp = TYPED_ALLOC(tree_node_t);
rootp->id = newId;
rootp->restp = NULL;
rootp->leftp = NULL;
rootp->rightp = NULL;
} else if ( newId == rootp->id){
/* */
} else if (newId < rootp->id){
rootp->leftp = get_studentTree(rootp->leftp, newId);
} else {
rootp->rightp = get_studentTree(rootp->rightp, newId);
}
return (rootp);
}
This parts are not related with this question. I gave them because I want to share the partial solution of real question.
/*
* Its aim to add courses to restp component of subtree
* It may have some problems. And you can omit it. Because it not related with this question
* Pre: elementp not empty
*/
courseList_node_t * add_course(courseList_node_t *nextp, courseList_node_t *elementp){
if(nextp->restp == NULL){
nextp->restp = elementp;
} else {
nextp->restp = add_course(nextp->restp,elementp);
}
return (nextp);
}
/*
* It is not neccessary to first call get_studentTree function. It simply creates a linked list which consist of student class/lecture schedule.
* Pre: ele and id not empty
* Post: Tree returned includes all schedule and retains binary search tree properties.
*/
tree_node_t * insert_studentSchedule(tree_node_t *rootp,courseList_node_t *ele, int id){
if (rootp == NULL){
rootp = get_studentTree(rootp, id);
rootp->restp = TYPED_ALLOC(courseList_node_t);
strcpy(rootp->restp->course, ele->course);
rootp->restp->credit = ele->credit;
rootp->restp->section = ele->section;
}
else if(rootp->id == id){
if ( rootp->restp == NULL ){
rootp->restp = TYPED_ALLOC(courseList_node_t);
strcpy(rootp->restp->course, ele->course);
rootp->restp->credit = ele->credit;
rootp->restp->section = ele->section;
} else {
rootp->restp = add_course(rootp->restp, ele);
}
} else if ( id < rootp->id ){
if ( rootp->leftp != NULL )
rootp->leftp = insert_studentSchedule(rootp->leftp, ele, id);
} else if ( id > rootp->id ) {
if ( rootp->rightp != NULL )
rootp->rightp = insert_studentSchedule(rootp->rightp, ele, id);
}
return (rootp);
}
/*
* Course scanning function
*/
courseList_node_t * scan_course(void){
courseList_node_t *cur_coursep;
char courseName[6];
cur_coursep = (courseList_node_t *)malloc(sizeof(courseList_node_t));
printf("Welcome to course scanning part>\n");
printf("Enter the name of course> ");
scanf("%s", courseName);
strcpy(cur_coursep->course, courseName);
printf("Enter the credit of course> ");
scanf("%d", &cur_coursep->credit);
printf("Enter the section of course> ");
scanf("%d", &cur_coursep->section);
cur_coursep->restp = NULL;
return (cur_coursep);
}
/*
* My way to print binary search tree with all elements
*/
void display_schedule(tree_node_t *rootp){
courseList_node_t *cur_course;
if(rootp == NULL)
return;
display_schedule(rootp->leftp);
if (rootp->restp == NULL)
printf("Tree with id: %d element has no member!", rootp->id);
else {
cur_course = rootp->restp;
while (cur_course != NULL){
printf("Student Id> %d\n", rootp->id);
printf("Course name> %s\t", rootp->restp->course);
printf("Course credit> %d\t", rootp->restp->credit);
printf("Course section> %d\n", rootp->restp->section);
cur_course = cur_course->restp;
}
}
display_schedule(rootp->rightp);
}
It may not full solution of book question but with your helps, It is solution of essential parts. If you found a mistake. Feel free to add a comment.