2017-04-14 129 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

現在你需要整合一些什麼沒有用到的東西。你正在使用版本控制系統,不是嗎? –