2017-01-16 12 views
3

Я пытаюсь записать в файл с помощью функции write() (входит в состав <unistd.h>). Программа проста: при запуске исполняемого файла я печатаю сообщение, а затем сообщение и идентификатор пользователя (Linux UID) сохраняются в файле.Функция C и write() - файл записывается в шестнадцатеричном виде, а записанное значение int неверно

$ ./notetaker "Hello" 

Я ожидал, что следующее значение может быть сохранено в файл:

1000 
Hello 

Есть две проблемы:

  • мой файл записывается в шестнадцатеричном виде (при открытии он использует Sublime Text, все, что я могу видеть, - это шестнадцатеричные значения)
  • целое число, введенное, представляющее мой идентификатор пользователя, неверно

Это результат, который я получаю при запуске cat notes.txt:

� 
Hello 

Когда я открываю notes.txt файл с Sublime Text, я могу прочитать следующие данные:

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 Trusty тар (x64), и мой GCC версии 4.8.4. Кроме того, при компиляции с использованием опции -Wall не отображается предупреждение.

+1

Создать [mcve]. Также дважды проверьте свои теги. Этот вопрос действительно имеет отношение к C++? – user2079303

+4

Функции 'write_uid' и' write_note' записывают числа в файл, а не представления чисел в базе 10. Ваше ожидание, что вы найдете строку «1000» в файле (представление числа одна тысяча в базовой десятке) является необоснованным, так как у вас нет кода для записи десяти базовых чисел в файл. Вполне возможно, что самое важное для любого программиста - это разница между числом (например, двумя, количеством рук у меня) и представлениями чисел (например, «два», английское слово или «2» десятичная цифра, которые представляют собой номер два). –

+0

@ user2079303 Извините, мой плохой. В любом случае я отредактировал код, выполнив требование «Минимальное, полное и проверяемое». @DavidSchwartz, спасибо! После прочтения вашего комментария внимательно, я мог видеть, что я делаю неправильно. Как вы сказали, сам номер (а не его представление): 'e8 03 00 00'. Я пытался преобразовать число, как оно есть, забывая о концепции «мало-конца». Когда я преобразовал '3e8', я мог видеть номер. Ты действительно помог мне. –

ответ

7

Ваше числовое значение 1000 - это первые 4 байта: e8 03 00 00.

процессоров Intel является прямой порядок байтов, то байт (а не nybbles) должны быть перераспределены, чтобы читать их в нормальном левом правильном порядке, поэтому значение становится 00 00 03 e8. Отбрасывание ведущих нулей оставляет вас 3e8 в шестнадцатеричном формате, который, действительно, 1000 в десятичной системе.

Ваша проблема заключается в том, что вы записываете байты из current_user_id, который представляет собой 32-разрядное целое число, в ваш файл по-символу в порядке памяти. Если вы хотите, чтобы он был доступен для чтения в виде числа, вам придется преобразовать его в строковое представление, используя функцию по вашему выбору. Путь наименьшего сопротивления, вероятно, должен использовать fprintf(), а не write().

1

Вы должны отформатировать результат или другое мудрый, он будет записан в необработанном двоичном формате. Использовать fprintf (f ile печатьf 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