Ошибка сегментации при попытке получить строку из ввода - PullRequest
0 голосов
/ 12 марта 2020
#include <iostream>

using namespace std;

int main() {
  char *s;

  printf("enter a word \n");

  scanf("%s", s);

  int i;

  for (i = 0; s[i] != '\0'; i++) {
  }

  printf("length is = %d", i);

  return 0;
}

Когда я компилирую эту программу, возникает ошибка сегментации.

Может кто-нибудь сказать мне плз, в чем проблема в этом коде?

Ответы [ 3 ]

2 голосов
/ 12 марта 2020
char *s;

Унифицирован, вы не можете назначить ему входной поток, пока он не будет.

char s[100]; //space for 99 characters plus null terminator

или

char* s = malloc(100); //each char has the size of one byte

Это инструменты C, для В C ++, однако, вы можете / должны использовать std::string, с std::cin вместо scanf.

std::string s;
std::cin >> s;

Если вам необходимо использовать C tools, scanf("%s", s); не самый безопасный метод , если вы не передадите размер контейнера char array, лучше указать спецификатор %s на %100s или изменить его на более безопасную функцию, например fgets(s, sizeof(s), stdin);.

1 голос
/ 12 марта 2020
char *s;

printf("enter a word \n");

scanf("%s",s);

scanf с %s не выделяет память, вместо этого он считывает данные в буфер, который вы предоставляете (например, s = malloc(100);. Насколько большим должен быть этот буфер, чтобы избежать Переполнение буфера? К сожалению, это может быть слишком долго до символа пробела, поэтому это небезопасно по своей природе.

Вы можете указать максимальный фронт (не включая нулевой терминатор!), но для обработки переменного размера вам необходимо динамически построить строку формата, которая становится сложной. Как и то, что делать, если пользователь вводит строку слишком долго.

char s[100];
scanf("%99s", s);

Поскольку вы пометили C ++, вы можете использовать std::string и потоки ввода-вывода (например, std::cin для консольного ввода), который будет обрабатывать все выделение памяти для вас.

std::string s;
std::cout << "enter a word" << std::endl;
std::cin >> s;

В случае C, вы можете использовать fgets(str, num, stream), это позволяет вам указать максимальную длину и избежать переполнения в простой способ.

char s[128];
fgetsf(s, 100, stdin);

Или с POSIX 2008 scanf он может выделить память , но я не верю, что это универсально поддерживается, например, Microsoft Visual Studio.

char *s = 0;
scanf("%ms", &s); // pass a pointer to a pointer!
free(s); // needs to be freed later!
1 голос
/ 12 марта 2020
char *s;

Вы создали указатель, хотя он ни на что не указывает (он не инициализирован).

scanf("%s",s);

Вы пытаетесь прочитать данные в строку, на которую указывает s, но таких вещей не существует.

?!

Выделите часть памяти и укажите s на нее ... или, что еще лучше, используйте std::string и std::cin.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...