#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 массиву.