[ Pera Pisar @ 14.10.2008. 14:16 ] @
Imam problem sa memcpy naredbom u C++u.

Ne uspeva da tačno prekopira sadržaj jednog niza u drugi.

Prvo se alocira prostor za destination niz, a onda se izvršava memcpy:
Code:

char* destination= new char[/*duzina source niza*/];
memcpy(destination, source, /*duzina source niza*/);

Pre toga sam ispisao sadržaj source niza i njegovu dužinu. Kada ispišem destination, posle sadržaja koji treba da bude u njemu, dodaje se nekoliko proizvoljnih karaktera. U čemu je problem? To treba da bude tako jednostavno, a ne funkcioniše. Pokušao sam sa svim mogućim varijantama koje su mi pale na pamet (različite dužine niza, zatim sam sam implementirao svoju memcpy funkciju i sl.), ali ništa nije uspelo.

Jel ima neko ideju? Hvala



[ X Files @ 14.10.2008. 14:50 ] @
Najverovatnije nisi iskopirao NULL ('\0') terminator kraja stringa.

Drugim rečima, ti si uradio sledeće:
Imaš SOURCE string "abcd" što je 4 bajta teksta (a interno ima 5 jer je poslednji element NULL).
Alocirao si 4 bajta za DESTINATION string.
Iskopirao si 4 bajta iz SOURCE i DESTINATION, ali nigde nemaš NULL terminator stringa, pa ni funkcija za određivanje ne zna gde je tom stringu kraj, već ide do prvog NULL-a u memoriji.

NULL terminator mozes i rucno da upises na poslednjoj poziciji, sto ti odmah govori da alokacija mora biti za jedan znak veca.

char* destination= new char[/*duzina source niza + 1*/];
memcpy(destination, source, /*duzina source niza*/);
destination[/*duzina source niza*/] = '\0';

... ili da iskopiras taj NULL zajedno sa stringom:

char* destination= new char[/*duzina source niza + 1*/];
memcpy(destination, source, /*duzina source niza + 1*/);
[ kiklop74 @ 14.10.2008. 14:52 ] @
Fali ti 0 na kraju stringa. Funkcije koje ispisuju sadrzaj C stringova pretpostavljaju da se string zavrsava sa 0.

Dakle:

Code:
char* destination= new char[/*duzina source niza*/ + 1];
memset(destination,0,/*duzina source niza*/ + 1);
memcpy(destination, source, /*duzina source niza*/);


[ Pera Pisar @ 14.10.2008. 21:53 ] @
"Elementary my dear Watson"

Hvala na odgovorima. U pravu ste.

Što je najgore, na početku sam tako slično i uradio, tj. alocirao sam jedan bajt više, međutim ništa nisam upisao u njega. Posle sam, pošto to nije radilo, prebacio na alokaciju tačnog broja bajtova.

Citat:
Fali ti 0 na kraju stringa. Funkcije koje ispisuju sadrzaj C stringova pretpostavljaju da se string zavrsava sa 0.
A šta kada je nula regularan član niza? Kako onda kompajler zna da li je terminalni karakter ili nije?

[ X Files @ 14.10.2008. 21:58 ] @
Pogledaj negde ASCII tabelu i napravi razliku izmedju znaka nula ('0') koji ima ASCII broj 48, i nule koja je baš prava nula i ovako se beleži: '\0'

"Elementary my dear Watson" ;)
[ kiklop74 @ 14.10.2008. 21:59 ] @
kompajler nema sa time nikakve veze. Radi se o tome kako su implementirane sve funkcije koje operisu sa C stringovima. Sve te funkcije pretpostavljaju da se string zavrsava kada se naidje na prvu 0 bez obzira gde to bilo.

[ X Files @ 14.10.2008. 22:05 ] @
A ako baš hoćeš da manipulišeš blokovima podataka koji zaista sadrže i 'prave' nule, onda više ne koristiš tzv null-terminated funkcije jer one polaze od pretpostavke nule kao kraja nečega, već neke druge tehnike među kojima je i ta memcpy funkcija koju si pokazao. Drugim rečima, o granicama moraš da vodiš računa uglavnom sam, sem ako koristiš neke stream klase koje interno beleže poziciju, ali to je već neka druga priča...

[ Eurora3D Team @ 16.10.2008. 10:28 ] @
Nizove zavrsene sa nulom mozes da kopias i ovako
Code:

while(*(out++)=*(in++))
        ;

Code:

#include <iostream>
using namespace std;

int main()
{
    char* nizA="Ovo je niz";
        char*nizB=new char[strlen(nizA)+1];

    //do nule
    char* in=nizA; char* out=nizB;
    while(*(out++)=*(in++))
        ;
    //
    cout << nizB << endl;

    memset(nizB,0,strlen(nizA)+1);

    //neki broj bajtova
    in=nizA; out=nizB; int ln=strlen(nizA)+1;
    while(ln--)
        *(out++)=*(in++);
    //
    cout << nizB << endl;

    //
    delete[] nizB;
    return 0;
}