This is a follow up to this question:
sorting structs in C with pointers
I've revised my revised code and I think the sort should be working but I get the feeling that I'm not using the pointers correctly. My printf statements aren't showing up on the console, they are labeled in the comments.
I'm new to C so this may be obvious but I'm just lost as to how to debug when print statements don't print.
Current compiler warnings:
Q1.c: In function 'generate':
Q1.c:28: warning: implicit declaration of function 'time'
Q1.c:35: warning: implicit declaration of function 'dupe'
Q1.c: In function 'output':
Q1.c:61: warning: implicit declaration of function 'sort'
Q1.c: At top level:
Q1.c:68: warning: conflicting types for 'sort'
Q1.c:61: warning: previous implicit declaration of 'sort' was here
Q1.c: In function 'sort':
Q1.c:82: warning: implicit declaration of function 'deallocate'
Q1.c: At top level:
Q1.c:90: warning: conflicting types for 'deallocate'
Q1.c:82: warning: previous implicit declaration of 'deallocate' was here
The code is:
#include <stdio.h>
#include<stdlib.h>
#include<math.h>
int SIZE = 10;
static char c[] = "------------------------------\n";
struct student{
int id;
int score;
};
struct student* allocate(){
/*Allocate memory for ten students*/
struct student *s = malloc(SIZE* sizeof*s);
/*return the pointer*/
return s;
}
void generate(struct student* students){
/*Generate random ID and scores for ten students, ID being between 1 and 10, scores between 0 and 100*/
srand((unsigned int)time(NULL));
int id[SIZE];
int y;
for (int i = 0; i < SIZE; i++){
do{
y = rand() % SIZE + 1;
} while(dupe(id, i, y));
id[i] = y;
}
for (int j = 0; j < SIZE; j++){
students[j].id = id[j];
students[j].score = rand() % 101;
printf("ID: %d\tScore: %d\n", students[j].id, students[j].score);
}
}
int dupe(int id[], int SIZE1, int i){
for (int x = 0; x < SIZE1; x++){
if(id[x] == i)
return 1;
}
return 0;
}
void output(struct student* students){
/*Output information about the ten students in the format:
ID1 Score1
ID2 score2
ID3 score3
...
ID10 score10*/
sort(students);
printf("post sort students.\n %s", c);
for(int x = 0; x < SIZE; x++){
printf("ID: %d\tScore: %d\n", students[x].id, students[x].score); //print stmt not showing
}
}
void sort(struct student* students){
struct student *sd = allocate();
struct student *stud;
for(int i = 0; i < SIZE; i++){
stud = &students[i];
sd[stud->id -1] = *stud;
}
printf("sorted SD.\n %s", c);
for(int x = 0; x < SIZE; x++){
printf("ID: %d\tScore: %d\n", sd[x].id, sd[x].score); //print stmt not showing
}
students = sd;
deallocate(sd);
}
void summary(struct student* students){
/*Compute and print the minimum, maximum and average scores of the ten students*/
}
void deallocate(struct student* stud){
/*Deallocate memory from stud*/
free(stud);
}
int main(){
struct student* stud = NULL;
/*call allocate*/
stud = allocate();
/*call generate*/
generate(stud);
/*call output*/
printf("%s", c);
output(stud);
/*call summary*/
/*call deallocate*/
deallocate(stud);
return 0;
}
"My printf statements aren't showing up on the console"
Are you sure that your program didn't crash before it got that far?
Since stud has type student*, &stud has type student**, but you are passing it to functions that expect student* ... just pass stud, not &stud. Turn on warnings in your compiler and it will tell you about such things.
assert(s != 0);
This is improper practice. assert should only be used to test for logic errors, not for normal failure conditions such as out of memory.
struct student *s = malloc(size*(sizeof(struct student)));
This is ok, but I recommend
struct student* s = malloc(size * sizeof *s);
as it is less verbose and doesn't depend on the type.
static int size = 10;
In C, this is not a constant (and doesn't become one by adding a const keyword). Since you use it as the size of local arrays, you are invoking the VLA (variable-length array) feature that is not available in all C compilers. In C, it's more normal to do
#define SIZE 10
or
enum { SIZE = 10 };
This is going to cause you trouble:
ID being between 1 and 10
(aside from the fact that it should say "1 and SIZE"). You allocate a SIZE element array and then use your student IDs as indices, but only 0..SIZE-1 are valid indices ... SIZE is not. So you need to index by student->id - 1, or make your IDs 0-indexed.
y = rand() % size + 1;
while(dupe(id, i, y)){
y = rand() % size + 1;
}
That can be written as
do
{
y = rand() % size + 1;
} while(dupe(id, i, y));
However, I don't think this does what you want it to do. You're assuring that the student ID is different from the index, but there's no reason to do that. What you want to assure is that no two student IDs are the same, but you aren't doing that. One possibility is to scan all the previously assigned IDs and pick another one if it was already assigned. Another way is to put all the IDs, 1 .. SIZE, in an array, then pull items out of the array at random, moving the top element of the array into that slot and decreasing the size of the array by 1 until you've emptied the array and assigned all the IDs.
(students + j)->id
C has some equivalence rules: *(x + y) === x[y], and x->y === (*x).y. So, (students + j)->id === (*(students + j)).id === students[j].id, which is the preferred way to write that.
students = &sd;
This statement doesn't do anything since students isn't used after it, and it's a type error (&sd has type student**), which, again, your compiler will warn you about if you turn on warnings (-Wall for gcc).
What you're trying to do here is change students in the caller, but this doesn't do that. You need to either pass the address of students in (i.e., have a struct student** pstudents argument which you then dereference to get students) or, better, return the new array (which must not be deallocated until you're done using it).
This list of issues is not necessarily exhaustive.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With