» »

[C++] Pretvorba iz int v char *

[C++] Pretvorba iz int v char *

Srachko ::

Pozdravljeni!

Ukvarjam se z eno manjšo programersko nalogico (ni za šolo, ampak za lastne potrebe). Pred dnevi sem se dokopal do nekega tutoriala o Windows API programiranju in ker sem zelo radoveden, sem zadevo tudi preizkusil. Z malo eksperimentiranja mi je uspelo sestaviti manjši programček, ki mi bo mogoče še prišel prav (gre za neke vrste osebni organizator financ).

Zadeva se mi zašteka pri API funkcijah MessageBox(), SetDlgItemText(), ipd., ki na zaslonu prikaže sporočilno okno, nastavi določen tekst na kontrolniku, ...
Problem je v tem, da lahko v tem sporočilnem oknu izpisujem le podatke tipa char *. Poizkušal sem malo poguglat, vendar nisem našel nič kaj uporabnega.

Zanima me, kako bil lahko neko spremenljivko tipa int (v nekaterih primerih tudi long in double) spremenil v char *. Npr. da želim v sporočilnem oknu izpisat število 200. To bi potem moral pretvoriti v char *, da bi lahko izpisal v sporočilnem oknu. Castanje seveda odpade. V mislih sem imel eno idejo, kako bi se to dalo rešiti, vendar je ta ideja preveč časovno požrešna.

Preiskal sem tudi CodeGuru, vendar mi ni uspelo najti nobenega članka, ki bi mi ustrezal.

Rabim nasvet, kako bi iz int nekaj = 200; naredil char* nekajzbesedo = "200";
I can see clearly now, the brain has gone...

BlueRunner ::

sprintf ali pa itoa.

zhigatsey ::

Ker prihajam iz delphi okolja sem bil pri cpp prav živčen dokler si nisem spisal tole:)
Mogoče je še kje kakšna napaka in bi lahko tudi boljše napisal...

// convertToString
template<class T>
string convertToString(T Value)
{
    stringstream ss;
    ss << Value;
    return ss.str();
}

// floatToStr
string floatToStr(double value)
{
    return convertToString<double>(value);
}

// intToStr
string intToStr(int value)
{
    return convertToString<int>(value);
}

// longToStr
string longToStr(long value)
{
    return convertToString<long>(value);
}

// uLongToStr
string uLongToStr(unsigned long value)
{
    return convertToString<unsigned int>(value);
}

// strToFloat
double strToFloat(string value)
{
    return std::atof(value.c_str());
}

// strToInt
int strToInt(string value)
{
    return std::atoi(value.c_str());
}

// strToLong
long strToLong(string value)
{
    return std::atol(value.c_str());
}

// strToULong
unsigned long strToULong(string value)
{
    char* pEnd;
    return std::strtoul(value.c_str(), &pEnd, 0);
}

Gundolf ::

Ok, ampak tole mi pa totalno ni jasno. Če že imaš eno splošno obliko funkcije, ki dela povsod (convertToString), zakaj si želiš imeti še eno tono različno poimenovanih funkcij za točno določene tipe?

SodVina ::

kaj pa ce bi poskusil

nekajzbesedo = ""+nekaj;

BlueRunner ::

@Gundolf: C++ Templates.

Generična funkcija convertToString je generičen postopek s katerim se na nek način pretvori vrednost poljubnega tipa spremenljivke v njeno tekstovno reprezentacijo. Vse ostale funkcije pa uporabljajo tipizirano (končno) obliko tega postopka.

Na ta način se je konkretno kodo naredilo krajšo, bolj pregledno in lažjo za vzdrževanje.

Zgodovina sprememb…

BlueRunner ::

@SodVina: Preberi si o sintaksi programskih jezikov C in C++.

SodVina ::

my bad. sem ze malo out s c-jem.

OwcA ::

Generična funkcija convertToString je generičen postopek s katerim se na nek način pretvori vrednost poljubnega tipa spremenljivke v njeno tekstovno reprezentacijo. Vse ostale funkcije pa uporabljajo tipizirano (končno) obliko tega postopka.

Pa saj že (pred)prevajalnik naredi točno to, kar on počne ročno. Če slučajno čigav čut za estetiko trpi pri pisanju convertToString<unsigned int>, je še vseeno bolj elegantno malo typedef-at kot pa klonirati kodo.
Otroška radovednost - gonilo napredka.

zhigatsey ::

He he, Kot sem že zgoraj napisal prihajam iz delphi okolja kjer sem
navajen na IntToStr, StrToINt, FloatToStr, StrToInt itd... to je bil razlog...

Gundolf ::

BlueRunner, še dobro da mi nisi mojega članka o templatih serviral :D

Kot je že Owca rekel in shigatse priznal, tiste dodatne funkcije so samo neke vrste syntactic sugar (verjetno za koga iz Delphija, meni osebno so popolnoma odveč). Jaz pa prihajam iz C++a in se mi zdi kontraproduktivno neko generično zadevo omejevat.

BTW, da se tudi v drugo smer.
struct fromString {
   const std::string source;
   fromString(const std::string& src) : source(src) {}

   template<class Dest>
   operator Dest() const {
      std::ofstream tempSS(source);
      Dest tempVar;
      tempSS >> tempVar;
      return tempVar;
   }
};

// uporaba:
int i = fromString(nekString);
double d = fromString(nekString);

(nisem preveril, če se tole res kompajla, ampak princip je tak)

Srachko ::

No sam sem uporabil itoa, in nekak dela, vendar me začne zezat, kot uporabim npr. strcpy(). Zanima me, če je potem niz znakov končan z null terminatorjem ali ga je potrebno ročno dodat pri itoa()?

Zgodi se mi sledeča stvar, da se nekaj pri kazalcih zaštrika in se program zruši. Osnova tega mojega programčka je seznam transakcij. V njem sem uporabil class, ki smo ga napisali na faksu in glede tega seznama grem glavo stavit, da ni tam problem (drugače mi nebi uspelo opravit vaj :D).
I can see clearly now, the brain has gone...

Gundolf ::

c++ reference
[edit]Da ne bom tako kratkobeseden, prvi stavek iz moje povezave: Converts an integer value to a null-terminated string using the specified radix and stores the result in the given buffer.
Odgovor je torej ja, buffer ti zaključi z 0. Za nadalnje pa velja tudi uporabiti malo logike - če ne bi zaključilo bufferja z 0, kako bi potem ti vedel, koliko veljavnih znakov imaš v bufferju? Oziroma, kako bi sam dodal 0, saj ne bi vedel kam.

P.S. Uporabljaj raje std::string namesto const char*, kadarkoli moraš kaj pretvarjati oblike, dodajati znake, združevati text itd, pa boš imel veliko manj problemov.

Zgodovina sprememb…

  • spremenil: Gundolf ()

Srachko ::

Večinoma tako ali tako uporabljam string, ker je veliko lažje za delat z njim. Char * uporabljam le, ko je treba iz katerega kontrolnega elementa (editbox, static, ...) kaj prebrati, ali pa kateremu izmed teh elementov nastaviti kaksen tekst (npr. za pushbutton "Click me baby one more time :-)").
Poleg tega se mi pa string zdi bolj robusten kot pa ""jajcanje" z char *. Ne vem zakaj pri MS-ju niso v Win32 API implementirali raje string kot pa char *.

Medtem pa sem ze pogruntal, kaj sem naredil narobe. Hvala na pomoči.
I can see clearly now, the brain has gone...

Gundolf ::

Oprsotite mi ker v template ponavadi kar padem, in zdaj ne bom nehal težil z njimi... So mi pač cool, kaj češ.
template<class Src>
struct ConvertStruct {
   std::stringstream str;

   ConvertStruct(const Src& src) {
      str << src;
   }

   template<class Dest>
   bool to(Dest& dest) {
      return (str >> dest);
   }
};

// syntactic sugar, da ni treba za vsako konvertanje pisat <string> ali <int> ali ...
template<class Src>
ConvertStruct<Src> convert(const Src& from) {
   return ConvertStruct<Src>(from);
}

//----------------------------------
// primeri uporabe
int i;
std::string str;
double d;

// string -> double, če se ne da potem pa string -> int
if (!convert(str).to(d)) {
   convert(str).to(i);
}

// double -> string
convert(d).to(str);

// tudi tole se da narediti (double - int), ampak obstajajo veliko boljši načini...
convert(d).to(i);

Uporaba popolnoma enostavna, ne moreš zgrešiti z vrstnim redom parametrov (from/to), deluje na vsem kar si izmisliš. Vse skupaj se da zapakirat v en header (.h fajl) in uporabit kadarkoli.

P.S. za tisti
return (str >> dest);
nisem siguren da res dela kot je treba, ampak takole pa mora zagotovo:
str >> dest;
return (!str.fail());

Zgodovina sprememb…

  • spremenil: Gundolf ()

'FireSTORM' ::

char* beseda;
int stevilo=200;
beseda=(char*)stevilo;

če bo šlo pretvorit...probaj, nisem ziher
Those penguins.... They sure aint normal....

OwcA ::

Ne bo.
Otroška radovednost - gonilo napredka.

Quikee ::

char* beseda;
int stevilo=200;
beseda=(char*)stevilo;


S tem poveš, da naj kazalec "beseda" kaže na pomnilniško lokacijo 200.

Matrin ::

Samo iz zanimanja, ali so tiste funkcije kaj bolj učinkovite, ko pa če jaz znak za znakom pretvarjam int v char. Stvar bi naredil tako, da bi število delil z deset in pogledal kakšen je pri tem ostanek, potem pa z if stavki ali pa s switch napisal pravilen znak v char.

y00r3 ::

Uporabi itoa() in atoi() in je probelm rešen... zakaj bi izmumljal toplo vodo:D

Matako ::

sprintf() zrihta!
/\/\.K.

Srachko ::

Malo sem še pobrowsal po ene par kjižcah, ki drugače samo stojijo na polici. V njih sem našel eno zanimivo stvar o Win32 api, da lahko s pomočjo funkcije SetDlgItemInt() nastavim nekemu kontrolniku skoraj katerikoli napis (seveda številski) brez pretvarjanja v char * ipd. ampak vseeno hvala na pomoči.

Zdaj pa grem pregledat ene 1800 vrstic kode, kje vse lahko to uporabim :D
I can see clearly now, the brain has gone...

zhigatsey ::

Živjo,

Imam en problem.... Za pretvarjanje med tipi imam po zgledu zgornjih odgovorov narejeno tole funkcijo
    template<class Src, class Dest>
    inline bool convert(const Src& src, Dest& dest)
    {
        std::stringstream str;
        str << src;
        str >> dest;
        return (!str.fail());
    }


Problem nastane pri pretvarjanju double v std::string... in sicer zato ker mi v določenih primerih odreže decimalke....
Po defaultu je precision 6 in zato mi npr. pri 12345.45 pretvori v 12345.5....
Sem mislil da bi bila rešitev to da bi naredil magari še eno funkcijo za tipa double in string, dodal še en
parameter, ki bi določal precision in bi stringstream-u nastavil željeno "preciznost"...... Samo rad pa bi
da se mi ni treba ubadati še s tem koliko bom nastavljal precision... Rad bi da se mi double pretvori v string
taka kot je, in to brez nastavljanja preciznosti.... Če imate kakšen nasvet, kako bi to rešil....

Hvala za odgovore

Gundolf ::

str << setprecision(100) << src; 

pa ne pozabi na includat iomanip.

lahko pa tisti 100 nadomestiš z parametrom, mu daš v funkciji default vrednsot 100 in tako obdržiš možnost spreminjanja in enostavnost, kadar tega ne rabiš.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C++] charset-a

Oddelek: Programiranje
7681 (538) SasoS
»

[C++] vprašanja (strani: 1 2 3 4 5 6 7 8 9 )

Oddelek: Programiranje
44724617 (9163) aljazko1995
»

[C] struct in int[] (strani: 1 2 )

Oddelek: Programiranje
655939 (5012) MrBrdo
»

operator +

Oddelek: Programiranje
71102 (975) MasterBlaster
»

int to string v c++

Oddelek: Programiranje
272024 (1752) OwcA

Več podobnih tem