3

我只是想得到一组有序的数字(虽然我发布的代码不是我要使用的方法,但我确实需要将输出写入二进制文件,就像代码中所做的那样)。
一切正常,除了“ordenar”的最后一次迭代:当我在订购后再次打印数字时,除了最后一行之外的所有东西都是有序的,我已经验证了 ordenar 正确完成,并且fwrite()在最后一次迭代中是返回值 10,但似乎它没有写入最后一个输出。

代码是:

#define _CRT_SECURE_NO_DEPRECATE
#define SIZE 10
#define MAX  10

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int numbers[SIZE];


int genera_numeros() {
    unsigned long i, j;
    FILE *file;

    file = fopen("number.dat", "wb");
    if (!file) {
        perror("fopen");
        return 1;    
    }

    srand(time(0));
    for (i = 0; i < MAX; i++) {
        for (j = 0; j < SIZE; j++) {
            numbers[j] = rand()%1000;
            printf("%i ", numbers[j]);
        }
        fwrite(numbers, sizeof(int), SIZE, file);
        printf("\n");
    }
    fclose(file);
    return 0;
} 


int imprime_numeros() {
    unsigned long i, j;
    int numbers[SIZE];
    FILE *file;

    file = fopen("number.dat", "rb");
    if (!file) {
        perror("fopen");
        return 1;
    }

    for (i = 0; i < MAX; i++) {
        fread(numbers, sizeof(int), SIZE, file);
        for (j = 0; j < SIZE; j++) {
            printf("%i ",numbers[j]);
        }
        printf("\n");
    }
    fclose(file);
    return 0;
}

int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}


int ordenar(FILE* file, long int num_bloque)
{
    int byte=0, written=0;
    fseek(file, num_bloque * sizeof(int) * SIZE, SEEK_SET);
    fread(numbers, sizeof(int), SIZE, file);
    qsort (numbers, SIZE, sizeof(int), compare);
    fseek(file, num_bloque * sizeof(int) * SIZE, SEEK_SET);
    byte=ftell(file);
    written=fwrite(numbers, sizeof(int), SIZE, file);
    return 0;
} 


int main(int argc, char* argv[]) {
    FILE *file;
        file = fopen("number.dat", "rb+");
    long int i;

    genera_numeros();
    printf("\n\n Los numeros son:\n\n");
    imprime_numeros();
    printf("\n\n Ordenando...");

    for (i=0; i<MAX; i++)
    {   
        ordenar(file, i);
    }

    printf("\n\n Los numeros son:\n\n");
    imprime_numeros();
    printf("\n");

    fclose(file);
    system("PAUSE");
    return 0;
}
4

1 回答 1

3

对于初学者,因为我不知道你的代码到底应该做什么,所以删除给你的段错误。
fileimprime_numeros()和 in关闭你main()。删除一个或另一个,您的程序就可以工作。



这是我对未对最后一行进行排序的问题的解决方案。只需再进行一次迭代

for(i=0;i<MAX+1;i++){

它有效。我目前正在研究解决方案的“为什么”部分。
编辑 1
我花了一段时间,但它是这样的:
在你的 main() 中你有FILE* file=fopen(..),这是你唯一不检查它是否正确打开的地方。每次您的程序第一次运行时,它都找不到该文件并且file在 main() 中设置为 NULL。

然后它愉快地继续并调用genera_numeros()打开自己的文件(并创建 numbers.dat btw ...)但在本地范围内的函数,因为 outsidegenera_numeros() file仍然是 NULL。

因此它创建一个文件,填充它并继续imprima_numeros()打开先前创建的文件numbers.dat(仍在本地范围内,使用后关闭此文件)。

然后是ordenar部分,事情开始变得有趣。
ordenar(file, i)获取您的 NULL 文件并...因分段错误而崩溃。
有趣的部分,并且欺骗了我的是,这不会您第二次运行程序时发生,因为numbers.dat它将保留在之前的运行中)。

编辑 2. 最终 结果 是的,我刚刚花了 2 个非付费的深夜时间来查找别人代码中的错误。我可能是那个人......无论如何......
问题是多次打开同一个文件。但是,我的意思是,当您通过打开不存在的文件来修复以前的错误时,或者只是第二次运行程序时,您在 main() 中打开一个文件,然后使用and
打开和关闭该文件几次。这应该是行为。 问题是,在您最后一次调用循环后,您重新打开它并写入最后排序的行在磁盘上的文件中尚不可见。这将在您关闭文件流后完成。因此,您会在将排序的最后一行写入文件之前看到文件的状态。 现在为什么我的imprime_numerosgenera_numerosimplementation-defined
ordenar()imprime_numeros

MAX+1有效的解决方案是它强制永久写入最后一行,因此它在您打开的文件中可见imprime_numeros()
几乎是全部。
请注意,通过添加 MAX+1,您将获得 440 字节大小的文件(我有 4 字节 int),它应该是 400。
我也忘了提及如何解决这个问题,但您可以通过我的描述找到它. 在读取之前
提示fclose(file)。 所有正在阅读此答案的人,我将感谢您对其语法、风格进行编辑。已经很晚了,这让我付出了很多。


于 2013-10-16T21:34:26.067 回答