[C] problem z macierzami, malloc i segmentation fault

0

Witam. Mam problem z programem ktory dostalem na projekt. Mam zrobic kalkulator macierzy logicznych. Rozmiar macierzy ma byc podawany przez uzytkownika, w zwiazku z czym wymyslilem 2 rozwiazania:
1.ustalenie maksymalnego wymiaru tablicy poprzez zadeklarowanie gotowych tablic statycznych 2-wymiarowych.
2.skorzystanie z funkcji malloc i dynamicznych tablic.

Ciekawosc kazala mi wybrac druga opcje i mam problemy. Stworzylem program, caly w main(), ktory za pomoca malloca tworzyl macierz, pozwalal wczytac i wypisac jej zawartosc. Po podzieleniu programu na funkcje, sprawa sie rypla. Mimo dlugiego glowkowania nie udalo mi sie rozwiazac problemu z 'segmentation fault' w momencie wywolania funkcji wczytujacej. Goraco prosze o pomoc niedoswiadczonemu. Prosze tylko o wytkniecie bledu i wskazanie rozwiazania. Kody:

Dzialajacy, niepodzielony na fukcje:

#include <stdio.h>
#include <stdlib.h>

int main()
{
int **macierza,**macierzb,tmp;
int i,j,n;

scanf("%d",&n);

/*tworzenie*/
    macierza = malloc(n * sizeof (char));
for (i=0;i<n;i++)
{
    macierza[i] = malloc(n * sizeof (char));
}




for (i=0; i<n; ++i)
{
    for (j=0; j<n; ++j)
    {
        scanf("%d",&*(*(macierza+i)+j));
    }
}
for (i=0; i<n; ++i)
{
    for (j=0; j<n; ++j)
    {
        printf("%d\n",*(*(macierza+i)+j));
    }
}


    return 0;
}

Niedzialajacy, podzielony na funkcje:

#include <stdio.h>
#include <stdlib.h>

void tworzenie(int **macierz, int n);
void wczytywanie(int **macierz, int n);
void wypisywanie(int **macierz, int n);

int main()
{
int **macierza,**macierzb,**macierzc;
int n,wybor;

/*switch (wybor)
{
case 1: {wczytywanie(macierza,n); break;}
case 2: {wczytywanie(macierzb,n); break;}
case 3: {dzialanie(*/

scanf("%d",&n);
tworzenie(macierza,n);
wczytywanie(macierza,n);
wypisywanie(macierza,n);


return 0;
}



/*TWORZENIE*/
void tworzenie(int **macierz, int n)
{
int i;
macierz =(int**)malloc(n*( sizeof **macierz));
for (i=1;i<n+1;i++)
{
    macierz[i] =(int*)malloc(n*( sizeof *macierz));
}
}


/*WCZYTYWANIE*/
void wczytywanie(int **macierz, int n)
{
int i,j;
for (i=1; i<n+1; ++i)
{
    for (j=1; j<n+1; ++j)
    {
        scanf("%d",&*(*(macierz+i)+j));
    }
}
}


/*WYPISYWANIE*/
void wypisywanie(int **macierz, int n)
{
int i,j;
for (i=1; i<n+1; ++i)
{
    for (j=1; j<n+1; ++j)
    {
        printf("%d\n",*(*(macierz+i)+j));
    }
printf("\n");
}
}

Bardzo prosze o pomoc. Z gory dzieki:]

0

Przekazujesz do funkcji kopie wskaźnika. To że masz tam ** o niczym nie świadczy :)
to jest tak jakbyś chciał zrobić:

void funkcja (int x)
{
  x=x+1;
}
int main()
{
int a = 5;
funkcja (a);
cout<<a;
}

I oczekiwac żeby wyświetliło się 6 ;] A tak na prawdę wartość została zmieniona tylko w lokalnej kopii tej zmiennej. U ciebie jest podobnie. Najprościej będzie zwracać z funkcji alokujacej wskaźnik na tą tablicę:

int** tworzenie(int n)
{
int i;
int** macierz;
macierz =(int**)malloc(n*( sizeof **macierz));
for (i=1;i<n+1;i++)
  macierz[i] =(int*)malloc(n*( sizeof *macierz));
return macierz;
}

I wywolywać ją jako:

int** macierz = tworzenie(n);

Przy wczytywaniu nie ma problemu bo kopia wskaźnika nadal bedzie wskazywać na twoją tablicę.
Przy wypisywaniu podobnie.

0

Dzieki wielkie. Pojawil sie jeden problem, bo najprawdopodobniej zle zrozumialem Twoje wskazowki odnosnie dostepu do macierzy. Deklarowanie: int** macierz=tworzenie(n), w srodku kodu(po wczytaniu n) okazalo sie niezgodne z ANSI(tak przynajmniej mi sie wydaje:P). Usunalem "int**" i kompilator juz nic nie wyrzuca. Aha bo zapomnialem ze program ma byc zgodny z wlasnie standardem ANSI.

Jeszcze raz dzieki za pomoc:]

0

Ale co ty za bzdury opowiadasz? Ty wiesz w ogóle po co są te gwiazdki? Bo mam wrażenie że nie.
-ansi -pedantic może ci rzucic warninga, za to ze deklarujesz zmienne gdzieś w kodzie, a nie na początku funkcji, ale nie widze problemu. Nie możesz zdeklarować tej zmiennej wczesniej, a potem przypisać jej wartość? No chyba że zdeklarowałeś tą zmienną dwukrotnie w kodzie, to wtedy przepraszam i odsyłam do nauki podstaw C.

0

Dokladnie, wyrzucil mi warninga, jak zadeklarowalem w kodzie(czyli deklaracje ... kod... deklaracja). Myslalem ze o to chodzilo. Gdzies czytalem ze to mozliwe, a okazalo sie ze ANSI na to nie pozawala(o czym nie wiedzialem). Poza tym, ja sie ucze podstaw, dlatego tu pisze. Serio, wiem co to sa "te gwiazdki". Nie deklarowalem tych zmiennych 2x w kodzie. Zalozenie moich projektow jest takie, ze ma nie byc zadnych warnow, dlatego o tym wspomnialem.

0

No więc ok, wystarczy ze zadeklarujesz najpierw
int** macierz;
A potem w kodzie przypiszesz wartość. I nie będzie warninga ;)

0

Tak tez zrobilem:] Dzieki jeszcze raz:]
Zostalo mi zabezpieczenie przed blednymi danymi
Ogolnie wyszlo to tak:

#include <stdio.h>
#include <stdlib.h>


/*PROTOTYPY*/
int** tworzenie(int x,int y);
void wczytywanie(int **macierz,int x,int y);
void wypisywanie(int **macierz,int x,int y);
void and(int **macierz1,int **macierz2,int **macierz3,int x,int y);
void or(int **macierz1,int **macierz2,int **macierz3,int x,int y);
void xor(int **macierz1,int **macierz2,int **macierz3,int x,int y);
void nor(int **macierz1,int **macierz2,int **macierz3,int x,int y);
void nand(int **macierz1,int **macierz2,int **macierz3,int x,int y);

/*CZLON GLOWNY*/
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
int main()
{
int** macierza;
int** macierzb;
int** macierzc;
int x,y,wybor,mac,maca,macb,d;
mac=0;
maca=0;
macb=0;
d=0;

while (wybor!=0)
{
printf("1-zmien wymiary macierzy\n");
printf("2-wczytaj dane do macierzy A\n");
printf("3-wczytaj dane do macierzy B\n");
printf("4-wypisz dane z macierzy C(wynik)\n");
printf("5-wykonaj operacje AND\n");
printf("6-wykonaj operacje OR\n");
printf("7-wykonaj operacje XOR\n");
printf("8-wykonaj operacje NOR\n");
printf("9-wykonaj operacje NAND\n\n\n");
printf("0-wyjscie.");

scanf("%d",&wybor);

switch (wybor)
{
case 1: {
        scanf("%d",&x);
        scanf("%d",&y);
        macierza=tworzenie(y,x);
        macierzb=tworzenie(y,x);
        macierzc=tworzenie(y,x);
        mac=1;
        maca=0;
        macb=0;
        d=0;
        break;
        }
         
case 2: {
        if (mac==1)
        {
        wczytywanie(macierza,x,y);
        maca=1;
        }
        else
        {
        printf("najpierw podaj wymiary macierzy!");
        }
        break;
        }
        
case 3: {
        if (mac==1)
        {
        wczytywanie(macierzb,x,y);
        macb=1;
        }
        else
        {
        printf("najpierw podaj wymiary macierzy!");
        }
        break;
        }
case 4: {
        if ((mac==1)&&(maca==1)&&(macb==1)&&(d==1))
        {
        wypisywanie(macierzc,x,y);
        }
        else
        {
        printf("nie wykonales zadnego zadania!");
        break;
        }
        }
case 5: {
        if ((mac==1)&&(maca==1)&&(macb==1))
        {
        and(macierza,macierzb,macierzc,x,y);
        }
        else
        {
        printf("nie podales jakichs danych!");
        }
        d=1;
        break;
        }
case 6: {
        if ((mac==1)&&(maca==1)&&(macb==1))
        {
        or(macierza,macierzb,macierzc,x,y);
        }
        else
        {
        printf("nie podales jakichs danych!");
        }
        d=1;
        break;
        }
case 7: {
        if ((mac==1)&&(maca==1)&&(macb==1))
        {
        xor(macierza,macierzb,macierzc,x,y);
        }
        else
        {
        printf("nie podales jakichs danych!");
        }
        d=1;
        break;
        }
case 8: {
        if ((mac==1)&&(maca==1)&&(macb==1))
        {
        nor(macierza,macierzb,macierzc,x,y);
        }
        else
        {
        printf("nie podales jakichs danych!");
        }
        d=1;
        break;
        }
case 9: {
        if ((mac==1)&&(maca==1)&&(macb==1))
        {
        nand(macierza,macierzb,macierzc,x,y);
        }
        else
        {
        printf("nie podales jakichs danych!");
        }
        d=1;
        break;
        }
}
}
system("PAUSE");
return 0;
}


/*FUNKCJE*/
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/


/*TWORZENIE*/
int** tworzenie(int x, int y)
{
int i;
int** macierz;
macierz =(int**)malloc(x*( sizeof **macierz));
for (i=1;i<x+1;i++)
  macierz[i] =(int*)malloc(y*( sizeof *macierz));
return macierz;
}


/*WCZYTYWANIE*/
void wczytywanie(int **macierz,int x,int y)
{
int i,j;
for (i=1; i<x+1; ++i)
{
    for (j=1; j<y+1; ++j)
    {
        scanf("%d",&*(*(macierz+i)+j));
    }
}
}


/*WYPISYWANIE*/
void wypisywanie(int **macierz,int x,int y)
{
int i,j;
for (i=1; i<x+1; ++i)
{
    for (j=1; j<y+1; ++j)
    {
        printf("%d",*(*(macierz+i)+j));
    }
printf("\n");
}
}

/*AND*/
void and(int **macierz1,int **macierz2,int **macierz3,int x,int y)
{
     int i,j;
     for (i=1;i<x+1;i++)
     {
         for (j=1;j<y+1;j++)
         {
             if(((*(*(macierz1+i)+j))==1)&&((*(*(macierz2+i)+j))==1))
             {(*(*(macierz3+i)+j))=1;}
             else
             {(*(*(macierz3+i)+j))=0;}
         }
     }
}

/*OR*/
void or(int **macierz1,int **macierz2,int **macierz3,int x,int y)
{
     int i,j;
     for (i=1;i<x+1;i++)
     {
         for (j=1;j<y+1;j++)
         {
             if(((*(*(macierz1+i)+j))==1)||((*(*(macierz2+i)+j))==1))
             {(*(*(macierz3+i)+j))=1;}
             else
             {(*(*(macierz3+i)+j))=0;}
         }
     }
}

/*XOR*/
void xor(int **macierz1,int **macierz2,int **macierz3,int x,int y)
{
     int i,j;
     for (i=1;i<x+1;i++)
     {
         for (j=1;j<y+1;j++)
         {
             if(((*(*(macierz1+i)+j))==1)!=((*(*(macierz2+i)+j))==1))
             {(*(*(macierz3+i)+j))=1;}
             else
             {(*(*(macierz3+i)+j))=0;}
         }
     }
}

/*NOR*/
void nor(int **macierz1,int **macierz2,int **macierz3,int x,int y)
{
     int i,j;
     for (i=1;i<x+1;i++)
     {
         for (j=1;j<y+1;j++)
         {
             if(((*(*(macierz1+i)+j))==0)&&((*(*(macierz2+i)+j))==0))
             {(*(*(macierz3+i)+j))=1;}
             else
             {(*(*(macierz3+i)+j))=0;}
         }
     }
}

/*NAND*/
void nand(int **macierz1,int **macierz2,int **macierz3,int x,int y)
{
     int i,j;
     for (i=1;i<x+1;i++)
     {
         for (j=1;j<y+1;j++)
         {
             if(((*(*(macierz1+i)+j))==1)&&((*(*(macierz2+i)+j))==1))
             {(*(*(macierz3+i)+j))=0;}
             else
             {(*(*(macierz3+i)+j))=1;}
         }
     }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1