brak błędu? tablice znaków

0

Hej wszystkim

Mam do napisania banalny program, ale dopiero się uczę i C++ mnie cały czas zaskakuje. Zaczęłam od "podstaw podstaw", więc zadanie jest proste. Wczytać ciąg znaków, a potem wywalić go na ekran. Generalnie wszystko działa ładnie. Tylko, że chyba powinno się wywalać, nie? :P

 
#include <iostream>
using namespace std;

int main ()
{
	char znak;
	char ciag[1];
	char* c = ciag;

	while(true)
	{
		cout<<"podaj ciag\n";
		cin>>ciag;
		int dlu = strlen(ciag);
		cout<<"dlugosc "<<dlu<<"\n";
		cout<<"ciag "<<c<<"\n";
		cout<<"ciag[2] "<<ciag[2]<<endl;

	}
}

efekt jest taki, że przyjmuje mi ciąg dowolnej długości, zwraca jego długość bez błędu. w tabeli pod ciag[0] mam pierwszy znak w ciągu. Ale pozwala mi się też odwoływać do ciąg[1], ciag[2] itd bez zwracania błędu. A przecież deklarację mam na tablicę jednoelementową... Pasuje mi, że tak działa, pytanie tylko dlaczego. Podpowiecie?

0

Sprawa jest dość prosta. C++ nie sprawdza w żaden sposób czy nie wychodzisz poza zakres tablicy. Dla niego to jest po prostu jakieśtam miejsce w pamięci. Możesz za pomocą wskaźników czytać/pisać w zasadzie w dowolnym miejscu w pamięci (do którego masz dostęp). Dopóki odwołujesz się do pamięci która jest "twoja" to nic się nie dzieje. Jak wyjdziesz za daleko to poleci segfault.
Problem tylko w tym że pisząc w takim miejscu pamięci niszczysz dane które się tam znajdują! Jak wpiszesz do swojego ciągu więcej znaków to zwyczajnie zaczniesz zamazywać dane które są w pobliżu.
Przykład edukacyjny:

#include <iostream>
using namespace std;

int main()
{
    char znak2='B';
    char znak1='A';
    char tablica[1]={'x'};
    cout<< tablica[2]<< " " <<tablica[1]<< " "<< tablica[0] <<endl;
    return 0;
}

wypisze nam najczęściej A B c ponieważ przesuwając się w tablicy na stosie w przód idziemy tak na prawdę w górę stosu.

0

Dzięki za odpowiedź. Tak podejrzewałam. A możesz mi w takim razie podpowiedzieć jak zadeklarować tablicę tak, aby przyjmowała ciąg znaków dowolnej długości? Nie chcę deklarować tablicy np 1000-elementowej, bo jeśli ciąg będzie miał tylko 3 znaki, to jest to pamięciowo niewydajne. Zresztą docelowo będę wczytywać ciągi z plików, a wtedy nie wiadomo czy powinno to być 1000, czy 100000 elementów.

0

Skoro jesteś początkujący to najlepiej od razu nauczyć się nowoczesnych rozwiązań, poczytaj o typach string (służy do przechowywania łańcuchów znaków), oraz vector (to taka tablica "na dopingu", sama dopasuje się do ilości zawartych w niej elementów, ma też przydatne mechanizmy np usuwanie wybranego elementu).

0

Jeżeli nie znasz wcześniej ilości elementów to się nie da(chyba, że sam napiszesz taki mechanizm). Użyj std::string

0

Dzięki piękne. O wektorach czytałam, ale kompletnie mi z głowy wyleciało. Pokombinuję tak jak mówicie.

Miłego wieczoru!

1 użytkowników online, w tym zalogowanych: 0, gości: 1