[C++] Problem ze stringami


(Testsnifera) #1

Program ma odczytywać podaną ilość łańcuchów znaków i zapisywać je, aż do wprowadzenia łańcucha pustego. Wszystko się kompiluje jednak gdy wprowadzę dane n łańcuchów to program się "wykrzacza" , a gdy wcześniej próbuje wprowadzić łańcuch pusty to nie reaguje na enter.. Gdzie zawaliłem sprawę?

#include 

#include 

#include 


using namespace std;






int main(int argc, char *argv[])

{   


    int n,j=0;

    string lancuch;



    cout<<"Podaj ile chcesz wczytac lancuchow znakow \nMusi to byc liczba od 1 do 40: "<
    cin>>n;

    cout<

    cout<<"Lancuch nie moze miec wiecej niz 40 znakow\nGdy bedziesz chcial zakonczyc, wprowadz pusty lancuch: "<
    cout<








  string *p= new string[n];



   do {


          cout<<"Wprowadz "<
          getline( cin, lancuch );

          cin>>lancuch;

          j++;

          p[j]=lancuch;

    } while (j

    cout<

    

    delete[] p;




    system("PAUSE");

    return EXIT_SUCCESS;

}

(Lena(R)) #2

po pierwsze, skąd masz funkcję "getline"? U mnie środowisko jej w ogóle nie widzi:/

Kolejne "cin>>zmienna_typu_string", hmmm... z tego co mi wiadomo, to obiekt cin nie może być wywołany z obiektem typu string, tylko na rzecz jakiegoś łańcucha znaków (czyli char *). Analogicznie cout nie jest przeciążony do pracy z typem string, musisz wywołać funkcję "c_str()" na rzecz obiektu string który chcesz wypisać. Ona zamienia właśnie string na char * i wtedy powinno być dobrze. W drugą stronę chyba tak to nie zadziała.

Skoro to co Ty napisałeś u mnie nie działa (z powodu powyższych "usterek") mogę zaimprowizować. Po pierwsze w pętli do-while robisz najpierw j++, a potem dopisujesz do tablicy p zmienna. A więc ostatni, n-ty łańcuch wpisujesz w p[n], a to jest już poza obszarem tablicy i stąd wywalenie się programu. Dlatego te linijki

j++;

p[j]=lancuch;

powinny być zamienione miejscami i byłoby w porządku.

Problem nie wczytywania entera CHYBA polega na tym, że enter w konsoli nie działa jako pobranie pustego stringa tylko przejście do nowej linii w konsoli, a program i tak cały czas będzie czekał na wprowadzenie stringa (w sensie że w konsoli się kursor przesunie, a program to i tak oleje i nie ruszy się z miejsca). Być może ta funkcja "getline" działa jakoś magiczniej, ale u mnie system jej w ogóle nie widzi (mimo że dołączyłem te same headery co Ty), więc nie mogę tego przetestować i potwierdzić. Ale generalnie pusty string może być ciężki do pobrania, lepiej jakiś inny znak, np. pojedyncza kropka i wtedy w warunku porównać czy łańcuch jest długości 1 i czy na zerowym elemencie jest kropka.


(Testsnifera) #3

Miałaś racje z zamianą linijek, już się nie wykrzacza, jednak niestety przerwanie musi inicjować łańcuch pusty (takie polecenie) a ciągle przechodzi tylko do kolejnej linii gdy tylko go wprowadze. W przykładzie na cplusplus.com analogczne rozwiązanie działa, więc w czym tkwi problem... : Poniżej kod z podanej strony:

// string::empty

#include 

#include 

using namespace std;


int main ()

{

  string content;

  string line;

  cout << "Please introduce a text. Enter an empty line to finish:\n";

  do {

    getline(cin,line);

    content += line + '\n';

  } while (!line.empty());

  cout << "The text you introduced was:\n" << content;

  return 0;

}

(B.Andy) #4

No właśnie - podałeś przykład, który się różni od Twojego:

w przykładzie:

getline(cin,line);

u Ciebie:

getline( cin, lancuch );

cin>>lancuch;

Jeśli używsz getline, to już nie cin (a tak w ogóle @Lena® C++ getline). Tak więc usuń niepotrzebną linijkę cin>>lancuch;Dodatkowo przed pętlą musisz dodać

cin.ignore();

Bez tego nie będzie dobrze działać.

Nawiasem mówiąc: nie używaj system("PAUSE"); taki kod zadziała tylko pod Windowsem


(Lena(R)) #5

z getline już znalazłem dlaczego u mnie nie działa. Jednak dodałem nie tego headera co trzeba ale już wszystko jest na swoim miejscu.

I teraz po krótkim teście potwierdzam, jak 'getline' to nie 'cin >>', bo getline pobiera "dosłownie" to co podasz mu na konsoli, a cin nie. A Ty tutaj najpierw do 'lancuch' pobierasz dosłowny tekst, a potem zamazujesz go tym z cin. No i nie zapomnij o cin.ignore() przed pobieraniem łańcuchów.