Проблемы с указателем чтения файла C - PullRequest
1 голос
/ 07 октября 2009

Я пытался создать простую программу для сортировки пузырьков.

Считать числа из текстового файла и сравнить их со следующей строкой, отсортировать по возрастанию.

Теперь я обнаружил, что моя программа умеет читать из файла очень хорошо, и когда я использую какие-либо команды записи (fprintf или fputs), все идет не так.

Я пытался использовать ftell и fseek, и у меня была та же проблема.

Предполагается, что текстовый файл содержит:

1804289383
846930886
1681692777
1714636915
1957747793
424238335
719885386
1649760492
596516649

Он застревает в бесконечном цикле с

846930886

846930886
8804289383
8804289383 ...

как вывод в файл и 8804289383 повторение снова и снова

int main(void) {

int swapped;
int run_once;

// pointers

FILE *filep;

// file positions

fpos_t currpos;
fpos_t prevpos;
fpos_t nextpos; 

            /**
              * next pos helps represent where the file pointer was 
              * before the switch was initiated
            */

// swap variables

unsigned long long int prev;
unsigned long long int curr;

// string inputs

char buffer[20];

// open file stream

filep = fopen("dataFile.txt","r+"); // looks for the file to open for r/w

if (filep == NULL) {                        // check for file
    fprintf(stderr, "dataFile.txt does not exist!!\n");
    return 1;
}


// bubble sort

do {
    rewind(filep); // starts the pointers at the start of the file

    fgetpos(filep,&currpos);
    prevpos = currpos;
    nextpos = currpos;  


    swapped = 0; // swapped = false

    curr = 0;
    prev = 0;


    fgets(buffer, 20, filep); // need to read before loop or else it doesn't end properly       


    while (!feof(filep)) {      // while it's not the end of the file

        fgetpos(filep,&nextpos);

        sscanf(buffer,"%lld",&curr); // convert to unsigned long long


        printf("Prev: %lld\n",prev);    // troubleshooting stuff
        printf("Curr: %lld\n",curr);

        if (prev > curr) {      
            fsetpos(filep,&prevpos);    // move filep to previous
            fprintf(filep,"%lld\n",curr);   // print current to previous spot

            fsetpos(filep,&currpos);    // move filep to current
            fprintf(filep,"%lld\n",prev);   // print previous to current spot

            printf("Swapped!\n");   // more troubleshooting

            swapped = 1;        // swapped = true

            fsetpos(filep,&nextpos);    // reset filep by moving it to nextpos
        }


        if (prev < curr) {
            prev = curr;    // no need to swap since prev will continue to be the previous value 
        }


        // increment the postions
        prevpos = currpos;
        currpos = nextpos;

        fgets(buffer, 20, filep);
     }

} while (swapped == 1);


// close file stream

fclose(filep);  

return 0;

}

Большое спасибо за вашу помощь, потому что я потратил более 10 часов, пытаясь понять, как это исправить, но безуспешно.

Ответы [ 4 ]

2 голосов
/ 07 октября 2009

Ваш код для замены двух соседних символов некорректен. Обратите внимание, что если у вас есть два числа 1 и 234, они появляются внутри файла изначально как 1\n234\n, но если поменять местами, 1 не начинается с индекса 2 в файле (где изначально были 234), а вместо этого с индекса 4 .

В результате, если вы поменяете местами два числа prev и curr, причем prev - это первое из двух чисел в файле, изначально, поместите curr в положение prev и prev после новой строки после того, как вы закончили писать curr. Обратите внимание, что это локальное изменение (поскольку len (prev) + len (curr) == len (curr) + len (prev).

2 голосов
/ 07 октября 2009

Хм, я мог бы пересмотреть подход.

  • Это действительно ваше намерение сделать внешнюю сортировку? В противном случае было бы намного чище просто прочитать файл, отсортировать его в памяти, а затем записать его.
  • Независимо от предыдущего ответа, действительно ли необходимо сортировать на месте? Даже для внешней сортировки, будет ли в ваших параметрах задачи записывать новый файл вместо попытки разбить один файл в отсортированном порядке?
  • Полагаю, пузырьковая сортировка - это единственный вид сортировки, который действительно будет работать при редактировании текстового файла со строками переменной длины, потому что всякий раз, когда вы хотите записать длинное число на короткую строку, у вас также есть короткая номер и длинная линия прямо рядом с ним. ( Shudder )

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

Обновление: забудьте вышеупомянутый совет, я решил, что мне нравится эта проблема, как она есть. К сожалению, я уже прочитал ответ Юлия.

1 голос
/ 07 октября 2009

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

0 голосов
/ 07 октября 2009

Добавьте кое-что к устранению неполадок, и вы, вероятно, увидите, что ваш подход, скорее всего, появится довольно быстро: printf ("CurPost:% d \ n", currpos); printf («PrevPos:% d \ n», prevpos); printf ("NextPos:% d \ n", nextpos);

(подсказка: ваши номера имеют разную длину, так что ваши номера curppos и nextpos заканчиваются на одно место, потому что некоторые числа имеют длину, отличную от других номеров)

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

...