c - 使用文件流插入代码

标签 c sorting insertion-sort

这是我正在处理的任务:

我收到一个 txt 文件,其中包含学生姓名、身份证号码、学校、专业和考试成绩的列表。

  • 读取此内容并复制到 C 中的结构体中。

  • 使用插入排序对此列表进行排序。

  • 在屏幕上打印排序列表。

我通过静音某些部分来检查我的编码,我的插入排序功能有错误。

我不知道哪一部分是错误的。这对我来说都很有意义。我需要帮助:(这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000
#define BUF_SIZE 80
typedef struct {
        char name[20];
        char studentID[10];
        char department[20];
        char major[20];
        int mid;
        int final;
} student;
FILE *fp;
void operation(student t, student list[], int j);
void insertion_sort(student list[], int n);
void printing(student list[], int n);

int main(int argc, char *argv[])
{
        char filename[20] = "studentlist.txt";

        int n = 1;              /* (number of students) + 1 */
        student list[MAX];
        char buffer[BUF_SIZE];
        int i;
        fp = fopen(filename, "r");
        while (1) {
                if (fgets(buffer, BUF_SIZE, fp) == NULL)
                        break;
                strncpy(list[n].name, buffer, strlen(buffer) - 1);
                fgets(buffer, BUF_SIZE, fp);
                strncpy(list[n].studentID, buffer, strlen(buffer) - 1);
                fgets(buffer, BUF_SIZE, fp);
                strncpy(list[n].department, buffer, strlen(buffer) - 1);
                fgets(buffer, BUF_SIZE, fp);
                strncpy(list[n].major, buffer, strlen(buffer) - 1);
                fgets(buffer, BUF_SIZE, fp);
                list[n].mid = atoi(buffer);
                fgets(buffer, BUF_SIZE, fp);
                list[n].final = atoi(buffer);
                n++;
        }

        fclose(fp);
        insertion_sort(list, n);
        printing(list, n);
        return 0;
}

void insertion_sort(student list[], int n)
{
        int i;
        student temp;
        for (i = 2; i < n; i++) {
                temp = list[i];
                operation(temp, list, i - 1);
        }

}

void operation(student t, student list[], int j)
{
        list[0] = t;
        while (t.studentID < list[j].studentID) {
                list[j + 1] = list[j];
                j--;
        }
        list[j + 1] = t;
}

void printing(student list[], int n)
{
        int i;
        for (i = 1; i < n; i++) {
                printf(" %s  ", list[i].name);
                printf(" %s  ", list[i].studentID);
                printf(" %s  ", list[i].department);
                printf(" %s  ", list[i].major);
                printf(" %6d  ", list[i].mid);
                printf(" %6d  ", list[i].final);
                putchar('\n');
        }
}

最佳答案

继续评论和第一个答案,您在 split insertion_sortoperation 函数之间产生跟踪索引错误。当一个函数可以工作(并且可以说更小)时,就不需要两个函数。拆分几乎没有什么好处(除了增加困惑)。

将一个简单的插入排序放在一个满足您需要的函数中(并使用指针进行排序,而不是重复使用函数复制构造函数来完成交换),您可以执行类似于以下操作的操作:

typedef struct {
    int id, g;
} student;

void insertion_sort (student **list, int nmemb)
{
    for (int i = 0; i < nmemb; i++)
        for (int j = i; j > 0 && list[j]->id < list[j-1]->id; j--)
        {
            student *tmp  = list[j];
            list[j]   = list[j-1];
            list[j-1] = tmp;
        }
}

整理一个简短的(且有限的结构成员示例),您可以执行以下操作,按 ID(或下面的 id)对学生数据进行排序

#include <stdio.h>

typedef struct {
    int id, g;
} student;

void insertion_sort (student **list, int nmemb)
{
    for (int i = 0; i < nmemb; i++)
        for (int j = i; j > 0 && list[j]->id < list[j-1]->id; j--)
        {
            student *tmp  = list[j];
            list[j]   = list[j-1];
            list[j-1] = tmp;
        }
}

void printing(student *list[], int n)
{
    int i;
    for (i = 0; i < n; i++) {
        printf(" %d  ", list[i]->id);
        printf(" %d  \n", list[i]->g);
    }
}

int main (void) {

    student s[] = { {.id = 5, .g = 72},    /* minimal student test data */
                    {.id = 2, .g = 91},
                    {.id = 4, .g = 77},
                    {.id = 1, .g = 96},
                    {.id = 3, .g = 85}};
    int n = sizeof s / sizeof *s;
    student *l[n];

    for (int i = 0; i < n; i++)  /* initialize pointers in l */
        l[i] = &s[i];

    insertion_sort (l, n);       /* sort pointers in l */
    printing (l, n);             /* output sorted pointers */

    return 0;
}

示例使用/输出

按学生 ID 排序

$ ./bin/inssort_so
 1   96
 2   91
 3   85
 4   77
 5   72

如果您确实想避免使用传递指针数组(实际上是一个指针到类型的指针)所涉及的额外间接级别,您可以使原来的方法起作用如下:

void insertion_sort (student *list, int nmemb)
{
    for (int i = 0; i < nmemb; i++)
        for (int j = i; j > 0 && list[j].id < list[j-1].id; j--)
        {
            student tmp  = list[j];
            list[j]   = list[j-1];
            list[j-1] = tmp;
        }
}

void printing (student *list, int n)
{
    for (int i = 0; i < n; i++)
        printf (" %d   %d  \n", list[i].id, list[i].g);
}

int main (void) {

    student s[] = { {.id = 5, .g = 72},
                    {.id = 2, .g = 91},
                    {.id = 4, .g = 77},
                    {.id = 1, .g = 96},
                    {.id = 3, .g = 85}};
    int n = sizeof s / sizeof *s;

    insertion_sort (s, n);
    printing (s, n);

    return 0;
}

当您继续前进时,还可以考虑将比较回调函数传递给您的排序例程。这允许您使用相同的排序例程对许多不同类型的数据进行排序 - 只需更改 compare 函数(如 C 库 qsort 例程所做的那样。

关于c - 使用文件流插入代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44354205/

相关文章:

c - 在 *nix 系统上的 C 中,使用 $PATH 或 "which"找到二进制文件的绝对路径?

database - Oracle 在两次使用同一列时无法正确排序

c - 为 Make 添加不同的对象目录

c - 如何在rabbitmq-c中使用扇出交换?

c - 为子进程重定向 IO

c - 理解 C 中的二维字符数组

javascript - 当分隔符从 ng : to ng- 更改时,Angular-JS 表排序不起作用

java - 插入排序和哨兵

java - 每当我调用 "InsertionSort"方法时,输出文件都显示为空?我应该在哪里调用这个方法?

java - 插入排序算法大o : iterative and recursive