Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Sisältääkö joku merkkijono jtn.. c++

Sivun loppuun

Aloittelija3 [14.08.2007 19:44:13]

#

No hej.. miten/millä funktiolla saan tarkistettua sisältääkö joku lause vaik sanan "ohjelmointi" (kirjainkoolla ei pitäs olla väliä ja se saa esiintyä vaik keskellä jotain toista sanaa)?

Eli siis se toimis jotenki tähän tapaan: "Ohjelmointiputka: Keskustelu: C / C++ ja Delphi / Pascal - Opera" -> return KyllaLoytyi;

"C++ - Wikipedia - Opera" -> return EiLoytynyt;

eli siis toi lainausmerkeissä oleva on se tarkistettava jutska ja ylemmästä löytyy sana ohjelmointi (OHJELMOINTIputka).

Legu [14.08.2007 19:55:01]

#

Sitä Googlea kannattaa käyttää...
No jokatapauksessa esim. http://www.cppreference.com saattaa auttaa jatkossa.

string mjono("Ohjelmointiputka: Keskustelu: C / C++ ja Delphi / Pascal - Opera");
string::size_type loc = mjono.find( "Opera", 0 );
if (loc != string::npos) {
    cout << "Löyty" << endl;
} else {
    cout << "Ei löytyny" << endl;
}

Aloittelija3 [14.08.2007 20:46:13]

#

Legu kirjoitti:

Sitä Googlea kannattaa käyttää...
No jokatapauksessa esim. http://www.cppreference.com saattaa auttaa jatkossa.

string mjono("Ohjelmointiputka: Keskustelu: C / C++ ja Delphi / Pascal - Opera");
string::size_type loc = mjono.find( "Opera", 0 );
if (loc != string::npos) {
    cout << "Löyty" << endl;
} else {
    cout << "Ei löytyny" << endl;
}

No nyt se valittaa että "`find' is not a type" ja "request for member of non-aggregate type before '(' token"

Mazzimo [14.08.2007 20:53:18]

#

Onko #include <string> mukana?
Huomaa myös ettö string sijaitsee std-nimiavaruudessa.

Aloittelija3 [14.08.2007 21:20:23]

#

Mazzimo kirjoitti:

Onko #include <string> mukana?
Huomaa myös ettö string sijaitsee std-nimiavaruudessa.

Kyllä oon mielestäni ottanu molemmat asiat huomioon.

#include <string>
using namespace std;

Tämähän riittää vai?

Pekka Karjalainen [14.08.2007 21:30:52]

#

Tämä kääntyi ja toimi minulla.

#include <iostream>
#include <string>

using namespace std;

int main() {
  string mjono("Ohjelmointiputka: ... Pascal - Opera");
  string::size_type loc = mjono.find( "Opera", 0 );
  if (loc != string::npos) {
      cout << "Löyty" << endl;
  } else {
      cout << "Ei löytyny" << endl;
  }
}

Sisennys ehkä vähän pielessä. Anteeksi, jos on. Lyhensin myös merkkijonoa, mutta se ei vaikuta esimerkkiin.

TsaTsaTsaa [14.08.2007 22:19:04]

#

Ja jos haluaa, että kirjainkoolla ei ole väliä, pitää hakusana ja teksti muuttaa vaikkapa pieniksi kirjaimiksi. Onnistuu seuraavanlaisella funktiolla:

#include <cctype>
#include <string>
#include <iostream>
#include <cstdlib>

using namespace std;

string pieneksi(string sana) {
   for ( unsigned int i = 0 ; i < sana.length() ; ++i ) {
      sana.at(i) = tolower(sana.at(i));  // Skandeille muunnos tod.näk. tehtävä manuaalisesti
   }
   return sana;
}

// Ja näin se toimii:
int main() {
   string teksti = "KiSSa KoIIRAIAIAI kel ELELE!!!";
   string pienena = pieneksi(teksti);
   cout << pienena;  // tulostuu "kissa koiiraiaiai kel elele!!!"
   return EXIT_SUCCESS;
}

koo [15.08.2007 09:27:49]

#

TsaTsaTsaa kirjoitti:

Skandeille muunnos tod.näk. tehtävä manuaalisesti

Muunnoshan riippuu käytettävästä merkistöstä sekä kielestä/maasta jossa muunnosta tehdään. Aina pienten/isojen kirjainten 1:1-muunnosta ei edes voi tehdä. Lähimmäksi kuitenkin voisi päästä, kunhan vain antaa tuolle tolower-funktiolle parametriksi olosuhteita kuvaavan locale:n. Oletuslokaali "C" kun passaa lähinnä vain jenkeille, jotka eivät ääkkösiä yms. oikein tajua. Mutta locale-otuksen kautta joka tapauksessa pääsee käsiksi kaikenlaisiin muihinkin vehkeisiin (esim. collate), joilla voi käsitellä tietojen esitystapaa.

Aloittelija3 [15.08.2007 19:01:12]

#

HWND ikkuna;
char* texti;
int length;
    while(1)
    {
     ikkuna = GetForegroundWindow();
     length = GetWindowTextLength(ikkuna);
     GetWindowText(ikkuna, texti, length);
     string::size_type loc = texti.find("ohjelmointi", 0);
      if (loc != string::npos)
       {
        DoSomething();
       }
    }

Vaan tämäpä ei sitten toimikkaan :/. Mikäs avuksi? Onko jotain muuta keinoa kun toi .find

Legu [15.08.2007 19:06:52]

#

Muuta tuo char-taulukko stringiksi:

char* teksti = "Tekstiä tässä...";
string teksti2(teksti);
teksti2.find(...);
//jne

http://www.cppreference.com/cppstring/string_constructors.html:

string( const char* str );

Aloittelija3 [15.08.2007 19:16:33]

#

Legu kirjoitti:

Muuta tuo char-taulukko stringiksi:

char* teksti = "Tekstiä tässä...";
string teksti2(teksti);
teksti2.find(...);
//jne

http://www.cppreference.com/cppstring/string_constructors.html:

string( const char* str );

Kiitos, nyt toimii. Tavallaan.. sain käännettyä sen mutta heti ku käynnistän exen ni ohjelma kaatuu ja tulee windowsin virheraportti-viesti ruutuun :o. Mitä ihmettä?

Legu [15.08.2007 19:52:09]

#

Johtuu ihan siitä, että nyt GetWindowText kirjoittaa tuon tuloksen ties minne.
Muistia ei ole varattu tuolle tulokselle, eli näin pitäisi toimia:

HWND ikkuna;
char* teksti;
int length;
string teksti2;

ikkuna = GetForegroundWindow();
length = GetWindowTextLength(ikkuna) + 1; //nollatavulle + 1
teksti = new char[length];
GetWindowText(ikkuna, teksti, length);
teksti2 = teksti;
delete [] teksti;

Tuolla taitaisi toimia (tosin vain jos unicodea ei käytetä, "oikeasti" kuuluisi käyttää noita Microsoftin LPTSTR, TCHAR ym.)

Kannattaa opetella ihan jostain kirjasta/oppaasta nuo perusasiat (muistinhallinta, osoittimet, jne.)

Pekka Karjalainen [15.08.2007 20:02:07]

#

Aloittelija3 kirjoitti:

Kiitos, nyt toimii. Tavallaan.. sain käännettyä sen mutta heti ku käynnistän exen ni ohjelma kaatuu ja tulee windowsin virheraportti-viesti ruutuun :o. Mitä ihmettä?

Vika voi olla tässä.

GetWindowText(ikkuna, texti, length);

texti-osoittimen pitää osoittaa muistialueeseen, jossa on length-muuttujan verran tilaa kirjoittaa tekstiä.

Jos määrittelet vaikkapa textin muodossa char texti[20];, niin silloin Windows API-referenssin mukaan voit laittaa pituudeksi myös 20. Mikäli sieltä tulee enemmän tekstiä, se katkeaa 19:ään merkkiin, koska myös loppumerkille pitää jäädä tila.

Sinun vastuullasi on varata tarpeeksi tilaa saadulle tekstille ja kertoa funktiolle length-parametrilla, mikä on sen tilan maksimikoko.

http://msdn2.microsoft.com/en-us/library/ms633520.aspx

Jos tämä on hepreaa, opettele pointterit ja muistinvaraus alusta asti. Ei se ole vaikeaa, mutta liian pitkä aihe tässä käytäväksi.

Tosin voi se ohjelma kaatua muistakin syistä. Auttaisi varmaan, jos voisit antaa kokonaisen ohjelman, josta olet karsinut kaiken turhan pois.

Aloittelija3 [15.08.2007 22:29:10]

#

Kiitos tuhannesti Kopeekka ja muut! Sain toimimaan :)

koo [16.08.2007 00:24:30]

#

Legu kirjoitti:

Kannattaa opetella ihan jostain kirjasta/oppaasta nuo perusasiat (muistinhallinta, osoittimet, jne.)

Esimerkki on ihan täyttä asiaa, mutta yksi perusasia unohtui. Kymmenen pointsia ja virtuaalinen virvoitusjuoma sille, joka äkkää, mitä tässä tapahtuu ratkaisevasti eri tavalla, vaikka periaatteessa tehdään ihan samat asiat:

HWND ikkuna = GetForegroundWindow();
int const length = GetWindowTextLength(ikkuna) + 1;
vector<char> teksti(length);
GetWindowText(ikkuna, &teksti[0], length);
string teksti2(&teksti[0]);

(Funktioiden paluuarvot pitäisi tarkastaa ja suosia Windowsin TCHAR-määritystä, mutta ei nyt välitetä näistä.)

Legu [16.08.2007 16:49:24]

#

string str;
HWND ikkuna = GetForegroundWindow();
int const length = GetWindowTextLength(ikkuna) + 1;
str.resize(length);
GetWindowText(ikkuna, &str[0], length);
// cout << str << endl; tai vastaavaa

Eikös tällainenkin toteutus ole mahdollinen?

koo [16.08.2007 22:30:41]

#

Standardin mukaan ei (vielä) ole. Ja vaikka olisikin, stringin pituutta pitäisi lopuksi vielä säätää, jotta '\0' tulisi oikein käsiteltyä.

Mutta se varsinainen pointti oli siinä, että se aiempi esimerkkisi voi vuotaa muistia, mutta viilaamani versio ei.

Pekka Karjalainen [17.08.2007 14:31:22]

#

koo kirjoitti:

Esimerkki on ihan täyttä asiaa, mutta yksi perusasia unohtui. Kymmenen pointsia ja virtuaalinen virvoitusjuoma sille, joka äkkää, mitä tässä tapahtuu ratkaisevasti eri tavalla, vaikka periaatteessa tehdään ihan samat asiat:

HWND ikkuna = GetForegroundWindow();
int const length = GetWindowTextLength(ikkuna) + 1;
vector<char> teksti(length);
GetWindowText(ikkuna, &teksti[0], length);
string teksti2(&teksti[0]);

Viittaus oli tähän koodiin.

Legu kirjoitti:

HWND ikkuna;
char* teksti;
int length;
string teksti2;

ikkuna = GetForegroundWindow();
length = GetWindowTextLength(ikkuna) + 1; //nollatavulle + 1
teksti = new char[length];
GetWindowText(ikkuna, teksti, length);
teksti2 = teksti;
delete [] teksti;

Saako pelata vielä jälkikäteen?

Kohdasta teksti2 = teksti voi seurata std::bad_alloc-poikkeus, jos stringiä luodessa sille ei voida varata tarpeeksi muistia. Sen jälkeen delete [] jää suorittamatta, mikä aiheuttaa mainitun muistivuodon.

Onko joku muu mahdollisuus jättää deletointi suorittamatta?

Koon versiossa vektori siivoa itse jälkensä, olipa tilanne poikkeuksellinen tai ei.

koo [17.08.2007 18:45:41]

#

Juuri näin se menee. Exception safety on tärkeä juttu C++:n kanssa. Ja kyllä se pitää ottaa huomioon muissakin kielissä, sillä ei esimerkiksi garbage collection ihan kaikkia juttuja paranna sekään.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta