получает и помещает, чтобы получить и распечатать строку

Я пытаюсь получить и распечатать строку с помощью команд Get и Put, но получаю ошибку сегментации, когда использую их вместе. это код, который я пытаюсь заставить работать. [я набираю строку "prova", чтобы проверить это]

int main()
{
    char *s;
    gets(s);
    puts(s);
    return 0;
}

если я изменю "получает" на "scanf", я получаю ту же ошибку. если я поменяю "put" на "printf ("% s ", s)", я получу результат. если я объявляю char * s = "prova", а затем помещаю (s), я получаю результат.

я также пытался изменить char * s; с char s [], но я получаю ту же ошибку.

где я ошибаюсь в этом? ты очень много

Я знаю, что это плохо, просто потому, что я пишу упражнение из "C, как программировать, пятое издание" Deitel и Deitel


person user3757339    schedule 04.07.2014    source источник


Ответы (3)


У вас есть несколько проблем с этим фрагментом кода. Для начала gets устарели со времени стандарта C99, а в стандарте C11 он был удален. Причина в том, что он не очень безопасен, не имеет проверки границ и поэтому может писать за пределами памяти, которую вы ему передаете, что приводит к переполнению буфера.

Во-вторых, вы используете неинициализированную локальную переменную s. Значение неинициализированной переменной неопределенно и будет казаться случайным. Использование неинициализированной локальной переменной приводит к неопределенному поведению, что часто приводит к вылетает.

Другая проблема заключается в том, что вы инициализируете s, чтобы указать на буквальные строки. Строки литералов представляют собой постоянные (доступные только для чтения) массивы символов, и попытка записи в них снова приведет к неопределенному поведению.

person Some programmer dude    schedule 04.07.2014

Вам нужно выделить место для строки:

char s[256];
gets(s);
puts(s);

Но gets плохо. (Он не знает, насколько велик ваш буфер, так что же произойдет, если будет прочитано более 255 символов?)

person James McLaughlin    schedule 04.07.2014
comment
я знаю, это просто для упражнений (моя книга просила об этом!) - person user3757339; 04.07.2014

Самая важная ошибка, которую вы совершаете, заключается в том, что вы объявляете указатель char, но не резервируете место в памяти, где будут храниться символы, поэтому вы получили указатель, указывающий на какой-то случайный адрес памяти, который вы не должны использовать. "Правильный" поступок будет:

#include <stdio.h>
#include <stdlib.h>

#define LENGHT 20
int main()
{
    char *s;
    s=malloc(sizeof(char)*LENGHT);  //here you make the pointer point to a memory adress that you can use
    gets(s);
    puts(s);
    free (s);
    return 0;
}

Но также настоятельно рекомендуется избегать использования get, потому что эта функция не проверяет длину ввода, поэтому вместо этого используйте fgets, которые позволяют вам это делать, вам нужно будет только установить поток данных на stdin. Код будет:

#include <stdio.h>
#include <stdlib.h>

#define LENGHT 20
int main()
{
    char *s;
    s=malloc(sizeof(char)*LENGHT);
    fgets(s,20,stdin);
    puts(s);
    free(s);
    return 0;
}
person sir psycho sexy    schedule 04.07.2014
comment
Почему malloc? Почему не просто char s[20];? В вашем коде явная утечка памяти, и вы ее пропустили, несмотря на то, что код состоит всего из пяти строк. Представьте себе реальную программу и насколько она будет катастрофической. - person Kerrek SB; 04.07.2014
comment
оба ответа верны, я решил сделать это с помощью malloc, потому что увидел, что OP объявляет указатель - person sir psycho sexy; 04.07.2014
comment
@KerrekSB Я мало что знаю об утечках памяти, но есть ли одна во втором коде? - person sir psycho sexy; 04.07.2014
comment
Использование malloc() - хороший масштабируемый подход. Страхование malloc() в паре с free() лучше. - person chux - Reinstate Monica; 04.07.2014