Сортировка структурных переменных(3 int) в файле от наименьшего до наибольшего C

#c #function #file #sorting

Вопрос:

Мне нужно отсортировать мои 2 текстовых файла для моего проекта. Один из текстовых файлов находится в формате студенческого билета, идентификатора курса и оценки, а другой-в формате студенческого билета. Я записал значения в обоих из них с помощью fprintf, поэтому я использую fscanf во время чтения, но моя функция работает неправильно, можете ли вы сказать мне, в чем моя ошибка?

(Я удалил старый код, который не работал, потому что я продолжил использовать другой код)

Изменить :Я попытался создать фрагмент кода на основе приведенного ниже решения, но когда я ввожу цикл while, fscanf начинает получать неправильные числа. Можете ли вы найти, в чем моя ошибка?

Редактировать :После редактирования здесь я выполнил проверки fopen. С ними нет никаких проблем. Цикл while закрывается после того, как он выполняется один раз, я думаю, что в частях if fscanf fscanf неправильно считывает число, поэтому он выходит из цикла с перерывом.

скорее всего, сломанная часть:

     FILE *index = fopen("index.txt", "r");
    FILE *record = fopen("record.txt", "r");
    if (!index)
        return;
    if (!record)
        return;
    int array[n][3];
    //int *array = (int *)malloc(n *3 sizeof(int));???
    int count = 0;
    int i=0,temp,id,course,score;
    while (1)
    {  
        if(count==n) break;
        if (fscanf(record, "%d", amp;id) != 1) break;
        if (fscanf(record, "%d", amp;course) != 1) break;
        if (fscanf(record, "%d", amp;score) != 1) break;
        array[count][0] = id;
        array[count][1] = course;
        array[count][2] = score;
        count  ;
    }
 

остальная часть функции для просмотра, если ошибка находится в другом месте:

 void sort_for_bin_search(int n)
{
    FILE *index = fopen("index.txt", "r");
    FILE *record = fopen("record.txt", "r");
    if (!index)
        return;
    if (!record)
        return;
    int array[n][3];
    //int *array = (int *)malloc(n *3 sizeof(int));???
    int count = 0;
    int i=0,temp,id,course,score;
    while (1)
    {  
        if(count==n) break;
        if (fscanf(record, "%d", amp;id) != 1) break;
        if (fscanf(record, "%d", amp;course) != 1) break;
        if (fscanf(record, "%d", amp;score) != 1) break;
        array[count][0] = id;
        array[count][1] = course;
        array[count][2] = score;
        count  ;
    }
     for (i = 1; i < n - 1; i  )
    {
        for (int j = 0; j < n - 1; j  )
        {
            if(array[i][0] > array [j][0])
            {
            temp=array[j][0];
            array[j][0] = array[i][0];
            array[i][0] = temp;

            temp=array[j][1];
            array[j][1] = array[i][1];
            array[i][1] = temp;

            temp=array[j][2];
            array[j][2] = array[i][2];
            array[i][2] = temp;
            }
            else if((array[i][0]==array[j][0])amp;amp;(array[i][1]>array[j][1]))
            {
            temp=array[j][0];
            array[j][0] = array[i][0];
            array[i][0] = temp;

            temp=array[j][1];
            array[j][1] = array[i][1];
            array[i][1] = temp;

            temp=array[j][2];
            array[j][2] = array[i][2];
            array[i][2] = temp;
            }

        }
    }
    fclose(record);
    fclose(index);
    FILE *index2 = fopen("index.txt", "w");
    FILE *record2 = fopen("record.txt", "w");
    for (i = 0; i < n; i  )
    {
        fprintf(index2,"%dn",array[i][0]);
        fprintf(record2,"%d %d %dn",array[i][0],array[i][1],array[i][2]);
        //printf("%d %d %dn",array[i][0],array[i][1],array[i][2]);
    }
    //free(array);
    fclose(record2);
    fclose(index2);
}
 

Комментарии:

1. Вам абсолютно необходимо проверить fopen , не получится ли

2. Добро пожаловать в SO. Что означает «работает неправильно»? Пожалуйста, укажите ваши входные данные, выходные данные и ожидаемые результаты. Если вы получаете какие-либо сообщения об ошибках, какие они?

3. Ваш подход неверен, ваше использование fseek не имеет смысла с текстовыми файлами. Вы также должны обрабатывать чтение из файлов, сортировку и запись в файлы отдельно, а не выполнять все три одновременно

4. fseek(record, 3*sizeof(int) * j, SEEK_SET); Вы вычисляете размер в байтах, а не в текстовом представлении. Как писал Бармаглот, fseek текстовые файлы и текстовые файлы не очень хорошо сочетаются друг с другом.

5. Я новичок в файловых операциях, если я не могу использовать его таким образом, что бы вы посоветовали мне использовать вместо этого?

Ответ №1:

Похоже, вы выполняете сортировку пузырьков, и на каждой итерации вы читаете/записываете с диска. Операции с дисками выполняются очень медленно. Это намного проще и быстрее, если вы прочитаете один раз в массиве. А затем отсортируйте этот единственный массив.

Пример:

 void sort_for_bin_search(int n)
{
    //assumes that `n` is the number of lines in this file
    if (n < 1) return;
    FILE* fin = fopen("index.txt", "r");
    if (!fin)
        return;
    FILE* fout = fopen("record.txt", "w");
    if (!fout)
        return;

    int* arr = malloc(n * sizeof(int));
    if (!arr) return;
    int count = 0;
    while (1)
    {
        if (count == n)
            break;
        int id, course, score;
        if (fscanf(fin, "%d", amp;id) != 1) break;
        if (fscanf(fin, "%d", amp;course) != 1) break;
        if (fscanf(fin, "%d", amp;score) != 1) break;
        arr[count] = id;
        count  ;
    }
    //add code for sorting arr
    for (int i = 0; i < count; i  )
        fprintf(fout, "%dn", arr[i]);

    free(arr);
    fclose(fin);
    fclose(fout);
}
 

Затем вы можете выполнить сортировку, например, с помощью пузырьковой сортировки.

Используйте printf для печати данных на экране на каждом шаге, это поможет при отладке.

 void sort_for_bin_search(int n)
{
    FILE* fin = fopen("input_file.txt", "r");
    if (!fin)
    {
        printf("input errorn");
        return;
    }
    int array[n][3];
    int count = 0;
    while (1)
    {
        int id, course, score;
        if (count == n) break;
        if (fscanf(fin, "%d", amp;id) != 1) break;
        if (fscanf(fin, "%d", amp;course) != 1) break;
        if (fscanf(fin, "%d", amp;score) != 1) break;
        array[count][0] = id;
        array[count][1] = course;
        array[count][2] = score;
        count  ;
    }
    n = count;
    printf("reading:n");
    for (int i = 0; i < n; i  )
        printf("%d %d %dn", array[i][0], array[i][1], array[i][2]);

    printf("nsortn");
    for (int i = 0; i < n; i  )
    {
        for (int j = 0; j < n - 1 - i; j  )
        {
            if (array[j][0] > array[j   1][0])
            {
                int temp;
                temp = array[j][0];
                array[j][0] = array[j   1][0];
                array[j   1][0] = temp;

                temp = array[j][1];
                array[j][1] = array[j   1][1];
                array[j   1][1] = temp;

                temp = array[j][2];
                array[j][2] = array[j   1][2];
                array[j   1][2] = temp;
            }
        }
    }
    fclose(fin);

    printf("sortedn");
    for(int i = 0; i < n; i  )
        printf("%d %d %dn", array[i][0], array[i][1], array[i][2]);

    printf("write to filen");
    FILE* fout = fopen("output_file.txt", "w");
    if(!fout)
    {
        printf("output errorn");
        return;
    }
    for (int i = 0; i < n; i  )
        fprintf(fout, "%d %d %dn", array[i][0], array[i][1], array[i][2]);
    fclose(fout);
}
 

Комментарии:

1. Поскольку они еще не учили нас рекурсии, они особенно хотели использовать сортировку по пузырькам или двоичную сортировку, я выбрал сортировку по пузырькам, потому что это было проще.

2. Спасибо @chux-RestorateMonica

3. @Yodax93 Игнорируйте qsort , я просто поместил это туда, чтобы быстро протестировать код. Вы должны иметь возможность переписать свой код для сортировки пузырьков в массиве arr .

4. Я немного изменил код и интегрировал его в свой проект, но внутри цикла while код начинает ломаться, и в результате массив начинает возвращать очень странные числа. Можете ли вы найти, где находится ошибка?

5. Я не могу понять, какой из них является вашим входным файлом, а какой-выходным. Я переименовал файл. Используйте правильное имя и выводите массив на экран на каждом шаге. Похоже, что с вашей сортировкой пузырьков тоже есть проблема, я заменил ее своей версией. Вам действительно следует начать с 1-D массива, прежде чем переходить к 3-D массиву.