Search code examples
csortingpointersstring-comparison

Sorting an array of strings in an alphabetical order using pointers


I have a project where I have to create a program that would let users input names in any order. Then the program displays the names alphabetical order. Also all of this has to be done using pointers. Now my attempt at the program prompts the user to put in the names and it displays them, but I can't get it to sort them for some reason. Can someone please help me?

Here's my attempt at the program:

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

int main() {
  int list;
  char *names[20];
  char str[20];
  printf("Enter the number of names: ");
  scanf("%d", &list);
  fflush(stdin);
  for (int i = 0; i < list; i++) {
    printf("Enter name %d: ", i + 1);
    // gets(str);
    scanf("%[^\t\n]s", str);
    fflush(stdin);
    names[i] = (char *)malloc(strlen(str) + 1);
    strcpy(names[i], str);
  }
  void sortNames();
  for (int i = 0; i < 5; i++)
    printf("%s\n", names[i]);
  return 0;
}

void sortNames(char **name, int *n) {
  int i, j;
  for (j = 0; j < *n - 1; j++) {
    for (i = 0; i < *n - 1; i++) {
      if (compareStr(name[i], name[i + 1]) > 0) {
        char *t = name[i];
        name[i] = name[i + 1];
        name[i + 1] = t;
      }
    }
  }
}

int compareStr(char *str1, char *str2) {
  while (*str1 == *str2) {
    if (*str1 == '\0' || *str2 == '\0')
      break;

    str1++;
    str2++;
  }
  if (*str1 == '\0' && *str2 == '\0')
    return 0;
  else
    return -1;
}

Solution

  • Focusing only on the issues with sorting, the main one is that you never call the sorting function you later define. The line

    void sortNames();
    

    serves only to declare a function with the identifier sortNames which takes any number of arguments of any types (probably not quite what you want to do). I would recommend revising this line to instead be

    sortNames(names, list); // Not &list because I'm about to suggest not taking it as a pointer
    

    Then for the sortNames function itself, I'm not totally clear on why you take the length of the array to be sorted as a pointer instead of just passing the int itself. I'd recommend revising this function to instead be

    void sortNames(char **name, int n) {
      int i, j;
      for (j = 0; j < n - 1; j++) {
        for (i = 0; i < n - 1; i++) {
          if (compareStr(name[i], name[i + 1]) > 0) {
            char *t = name[i];
            name[i] = name[i + 1];
            name[i + 1] = t;
          }
        }
      }
    }
    

    One issue with this as it stands though is that the expression compareStr(name[i], name[i + 1]) > 0 is always false. This is due to the fact that compareStr only ever returns 0 or -1. You could fix this by re-writing compareStr to correctly handle the case where the *str1 > *str2. One possible way to do this could be

    int compareStr(char *str1, char *str2) {
        if (*str1 == '\0' && *str2 == '\0') {
            return 0;
        } else if (*str1 > *str2) {
            return 1;
        } else if (*str1 < *str2) {
            return -1;
        }
        return compareStr(str1 + 1, str2 + 1);
    }
    

    Although if you're writing this to learn I'd suggest trying to revise your current iterative solution instead of just copying & pasting this version.

    Finally, because you want to use these functions before you've defined them you should either move their definitions prior to when they're used (i.e., have compareStr, then sortNames and then main) or provide a forward declaration at the start of your file for these functions, i.e., add

    void sortNames(char **name, int n);
    int compareStr(char *str1, char *str2);
    

    above your main.


    As others have noted you probably want to avoid fflush(stdin) as its undefined behaviour and I would recommend against casting the result of malloc.