Reputation: 13
I am learning C. I wrote my program to read the data from a text file and print it out. During the building process compiler did not give errors. However, the program crashed when I tried to run it. I checked that when printTable
function is removed, the program runs and prints the contents in the loop in main()
. I also tried to remove variable "total
" but the program still crashed. What is the problem?
#include<stdio.h>
#include<stdlib.h>
typedef struct{
char *country;
int females;
int males;
}person_count;
void printTable(person_count *data[]){
printf("Country Females Males Total\n");
int i;
int total[158];
for(i=0;i<158;i++){
total[i]=data[i]->females+data[i]->males;
printf("%15s %7i %7i %8i\n",data[i]->country,data[i]->females,data[i]->males,total[i]);
}
}
int main(){
person_count *data[158];
FILE *eduData=fopen("SecondaryEd2005.txt","r");
if(eduData==NULL){
printf("File not found.");
exit(1);
}
printf("File opened successfully.\n");
int k;
for(k=0;k<158;k++){
data[k]=malloc(sizeof(person_count));
char place[20];
fscanf(eduData,"%s %i %i\n",place,&data[k]->females,&data[k]->males);
data[k]->country=place;
printf("%s %i %i\n",data[k]->country,data[k]->females,data[k]->males);
}
printTable(data);
fclose(eduData);
return 0;
}
Sample of txt file contents:
Belgium 391138 423401 Belize 15591 15786 Benin 154266 281183 Bermuda 2494 2262 Bhutan 19870 22274
Upvotes: 1
Views: 251
Reputation: 2092
I fixed your program for you. The most important thing is to make country a fixed length array of chars, not a pointer. Also, make sure you free all memory you allocate to your program or you'll generate memory leaks.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char country[20]; //fixed to reflect country field better
int females;
int males;
}person_count;
void printTable(person_count *data[],int items){
items++;
int i,total[items]; //replaced fixed value with variable to prevent excessive empty rows from printing
printf("Country Females Males Total\n");
for(i=0;i<items;i++){
total[i]=data[i]->females+data[i]->males;
printf("%15s %7i %7i %8i\n",data[i]->country,data[i]->females,data[i]->males,total[i]);
}
}
int main(){
FILE *eduData=fopen("SecondaryEd2005.txt","r");
if(eduData==NULL){
printf("File not found.");
exit(1);
}
printf("File opened successfully.\n");
int k,fscanret;
person_count* data[159]; //added 1 to prevent out of bounds memory access
for(k=0;k<158;k++){
data[k]=malloc(sizeof(person_count));
fscanret=fscanf(eduData,"%s %i %i\n",data[k]->country,&data[k]->females,&data[k]->males);
if (fscanret==EOF){ //check return value to avoid going past end of file
free(data[k]); //discard empty record and free memory if EOF reached
k--;
break;
}
printf("%s %i %i\n",data[k]->country,data[k]->females,data[k]->males);
}
fclose(eduData);
printTable(data,k); //print k number of entries.
while (k>=0){
free(data[k]); //free memory for all entries. DONT FORGET THIS
k--;
}
return 0;
}
Upvotes: 2
Reputation: 137
You should change your person_count struct :
typedef struct{
char country[20];
int females;
int males;
}person_count;
The line data[k]->country=place;
should be replaced by memcpy(data[k]->country, place, 20*sizeof(char));
WhozCraig gave you the answer in his comment. Your code copy a pointer which is lost at next loop iteration.
Be aware that this code will work only if all your countries are less than 19 characters. You could also stick to the char* pointer, but in that case you will have to allocate memory and free it after usage.
Upvotes: 1