ďťż

Ładny brzuch

Dlaczego poniższy przykład się komiluje, ale wyskakuje błąd(w Dev i Visual) podczas pracy programu? Jest to przykład z książki "Język C++" Wiesława Porębskiego:
#include <iostream.h> main() { char *start = "ABCD"; char *cel = "EFGH"; int i = 0; while((cel[i] = start[i]) != '\0') i++; cout << "Lancuch to: " << cel << endl; return 0; }

Prosze o pomoc :)
Użytkownik comp123 edytował ten post 10 styczeń 2006, 23:46


#include <iostream> using namespace std; int main() { char *start = "ABCD"; char cel[5] = "EFGH"; int i = 0; cout << "Lancuch to: " << cel << endl; while((cel[i] = start[i]) != '\0') i++; cout << "Lancuch to: " << cel << endl; return 0; }

Spróbuj z tym kodem, powinno być oki. Swoją drogą, to ciekawe, że to przykład z książki. Błąd bierze się stąd, ze tamten program chce pisać do pamięci, do której nie może pisać. Deklaracja cel jako tablicy char już pozwala na zapisywanie do niej.

a nie da się jakoś używając samych wskaźników?

Da się tak:
#include <iostream> using namespace std; int main() { char *start = "ABCD"; char* cel= new char[5]; strcpy(cel,"EFGH"); int i = 0; cout << "Lancuch to: " << cel << endl; while((cel[i] = start[i]) != '\0') i++; cout << "Lancuch to: " << cel << endl; return 0; }

Troszkę się to komplikuje, bo trzeba alokować pamięć operatorem new, a na dodatek nie można od razu inicjalizować takiego stringa (chyba, że się mylę, ale ja nie wiem jak zainicjalizować od razu taką tablicę). Dlatego dalej jest funkcja strcpy, żeby coś wpisać do takiej tablicy. Jak dalej widzisz nadal możesz się odwoływać przez operator [] mimo, że cel jest wskaźnikiem. I działa :P



a co jest źle w tym programie?:
#include <iostream> #include <cstring> using namespace std; class Lancuch { public: Lancuch(char *lancuch); Lancuch(unsigned wielkosc); ~Lancuch(); Lancuch(const Lancuch &rhs); unsigned WyswietlRozmiar() const; char *WyswietlLancuch() const; void UstawLancuch(const char *const lancuch); void DodajLancuch(const char *const lancuch); private: char *Napis; unsigned dlugosc; }; Lancuch::Lancuch(char *lancuch) { dlugosc = strlen(lancuch); Napis = new char[dlugosc+1]; strcpy(Napis, lancuch); Napis[dlugosc] = '\0'; } Lancuch::Lancuch(unsigned wielkosc) { dlugosc = wielkosc; Napis = new char[dlugosc+1]; for(int i = 0; i < dlugosc; i++) Napis[i] = '\0'; } Lancuch::~Lancuch() { delete [] Napis; } Lancuch::Lancuch(const Lancuch &rhs) { if(!rhs.Napis) return; dlugosc = rhs.WyswietlRozmiar(); Napis = new char[rhs.WyswietlRozmiar() + 1]; strcpy(Napis, rhs.Napis); } unsigned Lancuch::WyswietlRozmiar() const { return unsigned(strlen(Napis)); } char *Lancuch::WyswietlLancuch() const { if(!Napis) return false; return Napis; } void Lancuch::UstawLancuch(const char *const lancuch) { if(!lancuch) return; delete [] Napis; dlugosc = strlen(lancuch); Napis = new char[dlugosc+1]; strcpy(Napis, lancuch); Napis[dlugosc] = '\0'; } void Lancuch::DodajLancuch(const char *const lancuch) { int suma = int(strlen(Napis)); suma += int(strlen(lancuch)); char temp[suma+1]; strcpy(temp, Napis); int indexLan = 0; int indexTemp = strlen(Napis); while(lancuch) // wydaje mi sie ze tu jest cos zle { temp[indexTemp++] = lancuch[indexLan++]; } temp[suma] = '\0'; delete [] Napis; Napis = new char[suma+1]; strcpy(Napis, temp); Napis[suma] = '\0'; } int main() { Lancuch jakis("cos"); jakis.DodajLancuch(" tam"); cout << "Caly: " << jakis.WyswietlLancuch() << endl; system("pause"); return 0; }
chyba chodzi o funkcję DodajLancuch, więc proszę skupić się tylko na niej.
Użytkownik comp123 edytował ten post 11 styczeń 2006, 00:27
#include <iostream.h> int main(void) {    char *start = "ABCD";    char *cel = "EFGH";    int i = 0;    while((cel[i] = start[i]) != '\0') i++;    cout << "Lancuch to: " << cel << endl;    system ("pause");    return 0; }

Tylko się tak zastanawiam, po choelre ten while, skoro i tak 'i' nigdzie nie wyrzucasz. A co do klasy, to postaraj się opisać problem, co ci wyrzucił kompilator itd.. a nie "co jest źle". Przypomina mi to pewien rysunek:

http://www.altix.pl/...lamborghini.jpg
Użytkownik teS edytował ten post 11 styczeń 2006, 01:54
Tam gdzie tes poprawił błąd, to błędu nie było :D ,tak na marginesie.
W kwestii tej metody klasy, to w zanaczonym miejscu może być tak:
while(lancuch[indexLan]) // wydaje mi sie ze tu jest cos zle { temp[indexTemp] = lancuch[indexLan]; indexLan++; indexTemp++; }

To akurat działa, ale już jest za późno, żebym się zastanawiała dlaczego tak działa, a poprzednio nie działało... :unsure: Czasem tak po prostu jest.

Heh w sumie racja :P Tak nie popatrzyłem, za późno. Zedytuję co by w błąd nie wprowadzać.
Użytkownik teS edytował ten post 11 styczeń 2006, 01:53

Da się tak:
#include <iostream> using namespace std; int main() { char *start = "ABCD"; char* cel= new char[5]; strcpy(cel,"EFGH"); int i = 0; cout << "Lancuch to: " << cel << endl; while((cel[i] = start[i]) != '\0') i++; cout << "Lancuch to: " << cel << endl; return 0; }

Troszkę się to komplikuje, bo trzeba alokować pamięć operatorem new, a na dodatek nie można od razu inicjalizować takiego stringa (chyba, że się mylę, ale ja nie wiem jak zainicjalizować od razu taką tablicę). Dlatego dalej jest funkcja strcpy, żeby coś wpisać do takiej tablicy. Jak dalej widzisz nadal możesz się odwoływać przez operator [] mimo, że cel jest wskaźnikiem. I działa  :P

no więc w końcu da się to zrobić używając samych wskaźników czy nie? A co do przykładu z klasami to poprawiłem i działa.

char *start = "ABCD";
Ten zapis alokuje 5 bajtów pamięci, ale jest to pamięć tylko do odczytu. W C++ wprowadzono operator new do zajmowania pamięci (na stercie, heap) i delete do zwalniania. Taka pamięć może być zapisywana.
char* cel= new char[5];
Ten zapis przypisuje wskaźnikowi cel adres początku miejsca w pamięci, w którym można zapisać 5 bajtów. Przez konwersję typu wskaźnika można tam zapisać coś innego niż typ char. Niemniej jednak mamy wskaźnik na jakiś obszar pamięci z określonym typem char. Wtedy zapis *(cel+1) oznacza zawartość drugiego bajta w tej pamięci. W powyższym przykładzie można zapisać zamiast:
while((cel[i] = start[i]) != '\0') i++;
tak:
while((*(cel+i) = *(start+i)) != '\0') i++;
Efekt będzie ten sam, ale odwołanie przez wskaźnik. (Podobno aplikacje działają szybciej niż z operatorem [] ).
Pozostaje operator [] przy alokacji pamięci przez new, ale ja bym nie robił z tego problemu i tak to już zostawił.

Do chodnik: tak też nie działa, ten program też się zawiesza:
#include <iostream> using namespace std; main() { char *start = "ABCD"; char *cel = new char[5]; cel = "EFGH"; int i = 0; while((*(cel+i) = *(start+i)) != '\0') i++; cout << "Lancuch to: " << cel << endl; delete [] cel; system("pause"); return 0; }

comp123 kurda czytaj posty kolegow !.

co to ma w ogole byc ? - myslisz ty troszke ? :)

char *cel = new char[5]; cel = "EFGH";

Już działa:
#include <iostream> using namespace std; main() { char *start = "ABCD"; char *cel = new char[5]; strcpy(cel, "EFGH"); int i = 0; while((*(cel+i) = *(start+i)) != '\0') i++; cout << "Lancuch to: " << cel << endl; delete [] cel; system("pause"); return 0; }

ale wciąż się zastanawiam dlaczego w książce pisało, że ten jest poprawny:
#include <iostream.h> main() { char *start = "ABCD"; char *cel = "EFGH"; int i = 0; while((cel[i] = start[i]) != '\0') i++; cout << "Lancuch to: " << cel << endl; return 0; }
Użytkownik comp123 edytował ten post 11 styczeń 2006, 20:01
Bo to pewnie stara ksiazka z czasow dos-a. Tam nie bylo ochrony pamieci. Mozna bylo nadpisac co sie chcialo - najwyzej komputer robil zwieche ...
Użytkownik st3tc edytował ten post 11 styczeń 2006, 20:33
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •