benclifford 0 Newbie Poster

Hi,

I have a task to perform which all to do with the smurfs, reading from a file and doing some simple stuff to it. The last part I need to do is print out a list of all smurfs and their corresponding role in alphabetical order. I am hoping I can do this using the qsort function but this is giving a segmentation fault. I have attached my code below:

#include <stdio.h> 		/*Required for file operations*/
#include <string.h>		/*Required for strlen etc*/
#include <stdlib.h>		/*Required for Malloc,Free, etc.*/

/*-----------------------------------Declarations----------------------------------*/
FILE* fp;			/*Declare the file pointer*/
char str_read[50];
char temp_array[6][50];
int i;
char current[20];
typedef struct
{
  char name[20];
  char gender[20];
  int age;
  char role[20];
  char skill[20];
  char speciality[20];
} SMURF;
  
SMURF *village = NULL;
SMURF *temp_sort = NULL;
int num_elements = 0;		/*This keeps track of the number of elements used i.e. total number of smurfs*/
int num_allocated = 0;		/*This keeps track of how large the array is*/
int countArray[5];
int smurfCount;

/*-------------------------------End of declarations-------------------------------*/

/*-----------Function to remove white space (excess spaces and \n chars)-----------*/
void trim(char *s)
{
  /*trim spaces and new lines from beginning of string*/
  int i=0,j;
  while((s[i]==' ')||(s[i]=='\n'))
  {
    i++;
  }
  if(i>0)
  {
    for(j=0;j<strlen(s);j++)
    {
      s[j]=s[j+i];
    }
  }
  /*trim spaces and new lines from end of string*/
  i = strlen(s)-1;
  while((s[i]==' ')||(s[i]=='\n')||(s[i]=='\r'))
  {
    i--;
  }
  if(i<(strlen(s)-1))
  {
    s[i+1]='\0';
  }
}
/*-------------------------------End of trim function------------------------------*/

/*------------------Function to add a smurf to the village array-------------------*/
void addSmurfToVillage(currentSmurf, current_data, village)
int *currentSmurf;
char current_data[][50];
SMURF *village;
{
  strncpy(village[*currentSmurf].name, current_data[0], 20);
  strncpy(village[*currentSmurf].gender, current_data[1], 20);
  village[*currentSmurf].age = atoi(current_data[2]);
  strncpy(village[*currentSmurf].role, current_data[3], 20);
  strncpy(village[*currentSmurf].skill, current_data[4], 20);
  strncpy(village[*currentSmurf].speciality, current_data[5], 20);
}
/*-------------------------End of addSmurfToVillage function-----------------------*/

void freeVillage()
{
  //function to free memory allocated for array village
}

int static cmpr(const void *a, const void *b)
{
  SMURF * const *one = a;
  SMURF * const *two = b;
  
  return strcmp((*one)->name, (*two)->name);
}

int main(int argc, char *argv[])/*function main begins program execution*/
{
  fp = fopen(argv[1], "r");	/*read file specified at run time from disk into memory, This assumes the only parameter is the filename*/
  if( fp != NULL )
  {
    while( fgets( str_read, 50, fp ) != NULL)
    {
      for( i=0; i<6; i++ )	/*i increments to 6 as there are 6 pieces of info for each smurf (reads in one smurfs data)*/
      {
	char delimiter[] = ":";
	char *token = NULL;
	token = strtok( str_read, delimiter );
	while( token != NULL )
	{
	  if( strlen(token) > 0 )
	  {
	    strncpy( current, token, 20 );	/*ensures null is avoided*/
	  }
	  token = strtok( NULL, delimiter );
	}
	trim(current);
	strcpy(temp_array[i], current);
	fgets( str_read, 50, fp );
      }
      if(num_elements == 0)
      {
	village = (SMURF *)malloc(sizeof(SMURF));
	num_allocated++;
      }
      else
      {
	num_allocated++;
	void *_tmp = (SMURF *)realloc(village, (num_allocated * sizeof(SMURF)));
	if(!_tmp)
	{
	  printf("ERROR: Couldnt realloc memory!\n");
	  return(-1);
	}
	village = (SMURF*)_tmp;
      }   
      addSmurfToVillage(&num_elements, &temp_array, village);
      num_elements++;
    }
    close(fp);
    
    qsort(village, num_elements, sizeof(SMURF), cmpr);
    
    batchCount(&num_elements, village, &countArray);  
    printf("\nVillage Population: %d Smurfs\n", num_elements);
    for( smurfCount = 0; smurfCount<num_elements; smurfCount++ )
    {
      printf("%s: %s\n", village[smurfCount].name, village[smurfCount].role);
    }
    printf("\n");
  }
  else
  {
    printf("Cannot open the file\n");
    return(0);			/*Indicates the program ended sucessfully*/
  }
}

I am running this on linux and reading in a text file with the data in.
The data is in the format below and is in a standard txt file if anyone wishes to test:

Name: Smurfette
Gender: Female
Age: 100
Role: Beautician
Skill: High
Specialty: FlowerPicking

Also if anyone has any tips to improve this code I would greatly appreciate them as i am new to C programming.

Thanks