Используйте write () для записи char * в файл из пользовательского ввода - PullRequest
3 голосов
/ 19 февраля 2020

Я пытаюсь написать функцию, которая получает путь от стандартного ввода и сохраняет этот путь в файл. Несмотря на множество попыток, я потерял всякое чувство, как правильно это сделать. Может кто-нибудь показать мне, как это сделать правильно? Это мой код:

void char_to_file(const char *pathname, const char *dest)
{
        int fd_1;
        if (fd_1 = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666) == -1)
                custom_error_shout("OPEN FD_1");
        while (*(pathname) != '\0')
        {
                *(pathname++);
                if (write(fd_1, &pathname, 1) == -1)
                        custom_error_shout("WRITE TO FILE");
        }

        if (close(fd_1) == -1)
                custom_error_shout("CLOSE FD_1");
}

Файл будет создан, но в нем ничего не будет записано. Из этого не вышло никаких ошибок.

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Причина, по которой ничего не написано, состоит в том, что вы сбрасываете fd_1 на результат условного open(..) == -1, что, если открытие не завершится неудачно, означает, что результат будет 0 (STDIN_FILENO). Если open() завершится неудачно и вернет -1, то fd_1 будет равно 1 (STDOUT_FILENO). Таким образом, вы пытаетесь от write до stdin, если не произойдет сбой open().

Это связано с вашей неспособностью заключить в скобки свое назначение, например, if (fd_1 = open() == -1) - которое должно быть if ((fd_1 = open()) == -1). В противном случае == (реляционный оператор) имеет более высокий приоритет оператора , чем = (простое назначение), а результат open(..) == -1 присваивается fd_1.

Для устранения проблемы , вам нужно:

if ((fd_1 = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)

( примечание: ваш выбор mode из 0666 будет зависеть от системы umask и, скорее всего, приведет к фактическим разрешениям 0644. См. man 2 umask )

Ваша команда write должна передавать адрес первого символа, а не указатель на этот адрес, например,

    if (write(fd_1, pathname, 1) == -1)

Вы должны включить предупреждения компилятора. Например, -Wall -Wextra -pedantic для gcc / clang или /W3 для VS (для других компиляторов проверьте параметры). С включенными предупреждениями вы должны получить предупреждение о том, что вычисленное значение не используется с:

    *(pathname++);

Чтобы продвинуть указатель, просто используйте pathname++;. Разыменование результата не имеет смысла, если он не присваивается или используется иным образом.

Если у вас нет других проблем со строками в pathname или dest, и ваши макросы ошибок работают должным образом - тогда это должно исправить вашу проблему. (с примечанием использование fopen и таких операций с потоком файлов, как fputs(), имеет гораздо больше смысла).

Дайте мне знать, если у вас есть дополнительные вопросы.

1 голос
/ 19 февраля 2020

Вы уверены, что выбрали трудный способ сделать это. Как @tadman, предложенный в комментариях, попробуйте это вместо:

void char_to_file(const char *pathname, const char *dest)
{
    FILE *fp;
    fp = fopen(dest, "w");
    if (fp == NULL)
    {
        custom_error_shout("Something went wrong opening the file");
        return;
    }

    if (fputs(pathname, fp) == EOF)
        custom_error_shout("Something went wrong writing to the file");

    fclose(fp);
}
...