¿Cómo se ordena una matriz de cadenas en orden alfabético en c?

Aquí está mi intento de hacerlo:

/**
 * sort data alphabetically
 * @param data[] array of strings
 * @param size array size
 * @return an alphabetically sorted array
*/
char *sortAlphabetically(char *data[], int size)
{
  char *sortedArray = malloc(size);
  char *temp;
  int index, nextIndex;

  // copy data to avoid mutation
  for (int i = 0; i < size; i++)
    snprintf(&sortedArray[i], size, "%s", data[i]);

  // check data is not empty data
  if (!sortedArray)
    return NULL;

  for (index = 0; index < size; index++)
  {
    for (nextIndex = index + 1; nextIndex < size; nextIndex++)
    {
      // return positive integer if string1 is greater than string2, negative if lesser and 0 if equal. strmp compares both string chars by ASCII values
      if (strcmp(sortedArray[index], sortedArray[nextIndex]) > 0)
      {
        temp = sortedArray[index];
        sortedArray[index] = sortedArray[nextIndex];
        sortedArray[nextIndex] = temp;
      }
    }
  }
  return sortedArray;
}

int main()
{
  int size = 4;
  char *names[size];
  char *result;

  for (int i = 0; i < size; i++)
  {
    printf("(%d) Enter a name: ", i);
    scanf("%s", names[i]);
  }

  result = sortAlphabetically(names, size);

  if (result)
  {
    for (int i = 0; i < size; i++)
      printf("%s", result[i]);

    free(result);
    return 0;
  }
}

Sin embargo, parece que hay algo mal en la forma en que copié data a sortedArray usando snprintf.

Tengo la intención de devolver una nueva matriz de la función de clasificación.

¿Dónde exactamente lo estoy haciendo mal y cuál sería la mejor manera de prevenir la mutación?

1
Ismail 30 ago. 2020 a las 18:41

1 respuesta

La mejor respuesta

sortedArray debe definirse como char ** y asignarse como:

char **sortedArray = malloc(size * sizeof(*sortedArray));

Hay otros problemas tambien:

  • no asigna el espacio para las cadenas leídas por el usuario. Debe leer la cadena en una matriz y usar strdup() para asignar una copia de la cadena.
  • scanf("%s",...) es una falla de seguridad: una entrada suficientemente larga hará que scanf() escriba más allá del final de la matriz de destino. Pase un número máximo de bytes para almacenar como un número entre % y s.

Aquí hay una versión modificada:

/**
 * clone an array of strings
 * @param array (source)
 * @param array_size (source)
 * @return array
*/
char **cloneArray(char *source[], int size) {
    char **destination = NULL;
    if (source) {
        destination = malloc(size * sizeof(*destination));
        if (destination) {
            for (int i = 0; i < size; i++) {
                destination[i] = strdup(source[i]);
            }
        }
    }
    return destination;
}

/**
 * free an array of strings
 * @param array
 * @param array_size
 * @return void 
*/
void freeArray(char *array[], int size) {
    if (array) {
        for (int i = 0; i < size; i++) {
            free(array[i]);
        }
        free(array);
    }
}

/**
 * sort data lexicographically into a new array with duplicate strings
 * @param array array of strings
 * @param array_size array size
 * @return a lexicographically sorted array
*/
char **sortAlphabetically(char *data[], int size) {
    char **sortedArray = cloneArray(data, size);

    // check for allocation failure
    if (!sortedArray)
        return NULL;

    for (int index = 0; index < size; index++) {
        for (int nextIndex = index + 1; nextIndex < size; nextIndex++) {
            // return positive integer if string1 is greater than string2,
            //        negative if lesser and
            //        0 if equal.
            // strcmp compares both string chars by unsigned char values
            if (strcmp(sortedArray[index], sortedArray[nextIndex]) > 0) {
                char *temp = sortedArray[index];
                sortedArray[index] = sortedArray[nextIndex];
                sortedArray[nextIndex] = temp;
            }
        }
    }
    return sortedArray;
}

int main() {
    int size = 4;

    char **names = malloc(size * sizeof(*names));
    if (names == NULL)
        return 1;

    for (int i = 0; i < size; i++) {
        char buf[100];

        printf("\n(%d) Enter a name: ", i);

        if (scanf("%99s", buf) != 1)
            return 1;

        names[i] = strdup(buf);
        if (names[i] == NULL)
            return 1;
    }

    char **result = sortAlphabetically(names, size);

    if (result) {
        for (int i = 0; i < size; i++)
            printf("%s\n", result[i]);
        freeArray(result, size);
    }

    freeArray(names, size);
    return 0;
}
1
chqrlie 31 ago. 2020 a las 11:37