【问题标题】:qsort function is causing issuesqsort 函数导致问题
【发布时间】:2015-09-27 07:18:13
【问题描述】:

这是我的代码

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

#define STRING_LENGTH 20
#define MAX 30

int read_string(char string[], int n);
int compare(const void*a, const void*b);

int main(){
    int i;

    char* word_list[30];
    char word[STRING_LENGTH + 1];

    for (i = 0; ; i++){
       printf("\nEnter a word.\n");
       read_string(word, STRING_LENGTH);

       if (word[0] == '\0')
           break;
       word_list[i] = (char *)malloc(STRING_LENGTH + 1);
       //free(word_list);
       strcpy(word_list[i], word);
    }

    int length = sizeof(word_list)/sizeof(char*);

    int j;

    qsort(word,length, sizeof(char*), compare);
    for (j = 0; word_list[j] != '\0'; j++)
        printf("%s\n", word_list[j]);

    return 0;
}

int compare(const void*element1, const void *element2){
    const char *string1 = *(const char**)element1;
    const char *string2 = *(const char**)element2;

    return strcmp(string1,string2);
}

int read_string(char string[], int n){
    int ch, i = 0;

    while ((ch = getchar()) != '\n')
        if (i < n)
            string[i++] = ch;
    string[i] = '\0';

    return i;
}

我的程序应该通过 read_string 函数读取字符串,然后使用strcpy 将它们作为指针数组的元素放置,然后名称按字母顺序排序。它编译并读取我的输入,但一旦到达qsort(),它就会崩溃。我知道qsort() 导致了问题,但我不知道为什么。任何帮助将不胜感激。

【问题讨论】:

  • 我必须为每个元素分配内存,以便可以将字符串复制到其中。当用户在没有输入任何内容后按下回车键时,就会发生循环中断。那部分不会给我带来任何问题
  • 是的,我注意到我没有看到它是一个 char* 数组
  • “这部分不会给我带来任何问题” - 再猜一次。 int length = sizeof(word_list)/sizeof(char*); 是错误的,除非您碰巧完全填充了所有 30 插槽。否则,您将对30-i 不确定的指针以及您did 填充的任何指针进行排序。一旦这些垃圾指针到达您的比较器并调用strcmp(取消引用它们),您就调用了未定义的行为
  • 问题是你给qsort() 完整的指针列表,不管它们中有多少实际上指向有效数据。此外,如果用户碰巧输入了更多单词,您的代码会愉快地写到 word_list 的末尾。永远不要写这样的代码...
  • 它们没有被使用。通过告诉qsort 要排序的实际项目数(您读取的字符串数)对列表进行排序。使用您读取的字符串数打印结果。如果您对最后一个问题很认真,那么您可能应该投资a decent book or two on C

标签: c arrays pointers qsort


【解决方案1】:

请注意,您要排序的是 word_list 而不是 word

int main() {
  int i;

  char* word_list[30];
  char word[STRING_LENGTH + 1];

  for(i = 0; ; i++) {
    printf("\nEnter a word.\n");
    read_string(word, STRING_LENGTH);

    if(word[0] == '\0')
      break;

    word_list[i] = (char *)malloc(STRING_LENGTH + 1);
    strcpy(word_list[i], word);
  }

  // call qsort with the number of items in the wordlist
  qsort(word_list, i, sizeof(char*), compare);

}


int compare(const void*element1, const void *element2){
  const char **string1 = (const char**)element1;
  const char **string2 = (const char**)element2;

  return strcmp(*string1,*string2);
}

您还应该在调用qsort() 之前将set length 调用为word_list 中的项目数,而不是单词中的字符数。

例如,如果您从stdin 中读到两个单词,那么您可以像这样调用qsort() qsort(word_list, 2, sizeof(char*), compare);

也许我还需要提一下,当你使用完单词列表后,你应该释放malloc()分配的内存。

【讨论】:

  • 感谢您的帮助。它没有崩溃,但是当我输入“foo”、“poo”和“boo”时,它打印了“foo”“poo”“奇怪的字符集”。
  • @Flower - 您需要使用列表中的单词数调用qsort()
  • 实际上它按字母顺序打印它们,我只是忽略了我的 for 循环。我的条件使用
  • @Flower - 很高兴我能帮上忙,你修好了 =)
【解决方案2】:

如 cmets 中指出的那样,存在许多问题。主要是您使用不正确的指针和不正确的成员数 (30) 而不是读取的字符串数调用 qsort。更正是:

qsort (word_list, i, sizeof (char *), compare);

虽然您可以在qsort 完成后使用哨兵停止打印,但为什么呢?您已经知道在i 中读取了多少字符串。很简单:

for (j = 0; j < i; j++)
    printf ("%s\n", word_list[j]);

顺便说一句,能够在read_string 中的任意数量的字符串之后停止输入会很有用。允许生成EOF 的键盘通过ctrl+d(Windows 上的ctrl+z)表示输入结束将起作用。例如:

while ((ch = getchar ()) != '\n' && ch != EOF)

【讨论】:

  • 这个 for 循环现在运行良好,但正如我在另一条评论中所说,我的最终字符串输出是一组随机字符
  • Hmm.. 我编译、调试并运行了上述更改的代码,没有发现任何问题。您需要确保在读取循环之后没有修改i,否则您将丢失读取的字符串数量。通常最好声明一个特定变量,比如 numstr 并遵循您的输入循环集 numstr = i;,因为您可能想再次使用 i 作为循环计数器。获得随机字符的唯一方法是read beyondword_list 中的字符串数。确保不会发生这种情况。
  • 我的 for 循环中只有
猜你喜欢
  • 2019-11-18
  • 2013-10-05
  • 2014-05-03
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 2015-06-20
相关资源
最近更新 更多