Diskuze: Pole poli - calloc meni casti pole, ktere menit nema

C a C++ C a C++ Pole poli - calloc meni casti pole, ktere menit nema

Aktivity (1)
Avatar
mnauik
Člen
Avatar
mnauik:1.6.2014 22:08

Mam problem, tento calloc, pri poradi==4 delkaRetezce==3

seznamStringu[po­radi] = (char**)calloc(del­kaRetezce,size­of(char*));

meni tyto chary:
seznamStringu[po­radi][0]
seznamStringu[po­radi][1]
seznamStringu[po­radi][2]

nebo-li mam seznam stringu, alokuju callocem pro 5. string, ktery chci tam chci pridat, ale pri calloc se nesmyslne zmeni chary v 1. retezci - tedy misto abc mam ruzne otazniky a nesmyslne znaky. Prosel jsem to debuggerem a tato situace nastane za podminek, ktere jsem jiz napsal poradi==4, delkaRetezce==3

Odpovědět 1.6.2014 22:08
minusuj mě, ale zdůvodni to ;)
Avatar
coells
Redaktor
Avatar
Odpovídá na mnauik
coells:1.6.2014 22:18

:-D viz komentáře v kódu

// 1) alokujes POLE POINTERU NA CHAR
// pokud je delkaRetezce = 3, pak alokujes 24 bytu
// 2) nastavíš 4. pointer v poli seznamStringu na nove alokovanou pamet
// (pokud poradi = 4)
seznamStringu[poradi] = (char**)calloc(delkaRetezce,sizeof(char*));

// protoze jsi nastavit hodnotu pointeru seznamStringu[poradi] na calloc
// mas tam ted NULL
// pres nasledujici prikazy se divas na adresu 0 ve svem datovem segmentu
// proto ty otazniky
seznamStringu[poradi][0]
seznamStringu[poradi][1]
seznamStringu[poradi][2]

Takže calloc nic nemění - ani nemůže - alokuje pamět a nastaví hodnoty na 0.
Hodnotu proměnné si měníš sám, a protože se jedná o pointer a ten pointer je nulový, máš velký problém ;-)

 
Nahoru Odpovědět  +1 1.6.2014 22:18
Avatar
mnauik
Člen
Avatar
Odpovídá na coells
mnauik:1.6.2014 22:26

ja to napsal spatne, omlouvam se, meni tyto chary:

seznamStringu[0][0]
seznamStringu[0][1]
seznamStringu[0][2]

neboli prvni "retezec"

Nahoru Odpovědět 1.6.2014 22:26
minusuj mě, ale zdůvodni to ;)
Avatar
Posix
Člen
Avatar
Odpovídá na mnauik
Posix:1.6.2014 22:34

jak už říkal coels... pleteš si char a char* a není ani jisté, jestli víš, co dělá calloc. Celé se mi to nezdá. Kdybys hodil větší kus kódu, tak bysme ti mohli líp poradit.

Nahoru Odpovědět 1.6.2014 22:34
Proč to dělat jednoduše, když to jde složitě.
Avatar
mnauik
Člen
Avatar
mnauik:1.6.2014 22:44

Zadani je takove, ze se programu zada string nejake delky (ale max. 8 ) a program vypise vsechny permutace, ktere budou serazene.

Algoritmus ohledne permutaci jsem bral odtud:
http://www.geeksforgeeks.org/…iven-string/

A ja ho trochu pozmenil, aby vyhovoval zadani (nevypisu permutace hned, ale nejprv je dam do pole a pak je setridim)

void swap (char *x, char *y)
{
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}


int k=0;

void permute(char *a, int i, int n)
{
   int j;
   if (i == n)  {

   seznamStringu[poradi] = calloc(delkaRetezce,sizeof(char*));
  strncpy(seznamStringu[poradi],a,delkaRetezce);

    poradi++;
   }
   else
   {
        for (j = i; j <= n; j++)
       {
          swap((a+i), (a+j));
          permute(a, i+1, n);
          swap((a+i), (a+j));
       }
   }
}

poradi - globalni promenna typu int, po kazdem zapsani retezce do pole se zvetsi o 1.

delkaRetezce - delka jednoho retezce

delkaPole - delka pole - neboli max pocet retezcu, ktere se vejdou do pole, jelikoz se jedna o permutace, tak je to delkaRetezce! (faktorial)

Editováno 1.6.2014 22:45
Nahoru Odpovědět 1.6.2014 22:44
minusuj mě, ale zdůvodni to ;)
Avatar
coells
Redaktor
Avatar
Odpovídá na mnauik
coells:1.6.2014 22:52

Jak alokuješ seznamStringu[] ? Není náhodou tahle proměnná neinicializovaná?

 
Nahoru Odpovědět 1.6.2014 22:52
Avatar
mnauik
Člen
Avatar
mnauik:1.6.2014 22:58

Jeste jsem nedodal main a v mainu inicializovana je:

int main()
{


int i = 0;      //cyklova prom
int j = 0;      //cyklova prom
char retezec[8];    //retezec vstupu
    scanf("%s",retezec);    //nacteni vstupu

//strcopy(retezec,tmp);


int    delka = strlen(retezec);     //prirazeni delky
delkaRetezce = delka;               //delka retezce globalne
delkaPole = fact(delka);            //delka pole globalne
//printf("delkaPole %i",delkaPole);

    seznamStringu=calloc(delkaPole,sizeof(char));      //alokace pole



    printf("Delka retezce: %i\n",delka);
    printf("Vstupni retezec: \"%s\"\n",retezec);
        for(i = 0; i < delka - 1; i++){                     //serazeni retezce
        for(j = 0; j < delka - i - 1; j++){
            if(retezec[j+1] < retezec[j]){
                int tmp = retezec[j + 1];
                retezec[j + 1] = retezec[j];
                retezec[j] = tmp;
            }
        }
    }



   permute(retezec, 0, delka-1);
   printf("%s\n",seznamStringu[0] );                       //permutace pole

   // qsort(seznamStringu,sizeof(seznamStringu)/sizeof(seznamStringu[0]),sizeof(seznamStringu[0]), strcmp);


   for(i=0;i<delkaPole;i++) {                           //vypis pole

        printf("%s\n",seznamStringu[i]);
   }

   return 0;
}

Pak tam mam jeste metodu fact - coz je rekurzivni faktorial.
edit: v C to vlastne neni metoda, ale funkce.

Editováno 1.6.2014 22:59
Nahoru Odpovědět 1.6.2014 22:58
minusuj mě, ale zdůvodni to ;)
Avatar
coells
Redaktor
Avatar
Odpovídá na mnauik
coells:1.6.2014 23:02
// alokuje fact(delka) bytu
seznamStringu=calloc(delkaPole,sizeof(char));

// alokuje fact(delka) pointeru na byte
seznamStringu=calloc(delkaPole,sizeof(char *));

Jinak řečeno, alokuješ 8x méně paměti, než potřebuješ.

 
Nahoru Odpovědět 1.6.2014 23:02
Avatar
mnauik
Člen
Avatar
Odpovídá na coells
mnauik:1.6.2014 23:12

Dekuji, je to tak.

Jak jeste seradim pole? Zkousel jsem:

qsort(seznamStringu,sizeof(seznamStringu)/sizeof(seznamStringu[0]),sizeof(seznamStringu[0]), strcmp);

ale nefunguje.

napr. kdyz vlozim permutaci aba tak do pole to vyhodi:
aab
aba
aab
aba
baa
baa

ale potrebuji to seradit, aby to bylo:
aab
aab
aba
aba
baa
baa

Nahoru Odpovědět 1.6.2014 23:12
minusuj mě, ale zdůvodni to ;)
Avatar
coells
Redaktor
Avatar
Odpovídá na mnauik
coells:1.6.2014 23:18
qsort(seznamStringu,delkaPole,sizeof(char*), strcmp);
 
Nahoru Odpovědět 1.6.2014 23:18
Avatar
mnauik
Člen
Avatar
Odpovídá na coells
mnauik:1.6.2014 23:31

nejak to nechce seradit (coz je divne, prave tenhle tvar qsort radí i jinde), nejak to prohodi ty retezce, ale netusim podle jakeho pravidla, napr misto prvnich 4 permutaci (retezec delky 4) ve tvaru:

aabb
aabb
aabb
aabb
........

to vypise:
aabb
baba
aabb
bbaa
........

Nahoru Odpovědět 1.6.2014 23:31
minusuj mě, ale zdůvodni to ;)
Avatar
coells
Redaktor
Avatar
Odpovídá na mnauik
coells:2.6.2014 10:25
int compare (const void *a, const void *b)
{
    const char **x = (const char **)a;
    const char **y = (const char **)b;
    return strcmp(*x, *y);
}

qsort(seznamStringu, delkaPole, sizeof(char *), compare);
 
Nahoru Odpovědět  +1 2.6.2014 10:25
Avatar
mnauik
Člen
Avatar
Odpovídá na coells
mnauik:2.6.2014 12:33

Dekuji moc, kontrolni system to vzal. Zkousel jsem pred tim bubblesort, ale to bylo na nej moc pomaly a vedel jsem o tom qsortu, ale nevedel jsem jak :)

Nahoru Odpovědět 2.6.2014 12:33
minusuj mě, ale zdůvodni to ;)
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.