Hi,
I am facing some problem dealing with the qsort funtion. Basically, the below program takes in a bunch of strings from the text file "word.txt" and then implements the qsort function for sorting the list alphabatically and then displaying the sorted list. However, after the sorting is done, all I'm getting is gibberish stuffs. Can anyone please look at the below code and suggest something or if possible rectify the code..

Regards,

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

FILE *data;

static int compare (const void *, const void *);

int main ()

{ 
  int i;

  data=fopen("word.txt","r");

  char list[100][20];
  char s[20];
  int sno1=0;

  while((fscanf(data,"%s",&s))==1)
    { strcpy(list[sno1],s); 
      ++sno1;}

  int strings_len = sizeof(list) / sizeof(char *);

  qsort(list, strings_len, sizeof(char *), compare);

  for (i = 0; i < strings_len; i++) 
     printf ("\n%d: %s.", i, list[i]);

  system("pause");
  return 0;
}

int compare (const void *a, const void *b)
{
    return strcmp( (const char *)a , (const char *)b );
}

And here are the contents of the text file "word.txt"

TEMPERATURE
TEACHER
COMPUTER 
ALLOCATE 
LOVE 
TREE 
KEYBOARD
TUTOR
FOLDER
PENCIL
NOTEPAD
DISK
MOUSE
WIRE

Dani AI

Generated

The symptoms (sorted output turned into gibberish) come from qsort being handed the wrong memory layout: the number-of-elements and element-size arguments must match how the strings are actually stored. spotted this and fixed the immediate cause; the remaining checklist below explains why it happened and how to avoid it reliably.

Always validate and bound input: check fopen returned non-NULL, never read past the per-string buffer, and stop when the count reaches the array capacity. Prefer line-safe input (for example, fgets with newline stripping) over unchecked formats so long words do not overflow fixed buffers. When calling qsort, pass the actual count of strings you read (not a computed size based on pointer sizes) and the byte size of one element (for a true 2D char array that is sizeof list[0]).

A more robust pattern is to read into a temporary buffer, allocate a copy for each line, and sort an array of pointers. That keeps memory contiguous per string and makes the comparator simple: compare the pointed-to C strings. Example pattern:

/* read with fgets into buf, strdup each line into words[count],
   then use qsort(words, count, sizeof words[0], cmp) where cmp
   compares *(const char * const *)a and *(const char * const *)b */

Cleanup and extras: close the FILE*, free allocated strings, and print only the actual count. For locale-aware or case-insensitive sorting use strcoll or strcasecmp instead of strcmp. Avoid non-portable calls like system("pause") in production. For qsort reference and behavior see qsort (C reference) and for safe line input see fgets.

Recommended Answers

All 2 Replies

In this case, you already know the number of elements (min(100,sno1)) and size of each element (20). Use those values instead of the computed values, besides the fact that the size argument is not the size of a char*, but is 20. So, your qsort call should be this:

qsort(&list[0][0], sno1, 20, compare);

Also, your while function should read like this - skipping the copy part:

while((fscanf(data,"%s",&list[sno1][0]))==1)
{
    ++sno1;
}
commented: Thanks! This solved my problem! +0

: Thanks mate! Your suggestions worked! Problem solved! Greetz

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.