2017-04-14 120 views
1

我在写一个uint32_t值到文件并读回来时遇到了问题。 为了写入到文件中,我使用在读取保存在文件中的uint32_t变量时出错

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

为了读取它,我第一文件中的内容复制到一个数组data[],然后通过线提取值线。

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); 

读取uint32_t的变量的值,我得到不同的价值观与atoistrtoul与不同的基础,但不是精确值写入文件。

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

这给read_num的价值为1345324165.

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

给人3226523632

我如何保存在文件中正确的值。 (i)是否使用sscanf将文件内容读入字符串或(ii)strtoul vs atoi(iii)基于strtoul()中的错误。

+1

strtoul(data [0],NULL,32); - 你的基数是32?我会查找如何正确使用此功能;基于我已经瞥了一眼应该是10,而不是32. – MateoConLechuga

+0

另外,我会建议使用EOF而不是-1作为getline的返回检查。 – MateoConLechuga

+2

@MateoConLechuga:实际上,在POSIX中定义了['getline()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html)来返回-1而不是'EOF',所以使用'-1'是正确的。 –

回答

0

我改编了你的代码片段到这个接近MCVE(Minimum, Complete, Verifiable Example),它似乎在运行macOS Sierra 10.12.4的Mac上正常工作,使用GCC 6.3.0作为编译器。 (我也得到相同的结果与clang - 苹果LLVM版本8.1.0(铛-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; 
} 

用于错误处理的使用assert是在极端的懒散,但总比没有好检查。错误strtoul()检查后也马虎 - 有未经检查的条件(read_num == ULONG_MAXerrno == ERANGE等)

编译和运行之后,我得到:

$ 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 
$ 

如果使用size_t len VS int len是不是你问题,也许你可以试试这段代码,看看它给了你什么。

+0

这对我来说也很好。非常感谢。但是,我还没有弄清楚为什么我的示例代码不起作用! – marc

+0

它是否与我在你的代码中使用NULL代替'​​endptr'? – marc

+0

现在你需要整合一些什么没有用到的东西。你正在使用版本控制系统,不是吗? –