Имейте в виду, что в C строки - это просто непрерывные наборы символов в памяти, начиная с известного адреса (char*
или char[]
, если хотите) и заканчивая нулевым байтом \0
C строки делаютне по своей сути знать их размер; вы программист несет ответственность за то, чтобы вы не пытались получить доступ к памяти за пределами того, что было выделено вашей строке. Когда вы это сделаете, вы получите Segfault.
scanf("%s",&word[0]);
Вы говорите scanf
прочитать строку из стандартного ввода и сохранить ее в word
(&word[0]
это просто word
). Но вы не указываете scanf
, сколько символов нужно прочитать максимально, поэтому вы не препятствуете scanf
получить доступ к world[20]
, что на один символ слишком далеко в 10-символьной строке (C - это смещение, основанное на 0, конечно,поэтому первый действительный символ в world
- это world[0]
, а последний - world[19]
.). Введите более 19 символов (оставляя еще один для завершающего \0
), и вы переполните свое выделение памяти, и все может произойти (если ваша программа имеет действительные данные по этому адресу памяти, вы перезапишете ее. Если данные есть)это указатель, вы перезапишете адрес и перестанете использовать segfault при следующей попытке разыменования. Если память вашей программы на этом заканчивается, вы напрямую перестанете работать с segfault.
Итак, вам нужно сказать scanf
максимальное количество байтов для чтения. Самый простой способ - с помощью необязательного «спецификатора ширины поля» для scanf:
scanf("%9s",word)
, который говорит scanf
прочитать строку и сохранить ее в слове, но толькохранить до 9 символов (10-й - это завершающий \0
символ).
Если я добавлю слово длиной 20+, моя программа должна игнорировать и продолжить
В вашей логике есть изъян - вы не знаете, будет ли слово длиной 10 символов, пока вы не прочитаете все это из ввода и , затем символrs от word
до первого появления '\ 0'. Прежде чем вы сможете проверить с помощью strlen
и, необязательно, continue
, вы уже допустили ошибку, записав 11-й символ в word[10]
в scanf
. Помните, что только из word
он не может знать, сколько байтов выделено по этому адресу.
Код списка слов также должен быть исправлен.
char *wordList[] = {""};`
...
//add word to wordList by extending memory for one new word and assign each char to memory
Ну, wordList[]
это ровно одна char*
длина, и эта строка ""
, пустая строка, которую вы определили как единственное содержимое статически определенного списка неопределенной длины []
размер которого во время компиляции определяется как 1. Вместо этого вы должны просто определить свой статический список, как вы делаете для word
.
char* wordList[20];
Вам также необходимо знать текущий размер списка, такой же, как смещение следующего элемента списка. Вы уже справляетесь с этим;начиная с -1
и увеличивая до операции, немного неортодоксально, но это работает.
Теперь у вас на самом деле есть wordList[i]
для распределения до i >= 20
.
unsigned int wordListLen = 0;
...
if(wordListLen >= 20){
// list full!
break;
} else {
unsigned int wlen = strnlen(word,10)+1;
wordList[wordListLen] = malloc( wlen * sizeof(char) );
strncpy(wordList[wordListLen], word, 10);
wordListLen++;
...print...
}
Не забудьте выделить место для '\0'
при выделении копии word
!