Эта программа принимает вводимые пользователем данные и сохраняется в массиве символов. Затем создает файл и помещает эти тексты в новый файл. Проблема в том, что он может скопировать только часть перед пробелом. Текущий вывод: «как читать» -> «как»

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

int main(int argv, char *argc[]){
    int fd;
    char buffer[100];

    printf("Type your text : ");
    scanf("%s",&buffer);

    fd=open("menew.txt",O_CREAT|O_WRONLY|O_EXCL,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
    if(fd<0){
        printf("file already exist!\n");
        }else printf("file created!\n");

    fd=write(fd,buffer,20);
    if(fd<0){
        printf("error on writing...\n");
        }else printf("successfully written!\n");

    close(fd);
    return 0;
}
0
Devyn 6 Янв 2010 в 19:49
2
Подсказка: что происходит, когда пользователь вводит более 100 символов?
 – 
Nikolai Fetissov
6 Янв 2010 в 19:57
Думаю, персонажей больше 100 не спасут. Он не появится. Я прав? Это как-то связано с моей проблемой?
 – 
Devyn
6 Янв 2010 в 20:29
Нет - если пользователь вводит более 100 символов, символы будут считаны, перезаписывая все, что находится в памяти рядом с выделенным вами buffer. Т.е. это «переполнение буфера», которое, как известно, используется почти всеми червями, троянскими конями, вирусами и т. д.
 – 
Jerry Coffin
6 Янв 2010 в 20:59

3 ответа

Лучший ответ

Наконец-то я нашел решение !!! Используйте gets(buffer); момент scanf("%s",&buffer);

0
Devyn 6 Янв 2010 в 20:43
3
Никогда не используйте gets. Вместо этого используйте fgets. gets не проверяет переполнение буфера, поэтому его нельзя безопасно использовать в этом случае.
 – 
Alok Singhal
6 Янв 2010 в 22:59

Проблема не в записи, а в чтении - преобразование scanf %s пропускает любые начальные пробелы, затем считывает и преобразует до следующего пробела (но не включая его).

Возможно, вы захотите использовать что-то вроде fgets или преобразования %[^\n] с scanf.

Изменить: я, вероятно, также должен упомянуть, что когда / если вы используете преобразование набора разверток (%[^\n]), вы должны указать длину буфера, в который вы читаете.

Поскольку &buffer в scanf("%s", &buffer); является ошибкой, технически он дает неопределенное поведение, но на самом деле я не знаю ни одной реализации, в которой это имеет реальное значение.

В этом случае buffer был определен как массив, а не указатель. Имя массива "распадается" на указатель во многих случаях, но нет при использовании в качестве операнда оператора адресации (унарный &). Таким образом, buffer и &buffer дают точно такой же результат - адрес начала массива.

Однако разница все же есть. Когда вы используете только buffer, вы получаете значение с типом pointer to char (при условии, что этот буфер является массивом символов). Когда вы используете &buffer, вы получаете указатель типа pointer to array of MAXLEN char.

Теперь, когда вы передаете значение в scanf (вариативная функция), вы получаете неопределенное поведение, когда / если тип передаваемого вами значения не соответствует типу, ожидаемому от указанного вами преобразования. На самом деле, с каждым компилятором C, о котором я когда-либо слышал, он будет работать нормально, потому что в любом случае будет передан один и тот же адрес. Теоретически (но только теоретически, AFAIK) компилятор может использовать какой-то «жирный указатель», который включает информацию о типе вместе с адресом, так что scanf сможет определить тип несоответствие. На самом деле я не знаю ни одного компилятора, который бы делал что-то очень похожее, поэтому вы не увидите никакой разницы между использованием только buffer и использованием &buffer в этом случае.

Однако в других обстоятельствах разницу можно обнаружить. Сложение и вычитание указателей зависит от типа, поэтому (например) array+1 и &array + 1 дадут разные результаты:

#include <stdio.h>

int main() { 
    char array[10];

    printf("%p %p %p\n", array, array+1, &array+1);
    return 0;
}

Это напечатает три числа. Первое число будет произвольным числом, обычно в шестнадцатеричном формате. Второй будет на единицу больше первого, а второй будет на 10 больше первого (потому что я определил его как массив из 10 символов ...)

5
Jerry Coffin 6 Янв 2010 в 20:26
Спасибо за Вашу информацию. Я буду помнить о них. Что касается моей проблемы, я обнаружил, что (буфер) решен.
 – 
Devyn
6 Янв 2010 в 20:42

Хотя бы одна ошибка:

scanf("%s",&buffer);

Должно быть:

scanf("%s", buffer);

Вы брали адрес указателя. Наверное, не то, что ты задумал.

Редактировать:

scanf также имеет ограничение, описанное Джерри Коффином.

0
luke 6 Янв 2010 в 19:57