我试图制作一个简单的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多个小时试图找出如何解决这个问题,没有运气。
答案 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数字最终会有一个地方,因为有些数字的长度与其他数字不同)。
只有文件每行的每个数字大小相同时,您的程序才有效。 即便如此,你还有其他一些问题,比如文件中的最后一个数字永远不会移动。