1

I am trying to do this programming project in the book i study:

Write a program that sorts a series of words entered by the user:

Enter word: foo

Enter word: bar

Enter word: baz

Enter word: quux

Enter word:

In sorted order: bar baz foo quux

Assume that each word is no more than 20 characters long. Stop reading when the user enters an empty word (i.e., presses Enter without entering a word). Store each word in a dynamically sllocated string, using an array of pointers to keep track of the strings.

After all words have been read, sort the array (using any sorting technique) and then use a loop to print the words in sorted order.

That is what i am trying:

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

#define MAX_LENGTH 20

int compare ( const void * p, const void * q);

int main (void){
    int n;
    printf("How many words do you want to write");
    scanf("%d", &n);
    fflush(stdin);
    char * word[n];

    for( int i = 0; i < n; i++){
        fprintf(stdout , "Waiting for the word:");
       if(fgets(word[i] , MAX_LENGTH +1 , stdin) == "\n")
       break;
    }
    qsort((void *)word,n,sizeof(int),compare);

    printf("Ordered list is:\n\n");
    for( int i = 0; i < n; i++){
        fprintf(stdout , "\t %s", word[i]);
    }
    
}

int compare (const void * p, const void * q){
    return strcmp( * (char**) p , * (char **) q);
}

Edit : question with italic is solved thanks to fellow coders here. My new issue is i can't read past the first element of array. And program closes itself.

C:\Users\Lenovo\Desktop\ogrenme\ch17>sorting
How many words do you want to write4
Waiting for the word:asd

C:\Users\Lenovo\Desktop\ogrenme\ch17>

And there is one single annoying error that keeps me prevented from completing the exercise and "chill" with rest of this challenging book:

sorting.c:20:5: warning: implicit declaration of function 'qsort' [-Wimplicit-function-declaration]
    qsort((void *)word,n,sizeof(int),compare);
Community
  • 1
  • 1
Ali A
  • 53
  • 6
  • 4
    Please `#include ` to get the function declaration for `qsort()`. – Weather Vane Mar 26 '20 at 12:37
  • 2
    Voting to close as simple typo. Include the header where the function is located, simple as that. – Lundin Mar 26 '20 at 12:40
  • `man qsort` would show you the required `#include`s. If you don't use a UNIX/Linux system you can enter this in your favorite search engine. – Bodo Mar 26 '20 at 12:40
  • 1
    Also please note the error in `if(fgets(word[i] , MAX_LENGTH +1 , stdin) == "\n")`. The return value from `fgets()` will *never* be the same as a string literal. Please see [Removing trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221) – Weather Vane Mar 26 '20 at 12:40
  • Welcome to SO. You are calling `qsort` wrong. Your array does not hold `int` values. Therefore `sizeof(int)` is not be correct. – Gerhardh Mar 26 '20 at 12:42
  • 1
    @Lundin it is not as simple as that. More: there is no memory allocated to the elements of the pointer array `char * word[n];`. Sadly, the code has **multiple errors** not just a simple typo. – Weather Vane Mar 26 '20 at 12:43
  • Yeah, well ,i mean, it looks like i am dumb. :( Btw, i still have an issue that `fgets` only reads first word. Maybe i get a solution o that so i edit the question. – Ali A Mar 26 '20 at 12:44
  • @WeatherVane That may be so, but the question is why they are getting the implicit declaration error. – Lundin Mar 26 '20 at 12:46
  • @Lundin fair enough then. – Weather Vane Mar 26 '20 at 12:47
  • Thanks for the previous help. I edited the question with my current problem. – Ali A Mar 26 '20 at 12:51
  • @AliA the task required you to "store each word in a dynamically allocated string", so you must allocate memory for each input string, storing the pointer in `word[i]` before calling `fgets()`. – Weather Vane Mar 26 '20 at 12:52
  • In your solution, the loop will stop after reaching `n` tries. This is not what they ask you to do.. you should keep reading until the user enters an empty string... therefore, you should use `while loop` instead.. as soon as your program reads an empty string, you should stop.... – mlwn Mar 26 '20 at 12:56
  • @mlwn I am trying what you are saying but , if you wish , can you show me how allocation and `while loop` should be structured as an answer? – Ali A Mar 26 '20 at 13:06
  • I can guide you here quickly... `while (1) { read string, test it if not empty, store it to array of string pointers... else, if empty, break out of loop... }` try this, and remember, websearch is your friend... if you fail, i'll write a sample for you – mlwn Mar 26 '20 at 13:11

1 Answers1

1

I did a small trial (definitely the code could be optimized)

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

int main (void) {
  int n = 0;
  char **string_list;
  char *tmp;

  //allocate memory for the first element
  string_list = (char**)malloc(sizeof(char*)*1);

  //infinite loop
  while ( 1 ) {
    //allocate size of each element to a max of 20 chars
    string_list[n] = (char*)malloc(sizeof(char)*20);

    printf("Enter word : ");
    fgets (string_list[n], 20, stdin);

    //remove trailing return carriage
    string_list[n][strlen(string_list[n]) - 1] = '\0';

    //break the loop here if user enters empty string
    if (strlen(string_list[n]) < 1) {
      break;
    }

    //add counter
    n++;

    //add memory to contain another element
    string_list = realloc(string_list, sizeof(char*)*(n+1));
  }

  printf("\n\nInitial List is:\n");
  for (int i=0 ; i<n-1 ; i++) {
    printf("%s - ", string_list[i]);
  }
  printf("%s\n\n", string_list[n-1]);

  //sorting the list
  for (int i=0; i<n; i++) {
    for (int j=0; j<n; j++) {
      if (strcmp(string_list[i], string_list[j]) < 0) {
        tmp = string_list[i];
        string_list[i] = string_list[j];
        string_list[j] = tmp;
      }
    }
  }

  printf("Sorted List is:\n");
  for (int i=0 ; i<n-1 ; i++) {
    printf("%s - ", string_list[i], strlen(string_list[i]));
  }
  printf("%s\n\n", string_list[n-1], strlen(string_list[n-1]));
}

output

$ ./sort 
Enter word : foo
Enter word : bar
Enter word : baz
Enter word : quux
Enter word : 


Initial List is:
foo - bar - baz - quux

Sorted List is:
bar - baz - foo - quux
mlwn
  • 1,156
  • 1
  • 10
  • 25
  • NB. This worked on linux gcc compiler... if it didn't work on windows, please post the output... – mlwn Mar 26 '20 at 17:08