Trafiłeś na dokładny problem z scanf() i% s - co się dzieje, gdy nie wiesz, ile masz danych wejściowych?
Jeśli spróbujesz uruchomić char mystring[0];
, Twój program skompiluje się dobrze. Ale zawsze będziesz segfault. Tworzysz tablicę o rozmiarze 0, więc gdy spróbujesz umieścić w tej tablicy coś, co stanie się, natychmiast wyjdziesz poza granice łańcucha znaków (ponieważ nie zostanie przydzielona żadna pamięć) - czyli jest to błąd segfault.
Zatem punkt 1: należy zawsze przydzielać rozmiar do napisu. Mogę myśleć o bardzo niewielu okolicznościach (w porządku, nie ma), gdzie chciałbyś powiedzieć char mystring[0]
zamiast char *mystring
.
Następnie, gdy używasz scanf, nigdy nie będziesz chciał używać specyfikatora "% s" - ponieważ nie będzie to miało wpływu na wielkość łańcucha znaków. więc nawet jeśli masz:
char mystring[512];
scanf("%s", mystring);
jeśli użytkownik wprowadzi więcej niż 511 znaków (od 512th jest \ 0), można wyjść z granic swojej tablicy.Sposobem na zaradzenie to:
scanf("%511s", mystring);
To wszystko znaczy, że C nie posiada placówki, aby automatycznie dopasowuje ciąg, jeśli istnieje więcej niż wejście czekasz. To jest coś, co musisz zrobić ręcznie.
Jednym ze sposobów rozwiązania tego problemu jest użycie numeru fgets().
można powiedzieć:
while (fgets(mystring, 512, stdin))
{
/* process input */
}
Następnie można użyć sscanf(), aby analizować mystring
Spróbuj powyższy kod, z ciągiem długości 5. Po 4 znaków, które zostały przeczytane, że kod pętle ponownie, aby pobrać resztę danych wejściowych. "Przetwarzanie" może zawierać kod, aby ponownie przydzielić ciąg o większym rozmiarze, a następnie dołączyć najnowsze dane wejściowe z fgets().
Powyższy kod nie jest doskonały - spowodowałby, że twój program zapętliłby się i przetworzył dowolną nieskończoną długość łańcucha, więc możesz chcieć mieć wewnętrzny twardy limit (np. Pętla maksymalnie 10 razy).
t należy dodać, że% s czyta słowa, a nie całe ciągi. Ponieważ ciąg formatu scanf używa spacji i znaków nowej linii jako ograniczników.W tym przypadku użyj% c zamiast tego (z szerokością pola) lub fgets, jak wspomniałeś. W przypadku% c z szerokością pola pamiętaj, aby zainicjować cały łańcuch bufora na zero. –
Program nie zawsze ulega uszkodzeniu. W rzeczywistości, prawdopodobnie nie przez większość czasu. Twój program prawdopodobnie zostanie po cichu zepsuty. Czy C nie jest piękny? :-) –