模仿linux的sort命令,对文本文件进行排序。

问题描述 投票:0回答:1

linux的Sort命令必须对文本文件的行数进行排序,并将输出结果传送到另一个文件。但我的代码给出了一个运行时错误。请纠正指针错误,以便输出。

我到底应该在哪一行进行修改?因为毕竟没有输出。

我把整个代码粘贴过来。

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

void sortfile(char **arr, int linecount) {
    int i, j;
    char t[500];

    for (i = 1; i < linecount; i++) {
        for (j = 1; j < linecount; j++) {
            if (strcmp(arr[j - 1], arr[j]) > 0) {
                strcpy(t, arr[j - 1]);
                strcpy(arr[j - 1], arr[j]);
                strcpy(arr[j], t);
            }
        }
    }
}

int main() {
    FILE *fileIN, *fileOUT;

    fileIN = fopen("test1.txt", "r");

    unsigned long int linecount = 0;
    int c;
    if (fileIN == NULL) {
        fclose(fileIN);
        return 0;
    }

    while ((c = fgetc(fileIN)) != EOF) {
        if (c == '\n')
            linecount++;
    }

    printf("line count=%d", linecount);
    char *arr[linecount];
    char singleline[500];

    int i = 0;
    while (fgets(singleline, 500, fileIN) != NULL) {
        arr[i] = (char*)malloc(500);
        strcpy(arr[i], singleline);
        i++;
    }

    sortfile(arr, linecount);

    for (i = 0; i < linecount; i++) {
        printf("%s\n", arr[i]);
    }
    fileOUT = fopen("out.txt", "w");
    if (!fileOUT) {
        exit(-1);
    }

    for (i = 0; i < linecount; i++) {
        fprintf(fileOUT, "%s", arr[i]);
    }

    fclose(fileIN);
    fclose(fileOUT);
}
c sorting pointers file-handling
1个回答
0
投票

你的代码中的问题是,你在第一次读取输入流后没有倒带计算新行数。 你应该在代码中加入 rewind(fileIN); 在下一个循环之前。

但是请注意,这段代码中还有其他问题。

  • 换行字符的数量可能比成功调用 fgets()注:超过499字节的行将被无声地分成多块,导致更多的项目被读取。fgets() 而不是换行。 另外最后一行也可能不以换行结束。只要计算一下成功调用 fgets().
  • 你为每一行分配了500个字节,这可能是非常浪费的。使用 strdup() 来只分配必要的大小。
  • 在排序例程中交换行应该通过交换指针来完成,而不是复制内容。
  • 分配 arrmalloc 比起将其定义为一个可变大小的数组,用 char *arr[linecount];

这是一个修改后的版本。

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

void sortfile(char **arr, int linecount) {
    for (;;) {
        int swapped = 0;
        for (int j = 1; j < linecount; j++) {
            if (strcmp(arr[j - 1], arr[j]) > 0) {
                char *t = arr[j - 1];
                arr[j - 1] = arr[j];
                arr[j] = t;
                swapped = 1;
            }
        }
        if (swapped == 0)
            break;
    }
}

int main() {
    FILE *fileIN, *fileOUT;
    char singleline[500];
    int i, linecount;

    fileIN = fopen("test1.txt", "r");
    if (fileIN == NULL) {
        fprintf(stderr, "cannot open %s\n", "test1.txt");
        return 1;
    }

    linecount = 0;
    while (fgets(singleline, 500, fileIN)) {
        linecount++;
    }

    printf("line count=%d\n", linecount);

    char **arr = malloc(sizeof(*arr) * linecount);
    if (arr == NULL) {
        fprintf(stderr, "memory allocation failure\n");
        return 1;
    }

    rewind(fileIN);
    for (i = 0; i < linecount && fgets(singleline, 500, fileIN) != NULL; i++) {
        arr[i] = strdup(singleline);
        if (arr[i] == NULL) {
            fprintf(stderr, "memory allocation failure\n");
            return 1;
        }
    }
    fclose(fileIN);

    if (i != linecount) {
        fprintf(stderr, "line count mismatch: i=%d, lilnecount=%d\n",
                i, linecount);
        linecount = i;
    }

    sortfile(arr, linecount);

    for (i = 0; i < linecount; i++) {
        printf("%s", arr[i]);
    }
    fileOUT = fopen("out.txt", "w");
    if (!fileOUT) {
        fprintf(stderr, "cannot open %s\n", "out.txt");
        return 1;
    }
    for (i = 0; i < linecount; i++) {
        fprintf(fileOUT, "%s", arr[i]);
    }
    fclose(fileOUT);

    for (i = 0; i < linecount; i++) {
        free(arr[i]);
    }
    free(arr);
    return 0;
}

为了得到不同的排序顺序,你需要改变比较函数。取而代之的是 strcmp() 你可以用这个。

#include <ctype.h>

int my_strcmp(const char *s1, const char *s2) {
    /* compare strings lexicographically but swap lower and uppercase letters */
    unsigned char c, d;
    while ((c = *s1++) == (d = *s2++)) {
        if (c == '\0')
            return 0;   /* string are equal */
    }
    /* transpose case of c */
    if (islower(c)) {
        c = toupper(c);
    } else {
        c = tolower(c);
    }
    /* transpose case of d */
    if (islower(d)) {
        d = toupper(d);
    } else {
        d = tolower(d);
    }
    /* on ASCII systems, we should still have c != d */
    /* return comparison result */
    if (c <= d)
        return -1;
    } else {
        return 1;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.