C文件指针读写问题

时间:2009-10-07 05:26:14

标签: c file-io text-files

我试图制作一个简单的bubbleort程序。

从文本文件中读取数字并将它们与下一行进行比较,按升序排序。

现在,我发现我的程序能够正常读取文件,当我使用任何写命令(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 个答案:

答案 0 :(得分:2)

嗯,我可能会重新考虑这个方法。

  • 你真的打算做外部排序吗?如果没有,那么只需读取文件,在内存中对其进行排序,然后将其写出来就会更加清晰。
  • 无论以前的答案如何,是否真的有必要进行排序?即使对于外部排序,是否可以在您的问题参数范围内写出新文件而不是尝试将单个文件压缩为排序顺序?
  • 我认为冒泡排序是一种在编辑具有可变长度线的文本文件时实际工作的排序,因为每当你想在长线上写一个长数字时你也有一个短数字和旁边的长行。 (发抖

如果你确实想要进行外部排序,那么我的建议是你将操作重构为小函数,这样你就可以分解必要的逻辑而不会混淆。

更新:忘记上面的建议,我已经决定我喜欢这个问题了。不幸的是,我已经阅读了Yuliy的回答。

答案 1 :(得分:2)

交换两个相邻字符的代码存在缺陷。请注意,如果您有两个数字1和234,它们最初在文件中显示为1\n234\n,但如果交换,则1不会从文件中的索引2开始(234最初启动时),而是在指数4。

因此,如果您交换两个数字prev和curr,其中prev是文件中最初的两个数字,请将curr置于prev的位置,并在完成写入curr后将换行符放在换行符之后。请注意,这是局部变化(因为len(prev)+ len(curr)== len(curr)+ len(prev)。

答案 2 :(得分:1)

由于您的号码具有不同的字符数,因此您无法在一般情况下执行此操作。您应该只读入所有数字,在内存中排序,然后使用包含已排序数字的新文件覆盖现有文件。

答案 3 :(得分:0)

在您的问题排查中添加一些内容,您应该会很快看到: printf(“CurPost:%d \ n”,currpos); printf(“PrevPos:%d \ n”,prevpos); printf(“NextPos:%d \ n”,nextpos);

(提示:你的数字长度不同,所以你的currpos和nextpos数字最终会有一个地方,因为有些数字的长度与其他数字不同)。

只有文件每行的每个数字大小相同时,您的程序才有效。 即便如此,你还有其他一些问题,比如文件中的最后一个数字永远不会移动。