fread给出空结果并检测到glibc

时间:2014-12-22 12:14:32

标签: c

我想读取一个txt / dat文件,我正在使用以下代码,但它没有加载文件,因为它为每个指针打印零值。

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

int main( int argc, const char* argv[] ){

    const int N = 10;
    double *t = (double*) malloc ( N * sizeof(double) ); 
    double *x = (double*) malloc ( N * sizeof(double) );
    double *v = (double*) malloc ( N * sizeof(double) );

    FILE * theFile;
    theFile = fopen( "testFile.dat", "w" );
    assert( NULL != theFile );

    printf("\n BEFORE \n");
    for ( int i = 0; i < N; i++ ) 
    {   

        t[ i ] = i;
        x[ i ] = i + 1;
        v[ i ] = i * 2;

        // write result to file
        fprintf ( theFile, "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] );        

        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] );

    }

    fclose( theFile );

    // open file for reading
    theFile = fopen( "testFile.dat", "r" );
    assert( NULL != theFile );

    const int buffSize = 3;
    double buffer[ buffSize ];

    fread( buffer, buffSize , N , theFile );

    t = &buffer[ 0 ];
    x = &buffer[ 1 ];
    v = &buffer[ 2 ];

    printf("\n AFTER \n");
    for ( int i = 0; i < N; i++ )
        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ],x[ i ],v[ i ] );

    fclose( theFile );

    free ( t );
    free ( x );
    free ( v );


return 0;

}

另外,在我们有不同数据类型的情况下,例如2个双精度数和1个整数数,我会使用2个不同的缓冲区并调用fread 2次?

5 个答案:

答案 0 :(得分:1)

您的fread来电写在buffer

的末尾
fread( buffer, buffSize , N , theFile );

如何最好地解决这个问题取决于您正在尝试做什么。例如,要将三个双打读入buffer,这应该是:

fread( buffer, sizeof(double), buffSize , theFile );

答案 1 :(得分:1)

如果使用fprintf写入文件,则应使用fscanf(使用相同的格式参数)将其读回。另外,你在阅读部分搞砸了缓冲。我想你的阅读代码应该如下所示(只有最重要的修改):

// open file for reading
    theFile = fopen( "testFile.dat", "r" );
    assert( NULL != theFile );

    const int buffSize = 3;
    double buffer[ buffSize ];
    for ( int i = 0; i < N; i++ )
    {
        fscanf(theFile, "%f \t %f \t %f \n", &buffer[0], &buffer[1], &buffer[2]);
        t[i] = buffer[ 0 ];
        x[i] = &buffer[ 1 ];
        v[i] = &buffer[ 2 ];
    }


    printf("\n AFTER \n");
    for ( int i = 0; i < N; i++ )
    {
        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ],x[ i ],v[ i ] );
    }

    fclose( theFile );

答案 2 :(得分:1)

您的fprintf()正在将双打作为字符串(由制表符分隔)写入文件 - 这是转换说明符%5.5f的作用 - 它将双精度转换为字符串表示形式。一个例子是testFile.dat的第一行:

0.00000          1.00000         0.00000

后来你试图读回双打,但你试图把它们看成是原始的双打,而不是字符串。您应该可以使用fscanf()来读取双打。

答案 3 :(得分:1)

要回读这些值,你应该将每一行作为一个字符串读取并解析它以提取浮点值这是你的代码,修复为这样做

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

int main( int argc, const char* argv[] ){

    const int N = 10;
    double *t = malloc ( N * sizeof(double) );
    double *x = malloc ( N * sizeof(double) );
    double *v = malloc ( N * sizeof(double) );

    FILE * theFile;

    theFile = fopen( "testFile.dat", "w" );
    assert( NULL != theFile );

    printf("\n BEFORE \n");
    for ( int i = 0; i < N; i++ )
    {

        t[ i ] = i;
        x[ i ] = i + 1;
        v[ i ] = i * 2;

        // write result to file
        fprintf ( theFile, "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] );

        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] );

    }

    fclose( theFile );

    // open file for reading
    theFile = fopen( "testFile.dat", "r" );
    assert( NULL != theFile );

    int i = 0;
    while (fscanf(theFile, "%f%f%f", &(t[i]), &(x[i]), &(v[i])) == 3) i++;

    printf("\n AFTER \n");
    for ( int i = 0; i < N ; i++ )
        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ],x[ i ],v[ i ] );

    fclose( theFile );

    free ( t );
    free ( x );
    free ( v );


    return 0;
}

您的原始代码声明了一个大小为3的数组,并将指针t xv重新指向数组,以下是{ {1}}以及对for的调用将尝试free数组而非原始free指针。

如果您不需要以人类可读格式存储数据,则可以使用此

malloc

作为最后一点,总是检查#include <stdio.h> #include <stdlib.h> #include <assert.h> int main( int argc, const char* argv[] ){ const int N = 10; double *t = malloc ( N * sizeof(double) ); double *x = malloc ( N * sizeof(double) ); double *v = malloc ( N * sizeof(double) ); FILE * theFile; theFile = fopen( "testFile.dat", "w" ); assert( NULL != theFile ); printf("\n BEFORE \n"); for ( int i = 0; i < N; i++ ) { t[ i ] = i; x[ i ] = i + 1; v[ i ] = i * 2; // write result to file //fprintf ( theFile, "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] ); printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] ); } fwrite(t, sizeof(double), N, theFile); fwrite(x, sizeof(double), N, theFile); fwrite(v, sizeof(double), N, theFile); fclose( theFile ); // open file for reading theFile = fopen( "testFile.dat", "r" ); assert( NULL != theFile ); fread(t, sizeof(double), N, theFile); fread(x, sizeof(double), N, theFile); fread(v, sizeof(double), N, theFile); printf("\n AFTER \n"); for ( int i = 0; i < N ; i++ ) printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ],x[ i ],v[ i ] ); fclose( theFile ); free ( t ); free ( x ); free ( v ); return 0; } 的返回值,它会在失败时返回malloc,表示系统中没有足够的内存,如果你不检查它,它返回NULL,您第一次尝试访问它时会出现分段错误。

即使这段代码有效,但它仍然存在严重的不良做法问题,我修复了代码以使其更加健壮

NULL

答案 4 :(得分:1)

the following code:
1) compiles with no warnings 
2) contains commentary about each step 
   and what is wrong with the code

#include <stdio.h>
#include <stdlib.h>
#include <assert.h> // <-- using assert is not suitable for production code

int main() // <-- if not accessing argc and argv, do not included them
{
    // note, I do not have the C99 version of the compiler, 
    //       so moved the definition of 'i'
    int i; // loop counter

    const int N = 10;
    // <-- need to check for successful operation of each following call to malloc())
    double *t = (double*) malloc ( N * sizeof(double) );
    double *x = (double*) malloc ( N * sizeof(double) );
    double *v = (double*) malloc ( N * sizeof(double) );

    FILE * theFile;
    theFile = fopen( "testFile.dat", "w" );
    assert( NULL != theFile ); // <-- better to use perror and exit
                               //     so reason for fopen failure is broadcast

    printf("\n BEFORE \n");
    for ( i = 0; i < N; i++ )
    {

        t[ i ] = i;
        x[ i ] = i + 1;
        v[ i ] = i * 2;

        // write result to file
        fprintf ( theFile, "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] );

        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ], x[ i ], v[ i ] );

    }

    fclose( theFile );

    // open file for reading
    theFile = fopen( "testFile.dat", "r" );
    assert( NULL != theFile ); // <-- better to use perror and exit
                               //     so reason for fopen failure is broadcast

    const int buffSize = 3;
    double buffer[ buffSize ];

    // note: the file was written with three doubles, separated by ' \t '
    //       it needs to be read the same way
    //       suggest using fgets() to control a loop, 
    //       along with the strtok() and strtod() library functions
    //       to extract values from each line of the file
    fread( buffer, buffSize , N , theFile ); // <-- this will overflow buffer,
                                             //     resulting in undefined behaviour
                                             //     leading to a seg fault event

    t = &buffer[ 0 ];
    x = &buffer[ 1 ];
    v = &buffer[ 2 ];

    printf("\n AFTER \n");
    for ( i = 0; i < N; i++ )
        printf( "%5.5f \t %5.5f \t %5.5f \n", t[ i ],x[ i ],v[ i ] );

    fclose( theFile );

    free ( t );
    free ( x );
    free ( v );


return 0;

} // end function: main