dzejo napisał(a)
Nie morduj tematu , można wpisać scanf-em do string ale po przydzieleniu
odpowiedniego buf w string .
string a ;
a.resize(20);
scanf("%19s",a.c_str());
cout << a << endl ;
wiesz co, nie posadzalbym Cie dotad o taka zenade..
nigdy tego przenigdy *rwa nie rób. po to c_str zwraca cholerne CONST, bys tego sie lamac nie odwazyl. string nie daje zadnej gwarancji, ze to co ma w srodku, jest ciagle i uzywalne do zapisu. to, ze jak mu zrobisz resize i poprosisz o c_str - oczywiscie, znaczy sie ze c_str faktycznie musi zwrocic conajmniej char[21]. nie znaczy to jednak, ze string nie ma prawa np. w ciemno co kazdy c_str alokowac sobie nowej przestrzeni a poprzednia stara wywalac. przeciez to jego bufor i zwracany constem, nie do zmiany przez szarakow.. a i tez przeciez zrobiles mu resize na swiezym pustym stringu? skad wiesz, ze implementacja stringa nie jest zoptymalizowana i w takim konkretnym przypadku nie zapamietuje sobie "jedem pusty, chcieli resize" i nie trzyma nic fizycznie az do żądania tresci ktore sobie moze wprost wygenerowac tablice "size" razy 0x00 na biezaco?
oczywiste jest, ze string tego nie robi w ten sposob, bo komu by sie chcialo. ale pokazuje to ze jest cos takiego jak dokumentacja i zalozenia. to ze ten kod dzial u Ciebie na Twoim kompilatorze, nie znaczy ze jest poprawny. nie znaczy ze bedze dzialal na innym kompilatorze, ani nawet nie znaczy ze bedzie dzialac na tym samym kompilatorze za dwa lata na nowszej wersji.
string ma c_str i data jako const, poniewaz dopuszczone zostalo, aby implementacja trzymala sobie tresc w formie nieciaglej (np. lista kolejnych kawalkow zamiast jednej duzej tablicy -- pomysl o wstawianiu/kasowaniu czegos ze srodka dlugiego napisu..) i zeby sklecala to w formie ciaglej dopiero na wywolaniu c_str/data. jesli tak to implementer napisze, co by sie stalo wtedy, gdybys zrobil:
string zuo = "ala ma ";
zuo += "_____";
zuo += " kotkow";
scanf("%s", zuo.c_str() + 7);
cout << zuo << endl;
zuo[0]='u';
cout << zuo <<endl;
?
ano, moze zobaczylbys poprawny napis "ala ma wpitu kotkow" za pierwszym coutem, ale za drugim razem moze zobaczylbys "ula ma _____ kontow", poniewaz string wykrylby zmiane i zregenerowalby tekst na podstawie wewnetrznie trzymanych kawalkow, ktorych Ty nigdy przy normalnej pracy bys nie zauwazyl..
a czemu te kawalki by sie nie odswiezyly po scanf'ie? string nie ma mozliwosci wykrycia zmian w buforze po ruszeniu ich na chama przez c_str!! przeciez to zwraca char* na ktorym string nie ma absolutnie zadnej mozliwosci kontroli/feedbacku.. musialby za kazda operacja nastepujaca po c_str liczyc i sprawdzac sumykontrolne/hashe/etc.. to dopiero byloby ciezkie i czasozerne..
zreszta, kurde, na chlopski rozum, po jaka cholere bylo tworzyc osobna klase string do trzymania ciagow znakow?
a czemu nie wrzucili se te metody do vector i uzywac vector<char> skoro to wszystko by mialo byc tylko opakowaniem na tablice charow!
string i vector sie RÓŻNIĄ.
string moze być nieciagly i robic magie, moze, BA. prawie na pewno ma mechanizm copy-on-write *). vector jest ciagly i kopiuje zawsze z wartosciami.
dlatego c_str i data maja cholerne CONST, dlatego vector nigdzie w analogicznych nie ma const.
*) - kolejny przyklad: ciekawe czy Twoj kompilator ma copy-on-write w stringu.. sprobuj tego, albo sie domysl po prostu..:
string zuo = "ala ma _____ kotkow";
string druga = zuo;
string trzecia = zuo;
scanf("%s", zuo.c_str() + 7);
cout << zuo << endl;
cout << druga << endl;
cout << trzecia << endl;
jedynym sposobem na prawidlowe pobranie do stringa jakiegos tekstu przez scanf jest - dostarczenie scanfowi CIĄGLEGO bufora nad ktorym masz 100% kontrole i potem przepisanie jego zawartosci do stringa, w najtrywialniejszej postaci:
vector<char> bufor(100, '\0'); //zakladajac ze nikomu nigdy nie uda sie wpisac \x00
scanf("%s", &bufor.front()); //a tu przydaloby sie pomyslec o ograniczeniu dlugosci pola %s do 100..
string niezuo(bufor.begin(), find(bufor.begin(), bufor.end(), '\0')); //<-- gwozdz programu..