• 16 odgovora
  • 3.939 pregleda
Konvertovanje unsigned char u CString 10.09.2010. u 06:57 · pre 196 meseci #1
Dobar dan,
imam problem sa brzinom izvrsavanja koda, pa bih zamolio ako neko moze da me posavetuje.

Opis problema
Potrebno je konvertovati relativno veliki niz unsigned char( ~ 200k) u CString. Kada je niz mali ~1000, funkcija radi dobro, ali kako raste niz tako se i funkcija usporava .. i to, cini mi se eksponencijalno.

Kod
U pitanju je jedna funkcija, koja manje-vise izgleda ovako:
Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
{
      CString retValue(' ', in_len);

      while(in_len--)
      {
             retValue += *(in_buff++); //ovaj deo je problem
      }

      return retValue; 

}



Pitanje
Da li ova funkcija moze da se ubrza?


Hvala
Re: Konvertovanje unsigned char u CString 10.09.2010. u 07:43 · pre 196 meseci #2
Nemam na ovoj masini instaliran VC (a i odavno ne koristim MFC), pa ne znam koliko cu ti biti od pomoci. Ipak, da pokusam dok ti se ne jave MFC majstori :)

Na osnovu nekog iskustva, ovo u petlji:
Code:

retValue += *(in_buff++); //ovaj deo je problem

... ne valja, jer pretpostavljam da se svaki put interno alocira "privremeni objekat" za sabiranje, koji je svaki put sve veci i veci, pa otuda i pomenuto "eksponencijalno" usporenje, sto je na 200K podataka vec ozbiljno.

Ako vec ne postoji direktno konvertovanje iz "unsigned char*" u CString (sto zaljucujem jer pitas :d) onda pokusaj neku akrobaciju sa:
1. ALOKACIJA: CString.GetBuffer(velicina_buffera)
2. KOPIRANJE iz unsigned char*: memcpy() ili CopyMemory() // pokusaj i sa strncpy, mada mislim da ona radi samo sa "char*"
3. OSLOBADJANJE: CString.ReleaseBuffer(velicina_buffera)

Ipak, još jednom razmisli o finalnom dizajnu te funkcije, tj. da li da funkcija vraca CString ili pokazivac na CString, s obzirom da se radi o 200K podataka.


EDIT: Ili modifikuj postojeci kod tako da koristi AppendChar(), mozda bude razlike.

[Ovu poruku je menjao X Files dana 10.09.2010. u 09:02 GMT+1]
Re: Konvertovanje unsigned char u CString 10.09.2010. u 08:13 · pre 196 meseci #3
Hvala na brzom odgovoru.

Mozda gresim, ali zar nije memorija alocirana na pocetku sa: CString retValue(' ', in_len) ?

.. retValue ce na kraju biti duzine in_len.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 08:27 · pre 196 meseci #4
Kad bolje pogledam, pitam se da li ono inicijalno alociranje "CString retValue(' ', in_len);" uopste ima smisla, jer dodavanje (+=) svakako mora da vodi racuna o realokaciji.

Sto se tice operacije += za dodavanje novog znaka, mislim da se svaki put interno alocira ceo prethodni sadrzaj da bi izvrsilo dodavanje, pa se to vraca u objekat.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 08:34 · pre 196 meseci #5
Prema ovome bi trebalo da CString čak ima konstruktor koji preuzima unsigned char*.

http://msdn.microsoft.com/ja-jp/library/ms928949.aspx

Da li si probao ovako:
Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
{ return CString(in_buff); }

Rekao bih da ovo očekuje string sa null-om na kraju.
Potpis
Ipak se ++uje.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 08:34 · pre 196 meseci #6
Ja koristim uvek GetBuffer , Copy .., ReleaseBuffer i nisam imao nikad problema ...
To je u principu standardno resenje u MFC-u za ovakve stvari ..
Potpis
Viva lollapalooza
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:17 · pre 196 meseci #8
Pa ovako nesto probaj :
Code:

CStringA retValue;
unsigned char* msg=(unsigned char*)retValue.GetBuffer();
memcpy(msg,in_buff, in_len) ; 
retValue.ReleaseBuffer() ; 


Eh , da probaj i primer sto je postavio @Mali Misha trebao bi da radi : (zaboravih da postoji taj konstruktor :)
s tim sto bi niz trebao da bude null-terminated
Potpis
Viva lollapalooza
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:33 · pre 196 meseci #9
Dodatak na post Malog Mishe, postoji i konstruktor koji uzima i pointer na bafer i dužinu bafera, pa bafer ne mora da bude NUL terminisan.

Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
{
  return CString((char*)in_buff, in_len);
}


Ovo je najefikasniji i najbrži način.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:42 · pre 196 meseci #10
@deerbeer

Kod mene tvoj program puca, ali se to eliminiše konstruktorom

CStringA retValue(' ', in_len);

Međutim, šta ako njemu treba CString, a ne CStringA (pitanje je tako i postavljeno). Tada ovo sa memcpy ne pije vodu jer se dobijaju kineska slova.

Ovo je univerzalno

Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
    CString retValue(' ', in_len);
    TCHAR *buff = retValue.GetBuffer(); 

    for (int i = 0; i < in_len; ++i) {
        buff[i] = in_buff[i];
    }

    retValue.ReleaseBuffer();
    return retValue;
}


Što se tiče predloga Malog Miše, on radi ako u baferu posle in_len znakova dolayi nula (terminator). No, u tom slučaju mu ne bi trebao in_len.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:44 · pre 196 meseci #11
Citat:
Shejn: Kada je niz mali ~1000, funkcija radi dobro, ali kako raste niz tako se i funkcija usporava .. i to, cini mi se eksponencijalno.


Kvadratno. Da je eksponencijalno, ne bi ti dočekao kraj ni za 100 znakova.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:45 · pre 196 meseci #12
Citat:
Mihajlo Cvetanović: Dodatak na post Malog Mishe, postoji i konstruktor koji uzima i pointer na bafer i dužinu bafera, pa bafer ne mora da bude NUL terminisan.

Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
{
  return CString((char*)in_buff, in_len);
}


Ovo je najefikasniji i najbrži način.


E, da, ovo je najbolje.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:52 · pre 196 meseci #13
Citat:

Međutim, šta ako njemu treba CString, a ne CStringA (pitanje je tako i postavljeno). Tada ovo sa memcpy ne pije vodu jer se dobijaju kineska slova.

Tacno , ali ako mu je ANSI bild u konfiguraciji a nije napomenuo onda je CString = CStringA
Potpis
Viva lollapalooza
Re: Konvertovanje unsigned char u CString 10.09.2010. u 09:54 · pre 196 meseci #14
Citat:
Nedeljko:

Ovo je univerzalno

Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
    CString retValue(' ', in_len);
    TCHAR *buff = retValue.GetBuffer(); 

    for (int i = 0; i < in_len; ++i) {
        buff[i] = in_buff[i];
    }

    retValue.ReleaseBuffer();
    return retValue;
}



ovo mi se nakako najbolje uklapa .. jedino sto moram staviti i velicinu buffera kod alociranja
Code:

    TCHAR *buff = retValue.GetBuffer(in_len); 


bez toga mi prijavljuje gresku
error C2660: 'GetBuffer' : function does not take 0 parameters
Re: Konvertovanje unsigned char u CString 10.09.2010. u 10:12 · pre 196 meseci #15
Nema potrebe to da radiš, nema potrebe da funkcija ima više od jedne linije koda. Već sam napisao, ali možda ti je promaklo. Ovo je najbrži i najefikasniji kod:
Code:
CString convert(unsigned char const* in_buff, unsigned int in_len) 
{
  return CString((char*)in_buff, in_len);
}

Re: Konvertovanje unsigned char u CString 10.09.2010. u 12:07 · pre 196 meseci #16
Da. Najbolje je ovo što Mihajlo Cvetanović kaže.
Potpis
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
Prijavite se da biste odgovorili u ovoj temi.PrijavaRegistracija

Premeštanje teme