fopen results in segfault - c

As in the headline.
Simple exercise, trying to learn structures and other essential c functionality.
Here is a structure containing a char[] and a number, I try to save its values in a file and read them back.
I read through a lot of topics concerning Seg.fault by fopen(), but can't find my mistake!
Someone here who knows why fopen() does crash in this instance?
Any suggestions and criticism on the matter is welcome!
The function where the Segfault happens is load():
void load(struct Telephon *structure, int *counter)
{
char filename[255];
char puffer[255], puffercpy[255];
int i, c, newline_count;
size_t strlaen;
FILE *datei=NULL;
char *token=NULL;
printf("\033[0;35mWelche Datei oeffnen?\033[0m\n");
scanf("%s", filename);
//emptystdin();
//strlaen=strlen(filename);
//printf("%d", strlaen);
//filename[strlaen+1] = '\0';
//printf("\n%s", filename);
datei = fopen(filename, "r");
if(datei==NULL)
{
printf("\033[0;31mKonnte Datei %s nicht oeffnen.\033[0m\n", filename);
}
else
{
while ( (c=fgetc(datei)) != EOF ) //count lines of file
{
if ( c == '\n' )
{
newline_count++;
}
}
for(i=0; i<=newline_count; i++) //get values in between ";"
{
fgets(puffer, 254, datei);
strcpy(puffercpy, puffer);
token = strtok(puffercpy, ";");
*counter = atoi(token);
token = strtok(NULL, ";");
strcpy(structure[i].name, token);
token = strtok(NULL, ";");
structure[i].nummer = atoi(token);
}
fclose(datei);
}
return;
}
The whole code, main is at the end:
telephonListen.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#define MAX 100
struct Telephon
{
char name[210];
unsigned int nummer;
}TELE[MAX];
char* gotTime(char *timestrg)
{
time_t now;
now = time(NULL);
strftime (timestrg, 19, "%d.%m.%Y, %H:%M", localtime (&now));
return timestrg;
}
void printT(struct Telephon *structarray, int addcount)
{ int i;
if(addcount==0)
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
else
{
for(i=0; i<addcount; i++)
{
printf("\nEintrag Nr.%d\n%s:\t%d\n",i+1, structarray[i].name, structarray[i].nummer);
}
return;
}
}
void eingabe(int num, struct Telephon *structarray)
{
size_t inputlen;
int check;
if(num>MAX)
{
printf("\033[0;31mMaximale Anzahl von Eintraegen erreicht!\033[0m\n");
return;
}
else
{
printf("\n\033[0;35mNamen eingeben:\t\033[0m");
//fgets(structarray[num].name, MAX, stdin);
fgets(structarray[num].name, 209, stdin);
inputlen=strlen(structarray[num].name);
structarray[num].name[inputlen-1]='\0';
printf("\n\033[0;35mNummer eingeben:\t \033[0m");
do
{
check = scanf("%10u", &structarray[num].nummer);
}while( getchar()!='\n');
fflush(stdin);
if(check==1)
{
printf("Ihr Kontakt wurde angelegt!\n%s:\t%u\n", structarray[num].name ,structarray[num].nummer);
}
else
{
printf("Fehler bei der Eingabe. Kontakt wurde nicht angelegt!");
return;
}
return;
}
}
void writeFile(struct Telephon *structure, char *zeitf, int counter)
{
char filename[255];
int i;
FILE *datei;
if(counter>0)
{
printf("\033[0;35mIn welche Datei soll das Telephonbuch geschrieben werden?\n(Achtung: Vorhandene Dateien werden ueberschrieben!)\t\033[0m\n");
scanf("%s", filename);
getchar();
datei = fopen(filename, "w");
if(NULL == datei)
{
printf("\033[0;31mKonnte Datei %s nicht öffnen.\033[0m\n", filename);
}
fprintf(datei, "Telephonverzeichnis vom %s\nNAME\t\t|NUMMER\n\n", zeitf);
for(i=0; i<counter; i++)
{
fprintf(datei, "%s\t\t|%d\n", structure[i].name, structure[i].nummer);
}
printf("\033[0;32mDatei gespeichert.\033[0m\n");
fclose(datei);
}
else
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
return;
}
void change(struct Telephon *structure, int count)
{
int eintragnum;
if (count == 0)
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
else
{
printT(structure, count);
printf("\033[0;31mWelcher Eintrag soll geaendert werden?\033[0m\n");
do
{
scanf("%d", &eintragnum);
}while(getchar()!='\n');
if(eintragnum<1||eintragnum>count)
{
printf("\033[0;31mBitte die Nummer [zwischen %d und %d]\n des zu aendernden Eintrags eingeben!\033[0m\n", 1, count);
}
else
{
eingabe(eintragnum-1, structure);
}
}
return;
}
void emptystdin()
{
int c;
while( ((c = getchar()) != EOF) && (c != '\n') );
}
void searchContact(struct Telephon *structure, int count)
{
char searchC;
int inputlen;
int i=0;
int countcompare;
if (count == 0)
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
return;
}
else
{
printf("Anfangsbuchstabe:\t");
scanf("%c", &searchC);
emptystdin();
for(i=0; i<count; i++)
{
if(structure[i].name[0]==searchC)
{
printf("Eintrag gefunden:\n");
printf("Nr. %d\nName:\t%s\nNummer:\t%u\n", i+1, structure[i].name, structure[i].nummer);
}
}
return;
}
}
void save(struct Telephon *structure, int counter)
{
char filename[255];
int i;
FILE *datei;
if(counter>0)
{
printf("\033[0;35mUnter welchem Dateinamen speichern?\n(Achtung: Vorhandene Dateien werden ueberschrieben!)\t\033[0m\n");
scanf("%s", filename);
emptystdin();
datei = fopen(filename, "w");
if(NULL == datei)
{
printf("\033[0;31mKonnte Datei %s nicht anlegen.\033[0m\n", filename);
}
for(i=0; i<counter; i++)
{
fprintf(datei, "%d;%s;%d\n", i+1, structure[i].name, structure[i].nummer);
}
printf("\033[0;32mDatei gespeichert.\033[0m\n");
fclose(datei);
}
else
{
printf("\033[0;31mEs sind noch keine Eintraege vorhanden!\033[0m\n");
}
return;
}
void load(struct Telephon *structure, int *counter)
{
char filename[255];
char puffer[255], puffercpy[255];
int i, c, newline_count;
size_t strlaen;
FILE *datei=NULL;
char *token=NULL;
printf("\033[0;35mWelche Datei oeffnen?\033[0m\n");
scanf("%s", filename);
//emptystdin();
//strlaen=strlen(filename);
//printf("%d", strlaen);
//filename[strlaen+1] = '\0';
//printf("\n%s", filename);
datei = fopen(filename, "r");
if(datei==NULL)
{
printf("\033[0;31mKonnte Datei %s nicht oeffnen.\033[0m\n", filename);
}
else
{
while ( (c=fgetc(datei)) != EOF ) //Zeilen in Datei zählen
{
if ( c == '\n' )
{
newline_count++;
}
}
for(i=0; i<=newline_count; i++) //CVS parsen/auslesen
{
fgets(puffer, 254, datei);
strcpy(puffercpy, puffer);
token = strtok(puffercpy, ";");
*counter = atoi(token);
token = strtok(NULL, ";");
strcpy(structure[i].name, token);
token = strtok(NULL, ";");
structure[i].nummer = atoi(token);
}
fclose(datei);
}
return;
}
int main(void)
{
int auswahl;
int count = 0;
char zeit[20];
char buffer[2];
struct Telephon *structptr; //malloc(MAX*(sizeof(TELE)));
structptr = TELE;
gotTime(zeit);
system("clear");
printf("Telephonkontaktverwaltung\t%s\n", zeit);
do
{
printf("\033[30;47m1: Kontakt hinzufuegen\t2: Kontakte anzeigen\n3: Kontakt aendern\t4: Als Datei speichern\n5. Kontakt suchen\n6. Als CVS sichern\t7. Aus CVS laden\n8. Beenden\nEine der Ziffern eingeben, mit Enter bestaetigen\033[0m\n");
/*
scanf("%d", &auswahl);
scanf("%c", &buffer);
fgets(buffer, 2, stdin);
if(isdigit(buffer[1]))
{
auswahl=atoi(buffer);
}
else
{
printf("Eine der Nummern eingeben um Aktion auszufuehren!\n");
}
do
{
scanf("%d", &auswahl);
}while(getchar()!='\n');
fgets(buffer, 2, stdin);
sscanf(buffer, "%d", &auswahl);
*/
scanf("%d", &auswahl);
emptystdin();
switch (auswahl)
{
case 1 : eingabe(count++, structptr);
break;
case 2 : printT(structptr, count);
break;
case 3 : change(structptr, count);
break;
case 4 : writeFile(structptr, gotTime(zeit), count);
break;
case 5 : searchContact(structptr, count);
break;
case 6 : save(structptr, count);
break;
case 7 : load(structptr, &count);
break;
case 8 : printf("ENDE\n");
break;
default : printf("Eine der Nummern eingeben um Aktion auszufuehren!\n");
break;
}
}while(auswahl!=8);
return EXIT_SUCCESS;
}

Use rewind().
Between the while() and for() loops, the file need to start at the beginning again.
while ( (c=fgetc(datei)) != EOF ) //count lines of file
{ ...}
rewind(datei);
for(i=0; i<=newline_count; i++) //get values in between ";"
{ ...}
Strongly suggest avoid using scanf() and fgets(,,stdin). Recommend one. Preferable fgets().
You likely want scanf(" %c", instead of scanf("%c",. (Add space).
Minor Idea:
Not that English is the be-all end-all language, but OP may want to consider something like
// Bold Red "Could not create file" EOL
const char *Err_FileCreation_format = "\033[0;31mKonnte Datei %s nicht anlegen.\033[0m\n"
printf(Err_FileCreation_format, filename);
// or
#define Err_FileCreation_fmt1 "\033[0;31mKonnte Datei "
#define Err_FileCreation_fmt2 " nicht anlegen.\033[0m\n"
printf(Err_FileCreation_fmt1 "%s" Err_FileCreation_fmt2, filename);

Assuming undefined behaviour hadn't been invoked prior to a call to fopen() the only way to make it crash is to pass it a non-initialised or non-0-terminated character array as file name or mode.
So to avoid this properly initialise all variables used to hold a file name and/or mode by declaring it like:
char filename[256] = "";
To avoid allowing scanf() to read in more then filenamecan hold do like this:
scanf("%255s", filename);
Update:
This code
while ( (c=fgetc(datei)) != EOF ) //count lines of file
{
if ( c == '\n' )
{
newline_count++;
}
}
reads until the end of the file.
So this code
for(i=0; i<=newline_count; i++) //get values in between ";"
{
fgets(puffer, 254, datei);
strcpy(puffercpy, puffer);
token = strtok(puffercpy, ";");
*counter = atoi(token);
token = strtok(NULL, ";");
strcpy(structure[i].name, token);
token = strtok(NULL, ";");
structure[i].nummer = atoi(token);
}
would not be able to read anything, as eof had already been reached.
However the code does not test whether fgets() might have failed but happily starts parsing what it didn't read and ... crashes during atoi()ing a token pointing to NULL.

Related

Why does this code not work in Linux if it shows an error message

I have to make the labyrinth program, which works in Windows under Code Blocks; but when I want to run it in Linux it doesn't work.
When I start debugging, it works correctly until line 63 returns and crashes.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
Quit
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max_col 50
#define max_row 50
#define max_numOflabyrinth 50
#define max_checkPt 50
#define MAX_LINES 10
#define MAX_LINE_LENGTH 2506
enum{UP, DOWN, LEFT, RIGHT};
typedef struct POSITION{
int x;
int y;
} POSITION;
typedef struct PFAD{
POSITION* pos;
int step;
} PFAD;
typedef struct CHECKPOINT{
int seqNum;
int total_span;
int next_span;
int stepNum;
POSITION pos;
POSITION next_steps[3];
//CHECKPOINT* previous_checkPt; //C don't support this.
} CHECKPOINT;
typedef struct LIS_CHECKPOINT{
CHECKPOINT checkPt;
CHECKPOINT* prev_checkPt;
} LIS_CHECKPOINT;
typedef struct LABYRINTH{
char name[10];
char** landkarte; //2D-array landkarte[y][x] y=row x=col
int max_x;
int max_y;
int max_step; //max. laufzeit für while()
POSITION start;
POSITION end;
} LABYRINTH;
int pos_cmp(POSITION a, POSITION b){
if(a.x == b.x && a.y == b.y){return 1;}
else{return 0;}
}
void pos_set(POSITION* des, const POSITION src){
des->x = src.x;
des->y = src.y;
}
void init_LABYRINTH(LABYRINTH* laby){
laby->landkarte=NULL;
laby->max_x=0;
laby->max_y=0;
laby->max_step=0;
laby->start.x=0;
laby->start.y=0;
laby->end.x=0;
laby->end.y=0;
}
/*
int erkunden(LABYRINTH* labyrinth){
POSITION cur_pos;
pos_set(&cur_pos, labyrinth->start);
POSITION check_steps[3]; //only three directions
PFAD footprt;
footprt.pos = calloc(labyrinth->max_x*labyrinth->max_y, sizeof(POSITION));
footprt.step = 0;
CHECKPOINT* prt_last_
}
*/
int erkunden(LABYRINTH* labyrinth){
fflush(stdin);
POSITION cur_pos;
//initialisieren
pos_set(&cur_pos, labyrinth->start);
POSITION check_steps[3]; //max. möglich 3 Richtung
PFAD footprt;
footprt.pos = calloc(labyrinth->max_x*labyrinth->max_y, sizeof(POSITION));
footprt.step = 0;
CHECKPOINT* ptr_last_checkPt;
LIS_CHECKPOINT* lis_checkPt;
lis_checkPt = calloc(max_checkPt, sizeof(LIS_CHECKPOINT));
int total_checkPt=0;
int i, j;
int if_break=1;
int numOFsteps=0;
int loopcontroll=0;
char** map= calloc(labyrinth->max_y, sizeof(char*));
for(i=0;i<labyrinth->max_y;i++){
map[i]=calloc(labyrinth->max_x, sizeof(char));
}
while(!pos_cmp(cur_pos, labyrinth->end) && if_break){
map[cur_pos.y][cur_pos.x]=1;
pos_set(&footprt.pos[footprt.step], cur_pos);
//oben
if(cur_pos.y-1>=0 && labyrinth->landkarte[cur_pos.y-1][cur_pos.x]!='w' && map[cur_pos.y-1][cur_pos.x]!=1){
check_steps[numOFsteps].x=cur_pos.x;
check_steps[numOFsteps].y=cur_pos.y-1;
numOFsteps++;
}
//unten
if(cur_pos.y+1<labyrinth->max_y && labyrinth->landkarte[cur_pos.y+1][cur_pos.x]!='w' && map[cur_pos.y+1][cur_pos.x]!=1){
check_steps[numOFsteps].x=cur_pos.x;
check_steps[numOFsteps].y=cur_pos.y+1;
numOFsteps++;
}
//links
if(cur_pos.x-1>=0 && labyrinth->landkarte[cur_pos.y][cur_pos.x-1]!='w' && map[cur_pos.y][cur_pos.x-1]!=1){
check_steps[numOFsteps].x=cur_pos.x-1;
check_steps[numOFsteps].y=cur_pos.y;
numOFsteps++;
}
//rechts
if(cur_pos.x+1<labyrinth->max_x && labyrinth->landkarte[cur_pos.y][cur_pos.x+1]!='w' && map[cur_pos.y][cur_pos.x+1]!=1){
check_steps[numOFsteps].x=cur_pos.x+1;
check_steps[numOFsteps].y=cur_pos.y;
numOFsteps++;
}
if(numOFsteps==0){
do{
ptr_last_checkPt=lis_checkPt[ptr_last_checkPt->seqNum].prev_checkPt;
j=(++ptr_last_checkPt->next_span);
}
while(ptr_last_checkPt->next_span > ptr_last_checkPt->total_span-1);
pos_set(&cur_pos, ptr_last_checkPt->next_steps[j]);
footprt.step=ptr_last_checkPt->stepNum;
}
else if(numOFsteps==1){
pos_set(&cur_pos, check_steps[0]);
}
else {
ptr_last_checkPt = &lis_checkPt[total_checkPt].checkPt;
ptr_last_checkPt->seqNum=total_checkPt;
if(total_checkPt==0){
lis_checkPt[total_checkPt].prev_checkPt=NULL;}
else{
lis_checkPt[total_checkPt].prev_checkPt=&lis_checkPt[total_checkPt-1].checkPt;
}
for(i=0;i<numOFsteps;i++){
pos_set(&ptr_last_checkPt->next_steps[i], check_steps[i]);
}
pos_set(&ptr_last_checkPt->pos, cur_pos);
ptr_last_checkPt->total_span=numOFsteps;
ptr_last_checkPt->next_span=0;
ptr_last_checkPt->stepNum=footprt.step;
pos_set(&cur_pos, ptr_last_checkPt->next_steps[0]);
total_checkPt++;
}
numOFsteps=0;
footprt.step++;
loopcontroll++;
if(loopcontroll>labyrinth->max_step) if_break=0;
}//end loop
//save the solution in the labyrith
for(i=0;i<footprt.step;i++){
labyrinth->landkarte[footprt.pos[i].y][footprt.pos[i].x]='*';
}
//free
free(footprt.pos);
free(lis_checkPt);
for(i=0;i<labyrinth->max_y;i++) free(map[i]);
free(map);
//rückgabewert
if(loopcontroll>labyrinth->max_step) return 1;
else return 0;
}
FILE* open_labyrinth_file(char* file_name){
FILE* file_landkarte = fopen(file_name, "r");
if (file_landkarte==NULL){
printf("Fehler bei Einlesen der Text-Datei\n");
return NULL;
}
printf("\"%s\" eingelesen!\n",file_name);
return file_landkarte;
}
LABYRINTH* load_labyrinth(const char* map_line, int max_x_size, int max_y_size){
LABYRINTH* labyrinth=NULL;
init_LABYRINTH(labyrinth);
int map_size = strlen(map_line)-1; //
int i=0,j=0,k=0; //variables to help
labyrinth->max_step=0;
int b=0, z=0;
//name for the Labyrinth
for(i=0;i<6;i++){
if(map_line[i] == '='){
labyrinth->name[i] = '\0';
break;
}else{
labyrinth->name[i] = map_line[i];
}
}
k = strlen(labyrinth->name)+1;
map_size -= k;
for(i=k; i<max_x_size; i++){
//if the labyrinth is not quadratic i.e. has an exact root
if(i*i == map_size){
labyrinth->max_x=i;
labyrinth->max_y=i;
break;
}
if(i*i>map_size){
printf("Dimensions incorrect: map not quaratic!: %s \n", labyrinth->name);
return NULL;
}
}
//loop to check that the maze contains one exit and one entrance
for(i=k;i<map_size;i++){
if(map_line[i]=='b'){b=1;}
if(map_line[i]=='z'){z=1;}
}
if(b!=1||z!=1){
printf("The map not contains an start and an end: %s \n", labyrinth->name);
return NULL;
}else{
printf("The map contains an start and an end: %s \n", labyrinth->name);
}
labyrinth->landkarte = calloc(labyrinth->max_y, sizeof(char*));
for(i=0;i<labyrinth->max_y;i++){
labyrinth->landkarte[i] = calloc(labyrinth->max_x, sizeof(char*));
}
for(i=0;i<labyrinth->max_y;i++){
for(j=0;j<labyrinth->max_x;j++){
labyrinth->landkarte[i][j]=map_line[i*labyrinth->max_x+j+k];
if(labyrinth->landkarte[i][j]=='b'){
labyrinth->start.x=j;
labyrinth->start.y=i;
}
if(labyrinth->landkarte[i][j]=='z'){
labyrinth->end.x=j;
labyrinth->end.y=i;
}
if(labyrinth->landkarte[i][j]=='k'){
labyrinth->max_step+=2;
}
}
}
return labyrinth;
}
/*
LABYRINTH* load_labyrinth(const char* landkarte_zeile, int max_x_size, int max_y_size){
int landkarte_size=strlen(landkarte_zeile);
int i,j,k;
LABYRINTH* labyrinth;
init_LABYRINTH(labyrinth);
labyrinth->max_step=0;
if(max_x_size!=max_y_size){
printf("Dimensionsangaben fehlerhaft: max_x und max_y muss identisch sein!/n");
return NULL;
}
for(i=0;i<5;i++){
if(landkarte_zeile[i]=='='){
labyrinth->name[i]='\0';
break;
}
labyrinth->name[i] = landkarte_zeile[i];
}
k=strlen(labyrinth->name)+1;
landkarte_size-=k;
for(i=3;i<=max_x_size;i++){
if(i*i==landkarte_size){
labyrinth->max_x=i;
labyrinth->max_y=i;
break;
}
if(i*i>landkarte_size){
printf("Dimensionen fehlerhaft: Landkarte nicht quaratisch!: %s \n",labyrinth->name);
return NULL;
}
}
labyrinth->landkarte = calloc(labyrinth->max_y, sizeof(char*));
for(i=0;i<labyrinth->max_y;i++){
labyrinth->landkarte[i] = calloc(labyrinth->max_x, sizeof(char*));
}
for(i=0;i<labyrinth->max_y;i++){
for(j=0;j<labyrinth->max_x;j++){
labyrinth->landkarte[i][j]=landkarte_zeile[i*labyrinth->max_x+j+k];
if(labyrinth->landkarte[i][j]=='b'){
labyrinth->start.x=j;
labyrinth->start.y=i;
}
if(labyrinth->landkarte[i][j]=='z'){
labyrinth->end.x=j;
labyrinth->end.y=i;
}
if(labyrinth->landkarte[i][j]=='k'){
labyrinth->max_step+=2;
}
}
}
return labyrinth;
}
*/
/*
//old
char* print_labyrinth(LABYRINTH* labyrinth){
if(labyrinth==NULL){
printf("Plot-Fehler: kein Labyrith gefunden.\n");
return;
}
char buffer[100];
char character = 'c';
int i,j;
printf("Labyrinth: %s\n", labyrinth->name);
//strcat(buffer, labyrinth->name);
for(i=0;i<labyrinth->max_y;i++){
for(j=0;j<labyrinth->max_x;j++){
if(labyrinth->landkarte[i][j]=='w'){
character = '#';
printf(character);
strncat(buffer, &character, 1);
}
else if(labyrinth->landkarte[i][j]=='k'){
printf(" ");
//strcat(buffer, ' ');
}
else{
printf("%c", labyrinth->landkarte[i][j]);
//strcat(buffer, labyrinth->landkarte[i][j]);
}
}
printf("\n");
//strcat(buffer,"\n");
}
printf("Start: (%i,%i) ", labyrinth->start.x,labyrinth->start.y);
printf("End: (%i,%i)\n", labyrinth->end.x,labyrinth->end.y);
return buffer;
} */
//new
char* print_labyrinth(LABYRINTH* labyrinth) {
if (labyrinth == NULL) {
return strdup("Plot-Fehler: kein Labyrinth gefunden.\n");
}
char* buffer = malloc(sizeof(char) * 10000);
if (buffer == NULL) {
// handle error
}
int offset = 0;
offset += sprintf(buffer + offset, "Labyrinth: %s\n", labyrinth->name);
for (int i = 0; i < labyrinth->max_y; i++) {
for (int j = 0; j < labyrinth->max_x; j++) {
if (labyrinth->landkarte[i][j] == 'w') {
offset += sprintf(buffer + offset, "#");
} else if (labyrinth->landkarte[i][j] == 'k') {
offset += sprintf(buffer + offset, " ");
} else {
offset += sprintf(buffer + offset, "%c", labyrinth->landkarte[i][j]);
}
}
offset += sprintf(buffer + offset, "\n");
}
offset += sprintf(buffer + offset, "Start: (%i,%i) End: (%i,%i)\n",
labyrinth->start.x, labyrinth->start.y, labyrinth->end.x, labyrinth->end.y);
printf("%s", buffer);
return buffer;
}
void save_to_file(char* text, char* filename) {
FILE* file = fopen(filename, "wt");
if (file == NULL) {
printf("Error opening file.\n");
return;
}
fprintf(file, "%s", text);
fclose(file);
printf("Text saved to file %s\n", filename);
}
int main()
{
/*
int i,j,k;
int *ergibnis;
int total_labyr=0;
char charbuff[2506]={'\0'};
char* solution = malloc(sizeof(char) * 10000);
int offset = 0;
LABYRINTH** labyrinth[max_numOflabyrinth];
FILE* file_landkarte = open_labyrinth_file("labyrinth_karte.txt");
if(fgets(charbuff,2506,file_landkarte)!=EOF){
labyrinth[total_labyr]=load_labyrinth(charbuff, 50, 50);
total_labyr++;
}
ergibnis = calloc(total_labyr, sizeof(int));
for(i=0;i<total_labyr;i++){
if(!erkunden(labyrinth[i])){ // ! weil erkunden liefert 0 wenn erfolgreich ist
ergibnis[i] = 1;
offset += sprintf(solution + offset, print_labyrinth(labyrinth[j]));
}
}
print_labyrinth(labyrinth);
save_to_file(solution, "solvelab.txt");
*/
LABYRINTH* labyrinth[MAX_LINES];
init_LABYRINTH(&labyrinth);
int i=0, j=0;
char charbuff[2506];
char* solution;
solution =(char*)malloc(sizeof(char) * 2506);
int offset = 0;
FILE* file_landkarte = open_labyrinth_file("labyrinth_karte.txt");
/* for(j=0; j< MAX_LINES; j++){
fflush(stdin);
init_LABYRINTH(labyrinth[j]);
}
*/
while (fgets(charbuff, MAX_LINE_LENGTH, file_landkarte) != NULL) {
labyrinth[i] = load_labyrinth(charbuff, max_row, max_col);
if(labyrinth[i]!=NULL){
print_labyrinth(labyrinth[i]);
if(!erkunden(labyrinth[i])){ // ! weil erkunden liefert 0 wenn erfolgreich ist
//solution = print_labyrinth(labyrinth[j]);
//strcpy(,print_labyrinth(labyrinth[j]));
offset += sprintf(solution + offset, print_labyrinth(labyrinth[i]));
printf("labyrinth solved!\n");
save_to_file(solution, "solvelab.txt");
}
else{
printf("labyrinth has no solution!\n");
}
}else{
printf("no posible: %i \n",j);
}
i++;
}
/*
for (j = 0; j < 6 ;j ++){
// labyrinth = load_labyrinth(lines[j],max_row, max_col);
if(labyrinth[j]!=NULL){
print_labyrinth(labyrinth[j]);
if(!erkunden(labyrinth[j])){ // ! weil erkunden liefert 0 wenn erfolgreich ist
//solution = print_labyrinth(labyrinth[j]);
//strcpy(,print_labyrinth(labyrinth[j]));
offset += sprintf(solution + offset, print_labyrinth(labyrinth[j]));
printf("labyrinth solved!\n");
//save_to_file(solution, "solvelab.txt");
}
else{
printf("labyrinth has no solution!\n");
}
}else{
printf("no posible\n: %i ",j);
}
}
*/
//save_to_file(solution, "solvelab.txt");
fclose(file_landkarte);
return 0;
}
labyrinth_karte.txt
L3=wwwwwwwskkkwwwkwswwskwwwwwkkzwwwwwww
L4=wwwwbwwskkkwwwkwswwskwwwwwkkswwwwwww
L5=wwwbwwwskkkwwwwwswwskwwwwwkkzwwwwwww
L6=wwwbwwkskkkwwwkwswwskwwwwwkkzwwwwwww
L1=wwwbwwwskkkwwwkwswwskwwwwwkkzwwwwwww
L2=wwwwwwwwwswkkkswwkwkwzwwwkkkwwswbkwwswkwwkkkkwkwwswwkkkwwwwwwwww

Why gdb showed /stdlib/strtol_l.c: No such file or directory? Do I missing something to install?

I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0, loc=0x7ffff7fb04a0 <_nl_global_locale>)
at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: No such file or directory.
I tried reinstalling gdb to get it working again, but I failed. It still shows the same error message. I later found the problem myself and marked it in the code below. I'm just curious why something like this sometimes happens when I try to debug some string functions? Like strdup, strtok, strtol, etc.. Am I missing something to install? I hope I can solve this problem completely.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char buff[255];
#define NUM_BUCKETS 32
typedef struct Customer {
char* email;
char* name;
int shoesize;
char* food;
struct Customer* next;
} Customer ;
unsigned long hash(char *str) {
unsigned long hash = 0;
int c;
while (*str != '\0') {
c = *str;
hash = ((hash << 5) + hash) + (unsigned char)c;
str++;
}
return hash;
}
Customer *add_friend_to_list(char *email, char *name, int shoesize, char *food, Customer *bucket) {
Customer* customer;
customer = malloc(sizeof(Customer));
customer->name = strdup(name);
customer->food = strdup(food);
customer->shoesize = shoesize;
customer->email = strdup(email);
customer->next = bucket;
return customer;
}
void add_consumer_to_hashtable(char *name, char *food, char *email, int shoesize, Customer **buckets, size_t num_buckets) {
size_t which_bucket = hash(name) % num_buckets;
buckets[which_bucket] = add_friend_to_list(email, name, shoesize, food, buckets[which_bucket]);
}
int main() {
Customer* buckets[NUM_BUCKETS] = {NULL};
int ittime = 0;
FILE *fp = NULL;
fp = fopen("customers.tsv", "r");
while (true) {
fgets(buff, 255, fp);
if (feof(fp)) {
break;
}
ittime++;
}
fclose(fp);
fp = NULL;
char *email = (char *)malloc(5 * sizeof(char));
char *name = (char *)malloc(5 * sizeof(char));
int shoesize;
char *food = (char *)malloc(5 * sizeof(char));
const char s[2] = "\t";
fp = fopen("customers.tsv", "r");
for (int i = 0; i < ittime + 1; i++) { //This line cause the Segmentation Fault
fgets(buff, 255, fp);
char *token;
token = strtok(buff, s);
email = token;
token = strtok(NULL, s);
name = token;
token = strtok(NULL, s);
shoesize = atoi(token);
token = strtok(NULL, s);
food = token;
add_consumer_to_hashtable(name, food, email, shoesize, buckets, NUM_BUCKETS);
}
fclose(fp);
while (true) {
char *cmd = (char *)malloc(5 * sizeof(char));
printf("command: ");
scanf("%s", cmd);
if (strcmp(cmd, "add") == 0) {
char *email1 = (char *)malloc(5 * sizeof(char));
char *name1 = (char *)malloc(5 * sizeof(char));
int shoesize1;
char *food1 = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", email1);
printf("name? ");
scanf(" %[^\n]", name1);
printf("shoe size? ");
scanf("%d", &shoesize1);
printf("favorite food? ");
scanf("%s", food1);
add_consumer_to_hashtable(name1, food1, email1, shoesize1, buckets, NUM_BUCKETS);
free(name1);
free(food1);
free(email1);
} else if (strcmp(cmd, "lookup") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "delete") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
free(cus->email);
free(cus->food);
free(cus->name);
free(cus);
cus->shoesize = EOF;
cus = NULL;
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "list") == 0) {
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
if (cus->next != NULL) {
cus = cus->next;
printf("\n");
} else {
break;
}
}
}
} else if (strcmp(cmd, "quit") == 0) {
break;
} else if (strcmp(cmd, "save") == 0) {
fp = fopen("customers.tsv", "w");
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
fprintf(fp, "%s\t%s\t%d\t%s", cus->email, cus->name, cus->shoesize, cus->food);
if (cus->next != NULL) {
cus = cus->next;
fprintf(fp, "\n");
} else {
break;
}
}
}
fclose(fp);
} else {
printf("unknown command\n");
}
}
for (int i = 0; i < 32; i++) {
Customer *tmp;
Customer *cus = buckets[i];
if (cus == NULL) {
continue;
}
if (cus->next != NULL) {
tmp = cus;
cus = cus->next;
} else {
break;
}
while ((tmp != NULL)) {
if (tmp->shoesize != EOF) {
free(tmp->email);
free(tmp->food);
free(tmp->name);
free(tmp);
}
cus->shoesize = EOF;
cus = NULL;
}
if (tmp != NULL) {
free(tmp);
}
if (cus != NULL) {
free(cus);
}
}
return 0;
}
I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
The error message means:
crash happened inside GLIBC strtol_l_internal() function
GDB can't show you the source of that function because libc6-src (or similar) package is not installed.
Now, looking at the source for strtol_l_internal() is not going to be helpful -- the root cause of the problem is that you called it with incorrect parameter.
You should read man strtol and verify that you satisfied its preconditions.
It looks like you called strtol(NULL, NULL, ...), which is not a valid thing to do. You could use (gdb) up command to find out where the wrong call came from, and fix the caller.

Searching a name in a text file by ID

I have a text file with 2 lines in it:
Voicu;Catalin;1234;2.32
Diana;Cadar;2345;1.01
I'm trying to make my program search in .txt file the ID (1234 or 2345) and match it to the name. Below is the code I've tried to make, but it won't find the ID in .txt after I write it in first scanf, the first thing that appears is the "else" line.
void alegereStudent(struct student *stud)
{
FILE *scStudenti = fopen("studenti.txt", "a");
char *error;
int i=0,n;
if(scStudenti==NULL)
{
error = strerror(errno);
printf("Fisierul nu poate fi creat: \n %s", error);
}
printf("\nIntroduceti Numele: ");
scanf("%39s", stud->numeStudent);
printf("Introduceti Prenumele: ");
scanf("%39s", stud->prenumeStudent);
printf("Introduceti ID-ul studentului: ");
scanf("%d", &stud->idStudent);
printf("Introduceti Media de admitere: ");
scanf("%f", &stud->medieAdmitere);
fprintf(scStudenti,"<%s>;", stud->numeStudent);
fprintf(scStudenti,"<%s>;", stud->prenumeStudent);
fprintf(scStudenti,"<%d>;", stud->idStudent);
fprintf(scStudenti,"<%.2f>\n", stud->medieAdmitere);
fclose(scStudenti);
}
//
void optiunea_2()
{
printf("\n1.Despre studenti.\n");
printf("2.Despre profesori.\n");
printf("3.Revenire la meniu principal.\n");
printf("\nAlegeti o optiune: ");
scanf("%d",&alegere_opt2);
switch(alegere_opt2)
{
case 1: while(&stud!=NULL)
{
FILE *scStudenti = fopen("studenti.txt", "r");
char *error;
int cautareID;
if(scStudenti==NULL)
{
error = strerror(errno);
printf("Fisierul nu poate fi creat: \n %s", error);
}
printf("\nIntroduceti ID-ul studentului: ");
scanf("%d", &cautareID);
fscanf(scStudenti,"%d",&stud->idStudent);
if(cautareID==&stud->idStudent)
{
printf("Numele Studentului este %s %s",&stud->numeStudent, &stud->prenumeStudent);
}
else
printf("\nAcest ID nu exista!\n");
optiunea_2();
}break;
fprintf(scStudenti,"<%s>;", stud->numeStudent);
fprintf(scStudenti,"<%s>;", stud->prenumeStudent);
fprintf(scStudenti,"<%d>;", stud->idStudent);
fprintf(scStudenti,"<%.2f>\n", stud->medieAdmitere);
fclose(scStudenti);
This makes formatting much more difficult. The output file will contain:
<first>;<last>;<1234>;<0.5>
You want to start with a new file and simplify the output to write:
first;last;1234;0.5
Don't always put & in front of integer. Just use:
if(cautareID == stud->idStudent)
{
...
}
Example:
const char *filename = "studenti.txt";
void alegereStudent()
{
struct student stud;
FILE *scStudenti = fopen(filename, "a");
if(scStudenti == NULL)
{
printf("error\n");
return;
}
printf("\nIntroduceti Numele: ");
scanf("%39s", stud.numeStudent);
printf("Introduceti Prenumele: ");
scanf("%39s", stud.prenumeStudent);
printf("Introduceti ID-ul studentului: ");
scanf("%d", &stud.idStudent);
printf("Introduceti Media de admitere: ");
scanf("%f", &stud.medieAdmitere);
fprintf(scStudenti, "%s;", stud.numeStudent);
fprintf(scStudenti, "%s;", stud.prenumeStudent);
fprintf(scStudenti, "%d;", stud.idStudent);
fprintf(scStudenti, "%.2f\n", stud.medieAdmitere);
fclose(scStudenti);
}
void find_by_id(int id)
{
FILE *fin = fopen(filename, "r");
if(!fin)
return;
int count = 0;
struct student stud;
while(fscanf(fin, "%39[^;];%39[^;];%d;%f\n",
stud.numeStudent, stud.prenumeStudent, &stud.idStudent, &stud.medieAdmitere) == 4)
{
if(id == stud.idStudent)
{
printf("found %s %s\n", stud.numeStudent, stud.prenumeStudent);
}
count++;
}
if(count == 0)
printf("failed to read any record. Start with a new file.\n");
}
int main(void)
{
alegereStudent();
find_by_id(1234);
return 0;
}
If <> characters are added, then read according to that format, you then have to remove the extra <> characters from the string.
void alegereStudent()
{
struct student stud;
...
fprintf(scStudenti, "<%s>;", stud.numeStudent);
fprintf(scStudenti, "<%s>;", stud.prenumeStudent);
fprintf(scStudenti, "<%d>;", stud.idStudent);
fprintf(scStudenti, "<%.2f>\n", stud.medieAdmitere);
fclose(scStudenti);
}
void find_by_id(int id)
{
...
struct student stud;
while(fscanf(fin, "%39[^;];%39[^;];<%d>;<%f>\n",
stud.numeStudent, stud.prenumeStudent, &stud.idStudent, &stud.medieAdmitere) == 4)
{
if(id == stud.idStudent)
{
char *p;
size_t i;
//remove the extra <> characters
p = stud.numeStudent;
if (strlen(p) > 1)
{
for(i = 1; i < strlen(p) - 1; i++)
p[i - 1] = p[i];
p[i - 1] = 0;
}
//remove the extra <> characters
p = stud.prenumeStudent;
if (strlen(p) > 1)
{
for(i = 1; i < strlen(p) - 1; i++)
p[i - 1] = p[i];
p[i - 1] = 0;
}
printf("found %s %s\n", stud.numeStudent, stud.prenumeStudent);
}
count++;
}
if(count == 0)
printf("failed to read any record. Start with a new file.\n");
}
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char const *filename = "test.txt";
FILE *input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading!\n\n", filename);
return EXIT_FAILURE;
}
char name[101];
char surname[101];
int id;
double value;
while (fscanf(input, "%100[^;];%100[^;];%d;%lf%*[\n]", name, surname, &id, &value) == 4) {
if (id == 2345) {
printf("Found \"%s %s\" by id %d\n\n", name, surname, id);
break;
}
}
}

Cannot understand why program crashes after a couple iterations of while loop?

I am writing the following program to parse the text file (attached) but it keeps crashing after couple of iterations of while loop or it seems that the buffer storing file contents is corrupted somehow?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char * pick_question(char *, char, int);
char * print_answer(char *, char, int);
int no_of_questions(char*, char);
void clear();
int debug = 0;
int main(int argc, char* argv[])
{
system("cmd /c chcp 1252");
// system("cmd /c chcp 65001");
if (argc < 2)
{
perror("Please enter a filename!\n");
exit(0);
}
if (argc > 2)
{
debug = atoi(argv[2]);
}
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
if (!file)
{
perror("Unable to read file!\n");
exit(0);
}
else
{
if (debug == 1)
{
printf("File opened successfully\n");
}
}
static char *buffer;
int fileSz;
fseek(file, 0, SEEK_END);
fileSz = ftell(file);
fseek(file, 0, SEEK_SET);
buffer = (char*) malloc((fileSz + 1) * sizeof(char));
if (!buffer)
{
perror("Unable to allocate buffer!");
exit(0);
}
fread(buffer, sizeof(char), fileSz, file);
while (1)
{
time_t t;
srand((unsigned) time(&t));
int sub = rand() % 5 + 1;
char del;
switch (sub)
{
case 1:
del = 'A';
break;
case 2:
del = 'B';
break;
case 3:
del = 'C';
break;
case 4:
del = 'D';
break;
case 5:
del = 'E';
}
int nrOfQues = no_of_questions(buffer, del);
if (nrOfQues == 0)
{
perror("main(): no_of_questions() returned 0. Unsupported text structure in file or incorrect file encoding!");
fclose(file);
exit(0);
}
int qNo = rand() % nrOfQues + 1;
char *ques = pick_question(buffer, del, qNo);
if (ques)
{
printf("\n\n");
puts(ques);
printf("\n\n");
}
else
{
perror("main(): pick_question() returned NULL. Unsupported text structure in file!");
fclose(file);
exit(0);
}
printf("\n\n");
printf("Do you want to see the answer(y/n)?");
char ans, repeat;
scanf("%c", &ans);
if ( ans == 'Y' || ans == 'y')
{
char *ans = print_answer(buffer, del, qNo);
if (ans)
{
printf("\n\n");
puts(ans);
printf("\n\n");
}
else
{
printf("\n\n");
perror("main(): print_answer() returned NULL. Unsupported text structure in file!");
fclose(file);
exit(0);
}
}
printf("Do you want to try more questions (y/n)?");
clear();
scanf("%c", &repeat);
if (repeat == 'N' || repeat == 'n')
{
break;
}
clear();
}
printf("\n\n");
printf("******** Thank you for using TULE Master! ********");
printf("\n\n");
fclose(file);
return 0;
}
char * pick_question(char * buffer, char sub, int qNo)
{
char tmpBuff[20];
char tmpBuff2[20];
const char * searchStr = "FRÅGA";
const char * searchStr2 = "A 1 SVAR:";
const char * searchStr3 = "*****************************************";
char *pStr, *currPos, *nStr, *tmpStr, *tmpStr2;
currPos = buffer;
int count = snprintf(tmpBuff, 20, "FRÅGA %c %d", sub, qNo);
if (count >= 0 || count < 20)
{
if (debug)
{
printf("tmpBuff is %s\n", tmpBuff);
}
currPos = strstr(currPos, tmpBuff);
if (currPos)
{
pStr = currPos;
nStr = currPos + 1;
nStr = strstr(nStr, searchStr);
if (!nStr)
{
nStr = currPos;
nStr = strstr(nStr, searchStr2);
if (!nStr)
{
printf("pick_qestion(): nStr is NULL. Unsupported "
"text structure");
return NULL;
}
}
// Check if it is a scenario based question
count = snprintf(tmpBuff2, 20, "FRÅGA %c %d", sub, qNo-1);
if (count >= 0 || count < 20)
{
tmpStr = strstr(buffer, tmpBuff2);
tmpStr2 = strstr(tmpStr, searchStr3);
if (tmpStr < tmpStr2 && tmpStr2 < pStr)
{
pStr = tmpStr2;
}
}
int qLen = nStr - pStr;
char *ques = malloc(sizeof(char) * (qLen+1));
snprintf(ques,qLen,"%s", pStr);
return ques;
}
else
{
printf("pick_qestion(): string \"FRÅGA\" not found in file!");
return NULL;
}
}
printf("pick_qestion(): snprintf was not successful!");
return NULL;
}
char * print_answer(char * buffer, char sub, int qNo)
{
char tmpBuff[20];
char *pStr, *currPos, *nStr;
int count = snprintf(tmpBuff, 20, "%c %d SVAR:", sub, qNo);
if (count >= 0 || count < 20)
{
currPos = strstr(buffer, tmpBuff);
if (!currPos)
{
printf("print_answer(): string \"SVAR\" not found in file!");
}
pStr = currPos;
nStr = currPos + 1;
char tmpBuff2[20];
int count = snprintf(tmpBuff2, 20, "%c %d SVAR:", sub, qNo+1);
if (count < 0 || count >= 20)
{
printf("print_answer(): snprint was not successful!");
return NULL;
}
nStr = strstr(nStr, tmpBuff2);
if (!nStr)
{
nStr = buffer + strlen(buffer);
}
int ansLen = nStr - pStr;
char *ans = malloc(sizeof(char) * (ansLen+1));
snprintf(ans, ansLen, "%s", pStr);
return ans;
}
printf("print_answer(): snprint was not successful!");
return NULL;
}
int no_of_questions(char *buffer, char sub)
{
char tmpBuff[20];
char *currPos, *pStr;
int count = snprintf(tmpBuff, 20, "FRÅGA %c", sub);
if (count >= 0 || count < 20)
{
if (debug)
{
printf("tmpBuff is %s\n", tmpBuff);
}
currPos = strstr(buffer, tmpBuff);
while (currPos != NULL)
{
pStr = currPos;
currPos = currPos + 1;
currPos = strstr(currPos, tmpBuff);
}
if (pStr != buffer)
{
pStr += 9;
char tmpBuff2[20];
memcpy(tmpBuff2, pStr, 2);
if (debug)
{
printf("No. of questions for %c DEL is are %d\n", sub,
atoi(tmpBuff2));
}
return atoi(tmpBuff2);
}
return 0;
}
return 0;
}
void clear()
{
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
}
This is the file that is given as input to the program:
Link

Sorting array filled with lines of string

I have a data in text like this:
1,jack,3,7.3
2,mike,4,8.6
3,gol,2,9
Could any one help me how to sort the data by the last column that represent the grades in descending using c language?
The question was posted before but with no code so I posted it again to get more help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int cid;
char name[40];
char term[2];
double gpa;
}student;
typedef struct
{
char line[300];
}data;
typedef struct
{
int cid;
}finds;
typedef struct
{
double score;
}gpa;
void menu();
int calculateMax(void);
void addStudent();
void find();
void display();
void sort();
int main()
{
menu();
system("PAUSE");
return 0;
}
void menu()
{
int selection;
printf("%s", "Program menu :\n");
printf("%s", "1. Add a new student\n");
printf("%s", "2. Find/retrieve information for a particular Student\n");
printf("%s", "3. Display STUDENTS list\n");
printf("%s", "4. Find a student that has the lowest and the highest deposit\n");
printf("%s", "5. Quit\n");
printf("%s", "Selection : ");
scanf("%d", &selection);
if(selection == 1)
{
addStudent();
}
else if(selection == 2)
{
find();
}
else if(selection == 3)
{
display();
}
else if(selection == 4)
{
sort();
}
else if(selection == 5)
{
exit(0);
}
else {
printf("%s", "\n\aError, please key in correct input!\n\n");
menu();
}
}
void addStudent()
{
int max, i;
FILE *f, *id, *name, *term, *gpa , *sort;
printf("%s", "\n\nADD student\n");
printf("%s", "How many students you would like to add : ");
scanf("%d", &max);
student *student_info;
student_info = (student *) malloc(max * sizeof(student)); /*Allocate Memory For Client's Info*/
if(student_info == NULL)
{
printf("Unable to allocate space for client\n\n");
exit (EXIT_FAILURE);
}
if ((id = fopen("id.txt", "a+")) == NULL) /*Open file id.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((name = fopen("name.txt", "a+")) == NULL) /*Open file name.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((term = fopen("term.txt", "a+")) == NULL) /*Open file TERM.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((gpa = fopen("gpa.txt", "a+")) == NULL) /*Open file GPA.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((f = fopen("student.txt", "a+")) == NULL) /*Open file STUDENTS.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((sort = fopen("sort.txt", "a+")) == NULL) /*Open file SORT.txt*/
{
printf("Error, the file cannot be opened\n");
}
else {
for (i = 0; i < max ; i++) { /*Get the input data*/
printf("student %d\n", i + 1);
printf("%s", "student's Id : ");
scanf("%5d", &student_info[i].cid);
printf("%s", "student's Name : ");
fflush(stdin);
gets(student_info[i].name);
printf("%s", "student's term : ");
fflush(stdin);
gets(student_info[i].term);
printf("%s", "student's GPA : ");
scanf("%7lf", &student_info[i].gpa);
printf("\n");
}
}
for(i = 0; i < max; i++) { /*Store input data into files*/
fprintf(id, "%d\n", student_info[i].cid);
fputs(student_info[i].name, name);
fprintf(name, "\n");
fputs(student_info[i].term, term);
fprintf(term, "\n");
fprintf(gpa, "%lf\n", student_info[i].gpa);
fprintf(sort,"%d,%s,%s,%lf\n",student_info[i].cid,student_info[i].name,student_info[i].term,student_info[i].gpa);
}
for(i = 0; i < max; i++) {
fprintf(f, "%d", student_info[i].cid, "");
fprintf(f, "%3s", "");
fputs(student_info[i].name, f);
fprintf(f, "%5s", "");
fputs(student_info[i].term, f);
fprintf(f, "%7s", "");
fprintf(f, "%lf\n", student_info[i].gpa);
}
fclose(f);
fclose(id);
fclose(name);
fclose(term);
fclose(gpa);
fclose(sort);
free(student_info);
student_info = NULL;
printf("\n");
menu();
}
void find()
{
int find_id = 0, i = 0, student_cid, n = 0, max, selection;
FILE *id, *f;
max = calculateMax();
finds *result;
result = (finds *) malloc(max * sizeof(finds));
if(result == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((id = fopen("id.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
else {
while (!feof(id)) { /*Get all clients' id number and store to array*/
fscanf(id, "%d", &result[i].cid);
i++;
}
}
fclose(id);
printf("%s", "\n\nFIND STUDENT\n");
printf("%s", "Key in Student's id : "); /*Get the client's id that user want to query*/
scanf("%d", &student_cid);
data *student_info;
student_info = (data *) malloc(max * sizeof(data));
if(student_info == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((f = fopen("student.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
i = 0;
while (!feof(f)) { /*Get all the students' data from clients.txt and stored to array*/
fflush(stdin);
fgets(student_info[i].line, 300, f);
i++;
}
fclose (f);
for(i = 0; i < max + 1; i++)
{
if(student_cid == result[i].cid)
{
printf("\n\n%s%6s%20s%17s\n", "ID", "NAME", "TERM", "GPA");
puts(student_info[i].line);
free(student_info);
student_info = NULL;
free(result);
result = NULL;
printf("Would you like to find another student?\nKey in 1 for yes or 2 to go to menu : ");
scanf("%d",&selection);
if(selection == 1) {
find();
}
else if(selection == 2) {
menu();
}
break;
}
else if(i == max)
{
printf("\nSory, there's no student with that exist in database.\n");
free(student_info);
student_info = NULL;
free(result);
result = NULL;
printf("Would you like to find another student?\nKey in 1 for yes or 2 to go to menu : ");
scanf("%d",&selection);
if(selection == 1) {
find();
}
else if(selection == 2) {
printf("\n\n");
menu();
}
}
}
}
void display()
{
int max = 0, i;
FILE *f;
printf("\n\nDISPLAY STUDENT");
max = calculateMax();
data *student_info;
student_info = (data *) malloc(max * sizeof(data));
if(student_info == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((f = fopen("student.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
i = 0;
while (!feof(f)) {
fflush(stdin);
fgets(student_info[i].line, 200, f);
i++;
}
fclose (f);
printf("\n\n%s%6s%20s%17s\n", "ID", "NAME", "TERM", "GPA");
for(i = 0; i < max; i++)
{
puts(student_info[i].line);
}
free(student_info);
student_info = NULL;
}
int calculateMax(void)
{
char str[150];
int maximum = 0;
FILE *f;
if ((f = fopen("student.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
else {
while (!feof(f)) {
maximum++;
fgets (str , 200 , f);
}
}
fclose (f);
maximum = maximum - 1;
return maximum;
}
////////////////////////////////////////////////////////////////////
static int student_info_compare(const void *a, const void *b)
{
const student_info *sia = a, *sib = b;
return strcmp(sia->name, sib->name);
}
void Sortdisplay()
{
int max = 0, i;
FILE *f;
printf("\n\nDISPLAY SORTED STUDENT");
max = calculateMax();
data *student_info;
student_info = (data *) malloc(max * sizeof(data));
if(student_info == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((f = fopen("sort.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
i = 0;
while (!feof(f)) {
fflush(stdin);
fgets(student_info[i].line, 200, f);
i++;
}
fclose (f);
printf("\n\n%s%6s%20s%17s\n", "ID", "NAME", "TERM", "GPA");
student_info_compare();
for(i = 0; i < max; i++)
{
// iwant to sort here
qsort(student_info, max, sizeof student_info[0], student_info_compare);
puts(student_info[i].line);
}
free(student_info);
student_info = NULL;
}
Try this:
static int student_info_compare(const void *a, const void *b)
{
const student_info *sia = a, *sib = b;
return strcmp(sia->name, sib->name);
}
then add this before the print loop:
qsort(student_info, max, sizeof student_info[0], student_info_compare);
This uses the standard qsort() function to sort the array. The student_info_compare() function serves as the comparison-callback, since qsort() doesn't know how your data looks.
The arguments to the comparison-callback have type const void *, which basically means "here's a pointer to something whose exact type is not known, and you're supposed to treat it as a read-only pointer". That's how qsort() passes pointers to the array elements, since (again) it doesn't know that they are of type const student_info *.

Resources