2017-01-16 56 views
3

我试图写入使用write()功能(包含在<unistd.h>)的文件。该程序很简单:当运行可执行文件时,我键入一条消息,然后将消息和我的用户标识(Linux UID)保存到文件中。C和write()函数 - 文件正被写入十六进制和书面int值是不正确的

$ ./notetaker "Hello" 

我期待的是,下面的值可以保存到文件:

1000 
Hello 

有两个问题:

  • 我的文件正被写入十六进制(当我打开它用崇高的文字,我能看到的是十六进制值)
  • 插入代表我的用户ID的整数是不正确的

这是运行cat notes.txt当我得到的结果是:

� 
Hello 

当我打开notes.txt文件与崇高的文本,我可以阅读以下资料:

e803 0000 0a48 656c 6c6f 0a 

前4个字节不等于“1000”。

为什么我的文件被保存与十六进制值?为什么数字不正确?

这是我的源代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include <unistd.h> 

void write_uid(const int); 
void write_note(const int, void *); 

int main(int argc, char *argv[]) 
{ 
    char *buffer = (char *) malloc(100); 
    if(buffer == NULL) exit(0); 
    strcpy(buffer, argv[1]); 

    char *filename = (char *) malloc(50); 
    if(filename == NULL) exit(0); 
    strcpy(filename, "notes.txt"); 

    int file_descriptor = open(filename, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); 
    if(file_descriptor == -1) exit(0); 

    write_uid(file_descriptor); 
    write_note(file_descriptor, buffer); 

    if(close(file_descriptor) == -1) exit(0); 

    printf("Your note has been saved successfully. \n"); 
    free(buffer); 
    free(filename); 

    return 1; 
} 

void write_uid(const int file_descriptor) 
{ 
    int current_user_id = getuid(); 
    int uid_write_result_code = write(file_descriptor, &current_user_id, sizeof(current_user_id)); 
    int new_line_write_result_code = write(file_descriptor, "\n", 1); 

    if(uid_write_result_code < 0 || new_line_write_result_code < 0) 
     exit(0); 
} 

void write_note(const int file_descriptor, void *buffer) 
{ 
    int note_write_result_code = write(file_descriptor, buffer, strlen((char *) buffer)); 
    int new_line_write_result_code = write(file_descriptor, "\n", 1); 

    if(note_write_result_code < 0 || new_line_write_result_code < 0) 
     exit(0); 
} 

我使用一个Ubuntu 14.04忠实的塔尔羊(64),和我的版本的GCC 4.8.4是。另外,使用-Wall选项编译时,不显示警告。

+1

创建[mcve]。同时仔细检查你的标签。这个问题真的和C++有什么关系吗? – user2079303

+4

您的'write_uid'和'write_note'函数将数字写入文件中,而不是以10为基数的数字表示。您期望您可以在文件中找到字符串“1000”(基数为10的数字表示)是不合理的,因为你没有代码来编写十个数字表示的文件。对于任何程序员来说,最重要的事情莫过于一个数字(比如两个数字)和数字表示之间的差异(比如“two”是英文单词或“2”是十进制数字,代表第二)。 –

+0

@ user2079303对不起,我的坏。我按照“最小,完整和可验证”的要求编辑了代码。 @DavidSchwartz,谢谢!仔细阅读你的评论后,我可以看到我做错了什么。如你所说,数字本身(而不是它的表示)就在那里:'e8 03 00 00'。我试图按照原样转换数字,忘记了“小端”概念。当我转换'3e8'时,我可以看到数字。你真的帮助了我。 –

回答

7

你的数值的1000值是第一个4个字节:e8 03 00 00

英特尔CPU为小端的字节(不是半字节)必须重新排序在正常的从左到右的顺序读取它们,所以值变为00 00 03 e8。丢弃前导零将使您以十六进制形式出现3e8,这实际上是十进制的1000。

你这里的问题是,你正在写从current_user_id的字节数,这是一个32位整数,给您的文件字符一个字符在内存中的顺序。如果你想让它作为一个数字可读,你将不得不使用你选择的函数将它转换为字符串表示。阻力最小的路径可能是使用fprintf()而不是write()

1

你必须格式化结果或其他明智的它会在原始的二进制写入。使用fprintff ile printf ormatted)。或者,如果你对使用写操作感到愤怒,那么使用sprintf来格式化整数以获得该整数的等效字符串表示,然后保存该字符串。

char str[20]; 
sprintf(str, "%i\n", current_user_id); 
write(file_descriptor, str, strlen(str)); 
// no needto write \n, it's already included in str