首页 > 解决方案 > 如何按字母顺序对字符串数组进行排序并防止c中的突变

问题描述

如何在 c 中按字母顺序对字符串数组进行排序?

这是我的尝试:

/**
 * 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;
  }
}

data但是,我复制到sortedArrayusing的方式似乎有问题snprintf

我打算从排序函数返回一个新数组。

我到底在哪里弄错了,防止突变的最佳方法是什么?

标签: arrayscstring

解决方案


sortedArray应定义为 achar **并分配为:

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

还有其他问题:

  • 您没有为从用户读取的字符串分配空间。您应该将字符串读入数组并用于strdup()分配字符串的副本。
  • scanf("%s",...)是一个安全漏洞:足够长的输入将导致scanf()写入超出目标数组的末尾。传递要存储为%和之间的数字的最大字节数s

这是修改后的版本:

/**
 * 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;
}

推荐阅读