简体   繁体   中英

Error in reading uint32_t variable saved in a file

I have an issue with writing a uint32_t value to a file and reading it back. For writing it into a file, I use

uint32_t num = 2036465665 ; 
FILE *fp = fopen("test.dat", "w");
fprintf(fp,"value = %" PRIu32 "\n", num);
fclose(fp);

For reading it, I first copy the contents of file into an array data[] and then extract values line by line.

int len = 100;
char *line = malloc(len * sizeof(char));
char field[256], tmp[2];

FILE *fp = fopen("test.dat", "r");
while ( -1 != getline(&line, &len, fp)){
            char *value=malloc(sizeof(char)*256);
            sscanf( line, "%s %s %s", field, tmp, value);
            data[i] = value;
            i++;
        }
 fclose(fp);

To read the value of uint32_t variable, I get different values with atoi and strtoul with different bases, but not the exact value written into the file.

uint32_t read_num;
read_num = strtoul (data[0], NULL, 32);

This gives value of read_num as 1345324165.

read_num = (uint32_t) atoi(data[0]);

gives 3226523632

How do I get the correct value saved in the file. Is the error in (i) reading the file contents using sscanf into string or (ii) the strtoul vs atoi (iii) base in strtoul() .

I adapted your code fragments into this close-to-MCVE ( Minimum, Complete, Verifiable Example ), and it seems to work correctly on my Mac running macOS Sierra 10.12.4 using GCC 6.3.0 as the compiler. (I also get the same results with clang — Apple LLVM version 8.1.0 (clang-802.0.41).)

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

static void write_data(const char *filename)
{
    uint32_t num = 2036465665; 
    FILE *fp = fopen(filename, "w");
    assert(fp != NULL);
    fprintf(fp,"value = %" PRIu32 "\n", num);
    printf("Wrote %" PRIu32 "\n", num);
    fclose(fp);
}

int main(void)
{
    const char filename[] = "test.dat";

    write_data(filename);

    char *data[10];
    size_t len = 100;
    char *line = malloc(len * sizeof(char));
    assert(line != 0);
    char field[256], tmp[2];

    FILE *fp = fopen(filename, "r");
    assert(fp != NULL);
    int i = 0;
    while ( -1 != getline(&line, &len, fp))
    {
        printf("Read: [%s]\n", line);
        char *value = malloc(sizeof(char)*256);
        assert(value != 0);
        if (sscanf(line, "%s %1s %s", field, tmp, value) != 3)
            assert(0);
        printf("Field [%s] tmp [%s] value [%s]\n", field, tmp, value);
        data[i] = value;
        i++;
    }
    free(line);
    fclose(fp);

    char *endptr;
    errno = 0;
    printf("Processing [%s]\n", data[0]);
    uint32_t read_num = strtoul(data[0], &endptr, 10);
    assert(endptr != data[0]);
    free(data[0]);

    printf("Number read: %" PRIu32 "\n", read_num);
    return 0;
}

The use of assert for error handling is lazy in the extreme, but better than no checking. The error checking after strtoul() is also sloppy — there are unchecked conditions ( read_num == ULONG_MAX and errno == ERANGE , etc.)

When compiled and run, I get:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
>     -Wstrict-prototypes -Wold-style-definition rd53.c -o rd53
$ ./rd53
Wrote 2036465665
Read: [value = 2036465665
]
Field [value] tmp [=] value [2036465665]
Processing [2036465665]
Number read: 2036465665
$

If the use of size_t len vs int len is not your problem, maybe you can try this code and see what it gives you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM