虽然 C 中的循环赋值没有按预期工作



尝试打印从按字母顺序排序的文件中读取的所有名称。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *a, const void *b){
    const char **ia = (const char **)a;
    const char **ib = (const char **)b;
    return strcmp(*ia, *ib);
}
int main(int argc, char* argv[]){
    //Takes input in terminal/cmd (filename.txt).
    char *input = malloc(sizeof(char) * 50);
    if (argc < 2){
        printf("Enter filename: ");
        scanf("%s", input);
    } else
        input = argv[1];
    //.......................

    int count = 0; //Names count
    char *names[100]; //Pointers to each name in file
    char str[50];
    FILE *file;
    file = fopen(input, "r");
    //Allocate space for the pointers
    for (int i = 0; i < 100;i++){
        names[i] = malloc(sizeof(char) * (50 + 1));
    }
    //Adding names to array
    if (file) {
        while ((fgets(str, 50, file)) != NULL){
            count++;
            names[count] = str;
            printf("%s", names[count]); //This will print names as read from file
        }      
        fclose(file);
        printf("%s", names[2]); //This will print the last name read with the while loop no matter the index of names[]
    } else printf("Can't read from file");
    //Sorting "names" in alphabetical order
    int length = sizeof(names)/sizeof(char*); //length of names
    qsort(names, length, sizeof(char*), compare);
    //printing each name (will be the last string read by while loop times the length)
    for(int i = 0; i < length; i++){
        printf("%s", names[i]);
    }
    printf("%d", count); //printing names count
}

编译和运行程序给了我这个输出:

Tredigar
Ghorvas
Wolvar
Lurtrum
Sabakzar
Hagan
Korlag
Malagar
Ferrek
Baelnar
Grimmalk
Roken
Vabul
Radek
Agaro
Krag
Balfam
Vistrum
Halzar
Maulnar
Auxlan
Krim
Borkul
Thorin
Morak
Arnan
Garmul
Avamir
Darkul
Bariken
Mardam
Hlant
Rogath
Melgar
Thorbalt
Dyrnar
Ezegan
Smethykk
Sharak
Swargar
Halagmar
Rozag
Orobok
Arval
Kurman
Erag
Dolmen
Glint
Haeltar
Haeltar
8┼Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
Haeltar
49

显然,我正在尝试按字母顺序对字符串进行排序。我目前的问题是,无论我在 while 循环之外打印 names[],指针都指向 Haeltar,这是在 while 循环中分配的姓氏。我已经搜索了很远很远,但无法弄清楚导致这种行为的原因。我对C编程比较陌生。

names[count] = str;为数组的每个成员分配str地址。他们都指向它。所以自然而然地都指向"Haeltar",这是最后写进str的。请注意,在执行分配时,您也会泄漏所有分配的内存。

您需要将names定义为char names[100][50],然后直接读取fgets(names[count], 50, file)。或者为每个成员分配内存(使用 malloc ,就像您已经做的那样(并复制到其中(使用 strcpy (1


1 如果您有幸使用POSIX系统,strdup可以在一次通话中同时完成这两项操作。

有几个错误:

首先,您必须将输入字符串复制到数组中,您只能替换最初来自 malloc 的指针。

strcpy(names[count], str);

接下来,您必须在使用后递增count,而不是之前:您0未使用的元素。

第三,您在两个应该使用count的地方使用length - 实际条目数,此处

qsort(names, count, sizeof(char*), compare);    // change length to count

和这里

for(int i = 0; i < count; i++) {                // change length to count

你有 2 个明显的错误:1(你过早地增加count。names 数组中的第一个条目未分配,并且可能会使应用崩溃,因为您尝试打印它。

if (file) {
        while ((fgets(str, 50, file)) != NULL){
            names[count] = str;
            printf("%s", names[count]); //This will print names as read from file
            ++count;
        }      

2(您计算字符串,但使用length打印。将其更改为count,它将起作用。

for(int i = 0; i < count; ++i){
        printf("%s", names[i]);    
}

最新更新