Mistä johtuu, että Visual C++ 5.0 Professional heittää virheilmoituksen String-luokkaa käytettäessä?
Koodikin on otettu C++ -kirjasta, joten siinäkään ei pitäisi olla vikaa. Sama koodi toimii hyvin Visual C++ 6.0 Standardilla ja ainakin Borlandin C++Builder 4:llä.
Eikö Vc++ 5.0 vain tue String-luokkia vai onko asetuksissa vikaa?
Koodi on tällainen:
#include <iostream> #include <string.h> using namespace std; int main() { string teksti = "Matti oli oli \"oli oli\" oli oli ihminen."; string sana = "oli"; cout << endl << "Merkkijono on: " << endl << teksti << endl; int lkm = 0; for(int indeksi = 0; (indeksi = teksti.find(sana, indeksi)) != string::npos ; indeksi += sana.length(), lkm++) ; cout << "Tekstissä oli: " << lkm << " kertaa sana " << sana << "\"." << endl; return 0; }
Siinä tuli tällaisia virheitä:
E:\Omat tiedostot\Visual C++\mh.cpp(13) :
error C2679: binary '<<' : no operator defined which takes a right-hand operand of type
'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >'
(or there is no acceptable conversion)
E:\Omat tiedostot\Visual C++\mh.cpp(20) :
error C2679: binary '<<' : no operator defined which takes a right-hand operand of type
'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >'
(or there is no acceptable conversion)
Error executing cl.exe.
Text1.exe - 2 error(s), 0 warning(s)
Kokeilin VC++7.1:llä, ja myöskään se ei tuota käännä. Ongelma on se, että cout ei osaa käsitellä string-tyyppistä oliota. Tästä selvitään kuitenkin niinkin helposti kuin että luodaan osoitin siihen, missä itse tekstiosa string-oliosta sijaitsee. Ainakin itselläni toimii tällainen:
#include <iostream> #include <string.h> using namespace std; // Tällä makrolla muutetaan string-olio char-osoittimeksi #define StrToChar(Str) ((char *)((unsigned long)(&Str) + 4)) int main() { // Luodaan string-muuttuja string Teksti = "Tama on koeteksti"; // Tulostetaan se makron avulla. cout << StrToChar(Teksti); return 0; }
Hmm, kumpikohan on nopeampi:
cout << ((char *)((unsigned long)(&foobar) + 4)); cout << foobar.c_str();
Veikkaisin jälkimmäistä, kun se on etukäteen optimoitu STL:n osa ja niin pois päin.
Edit: voisin tietenkin avata tuon makron.
Väitän, että niillä ei ole juurikaan eroa, koska minun tapanihan ei varsinaisesti tee muuta kuin lisää neljä olion osoitteeseen. Nuo tyyppimuunnoksethan ovat täysin kääntäjän iloksi; niillä vain varmistetaan, että käyttäjä tietää mitä tekee. Todellisuudessahan prosessori ei mitään muuta, vaan samat bitit ne ovat kuitenkin.
Varmasti on sinänsä helpompaa käyttää jälkimmäistä, mutta itse en ole ikinä string-oliota käyttänyt, enkä tule käyttämäänkään, joten en noita funktioita tunne.
Metabolix kirjoitti:
Nuo tyyppimuunnoksethan ovat täysin kääntäjän iloksi; niillä vain varmistetaan, että käyttäjä tietää mitä tekee. Todellisuudessahan prosessori ei mitään muuta, vaan samat bitit ne ovat kuitenkin.
Äsh, enhän minä tuota tajunnut/muistanut.
lainaus:
Varmasti on sinänsä helpompaa käyttää jälkimmäistä, mutta itse en ole ikinä string-oliota käyttänyt, enkä tule käyttämäänkään, joten en noita funktioita tunne.
Mielenkiinnosta: mikset?
Tein nopeustestin, 100000000 kertaa molemmat:
Omani: 280 ms
Vanha: 9570 ms
Miksi en käytä stringiä? (1) Ei ole juurikaan tarvinnut tekstiä käsitellä ja (2) olen huomattavan paljon iloisempi, kun tiedän tarkalleen, mitä ohjelmani tekee :) ja (3) tuo string on liian erilainen kuin Pascalin string. Sitä paitsi, osaan itsekin tehdä vastaavia systeemejä niin char-taulukolla kuin muutenkin, eivätkä ne ole ainakaan merkittävästi hitaampia kun niitä ohjelmassa käytetään vain hyvin satunnaisesti. Vielä kun minussa on sen verran Assembly-ohjelmoijan vikaa, että vaikken Assyä käytä (yleensä), teen silti kaiken mahdollisimman kompaktisti. Joidenkin mielestä on ihme, että tietyt ohjelmani eivät ole kaatuilevia ja bugisia kun niissä käytetään mitä oudoimpia viritelmiä.
Huhhuh, tuollaisia ihmeneuvoja ei kyllä aloittelijoille kannattaisi antaa. Eli siis: älä koskaan käytä edellämainittua makroa, kun haluat const char -osoittimen string-olion dataan. Ei ole mitään varmuutta, että se antaa oikeita tuloksia. Nopeuttakaan ei tuollaisessa operaatiossa tarvita.
Miten niin, "ei ole mitään varmuutta"? Hyvinhän tuo toimii. Sen kyllä myönnän, että aloittelija voi olla vähän pihalla.
Metabolix: itselläni tuo ei toiminut ei MSVC++ 6:ssa eikä Dev-C++:ssa (Mingw). Millä perusteella päättelit, että merkkijono löytyy aina tuosta samasta paikasta jokaisessa STL:n implementaatiossa?
Niin, luonnollisesti tuo pitää string.h -tiedoston eri versioille usein muuttaa. Kyllähän joillakin iostream-versioilla voi tulostaa string-muuttujan ilman mitään muutoksia cout << Oma_string;
En ole missään väittänyt merkkijonon löytyvän aina samasta paikasta. Kukin voi tehdä makrosta omalle kääntäjälleen sopivan version mikäli haluaa sitä käyttää. Tuohon sijaintiin pääsin lauseella "cout << (char *)&OmaString;
", josta näin ylimääräisten tavujen määrän.
Eri kääntäjille siirtäminen on täysin käyttäjäkohtaista. Itseltäni ei tule muille kääntäjille mitään muuta koodia, kuin se, minkä Putkaan laitan, ja sitä ei yleensä ole paljoa. Omat ohjelmani tulen varmasti aina kääntämään VC++:lla kunnes jokin uudempi ja parempi ohjelma ilmestyy ja VC++ ei enää kelpaa.
PS. Voin toki olla väärässä, mutta jotenkin noista kommenteistasi kuvastuu erittäin ikävä asenne.
Tämä tappelu alkaa nyt olla vähän turhaa. Aloittelijoille ei vain pitäisi antaa sellaista kuvaa että tuollaisten "hackien" käyttö olisi jotenkin suositeltavaa tai hyväksyttävä tapa kun tarjolla on standardinmukainen vaihtoehto. Jos joku koodivinkki syyttä tuollaisia kikkoja käyttää niin minä lupaan kyllä teilata sen :)
Pahoittelen jos joistain kommenteistani on tullut sinulle paha mieli. Ja tätä en siis tarkoita pahalla :)
En tiedä vaikuttaako itse ongelmaan, mutta yleisestikin lienee parempi sisällyttää <string> eikä <string.h> aivan yhtälailla, kun <iostream> <iostream.h>:n tilalta. Sitäpaitsi, eikös tuo <string.h> ole C-kielen standardi merkkijonojen käsittelykirjasto (strlen, strcpy, ...)?
En usko että vaikuttaa ongelmaan mutta totta pöriset, tn.
Aihe on jo aika vanha, joten et voi enää vastata siihen.