[C] Wrzucenie tablicy do funkcji

0

Witam
Stawiam pierwsze kroki w C.

Mam funkcję wyznacznik zwracającą obliczony wyznacznik podanej tablicy (macierzy), kod wygląda tak:

float wyznacznik (float a[2][2], int n) {
      (...)
      return det;
}

I wywołuję ją w taki sposób:

wyznacznik(tab3,2)

Program działa no i oczywiście kod ma wadę - trzeba zmieniać w parametrach wielkość tablicy jaką funkcja przyjmuje.
Szukałem w necie i znalazłem że powinno to wyglądać tak:

float wyznacznik (float **a, int n) {

Jednakże ten kod nie działa i dostaję errorka:
``float (*)[2]' to float**' for argument 1' to float wyznacznik(float**, int)'

Czy ktoś mógłby mnie naprowadzić na poprawne rozwiązanie? :)
Pozdrawiam

0

Do autora:
Tablica dynamiczna czyli:

int N,M; //wymiary macierzy

float** macierz = (float**)malloc(sizeof(float*)*N);
for(int i=0; i<N;i++)
  macierz[i]=(float*)malloc(sizeof(float)*M);

i tutaj już masz zwykłą tablicę macierz[N][M]; którą mozesz wysyłać do funkcji, ale do tej funkcji radze tez wysłac od razu N i M, bo inaczej skąd sobie wymiary tablicy weźmiesz? ;)
Ale pamiętaj że użycie tablicy dynamicznej wymaga tez jej usuwania:

for(int i=0;i<N;i++)
  free(macierz[i]);
free(macierz);
0

Jeśli komuś przeszkadza fragmentacja pamięci to można zrobić tak:

float** newMatrix(int columns, int rows)
{
      float** result = (float**)malloc(sizeof(float*)*columns+rows*columns*sizeof(float));
      if(result)
           for(int i=0;i<columns;++i)
                result[i]=(float*)(result+columns)+rows*i;

      return result;
}

Moim zdaniem dla macierzy rozwiązanie to jest bardziej eleganckie. Na dodatek jest tylko jeden malloc i free.

0

Nie wiem czy do końca chodziło mi o to:

Shalom napisał(a)
int N,M; //wymiary macierzy

float** macierz = (float**)malloc(sizeof(float*)*N);
for(int i=0; i<N;i++)
  macierz[i]=(float*)malloc(sizeof(float)*M);

Jeśli dobrze rozumiem powyższy kod tworzy tablicę o wcześniej zadeklarowanych wielkościach N i M, jednak nie do końca o to mi chodziło...

Funkcja wyznacznik oblicza (jak trudno się domyślić) wyznacznik macierzy dowolnej wielkości, problem jest tylko z "przyjęciem" danych.

W programie funkcja jest ta wywoływana w kilku miejscach z tablicą jako parametrem lecz tablica ta ma różne rozmiary, korzystając z kodu:

float wyznacznik (float a[2][2], int n) {
      (...)
      return det;
}

Ograniczam się do obsługi tylko tablicy o rozmiarach 2x2, w przypadku gdy wywołam funkcję wyznacznik np z tablicą o rozmiarach 3x3 pojawiają się schody.

Czy nie można wywoływać funkcji z dwoma parametrami np: wyznacznik(n,tablica) gdzie zmienna n odpowiadałaby wielkości przekazywanej tablicy? Funkcja pobrałaby sobie n, stworzyła tablicę o żądanej wielkości i "przyjęłaby" tablicę i funkcja mogłaby się spokojnie wykonać...

0

Liczby N i M mogą mieć dowolne wartości takie jakie im przypiszesz. Możesz je przypisać także w trakcie działania programu.

0
winerfresh napisał(a)

Liczby N i M mogą mieć dowolne wartości takie jakie im przypiszesz. Możesz je przypisać także w trakcie działania programu.

Tak, to rozumiem.
Ale nie rozumiem jak mam to konkretnie wykorzystać w mojej funkcji.

0

...

float wyznacznik (float macierz**, int N, int M) // albo samo int N jesli ma byc kwadratowa
{
//i wtedy wszystkie pętle itd mają lecieć od 0 do N-1 a nie od 0 do 1 tak jak miałeś w tym 2x2
}
0

Dobra, to ja już nie wiem co źle robię... Albo czego nie rozumiem.

Mój działający kod - na sztywno:

 #include <iostream>
float wyznacznik (float a[3][3], int n) {
      float dzielnik;
      for (int i=0; i<n-1; i++) {
          for (int j=i+1; j<n; j++) {
              dzielnik=a[j][i]/a[i][i];
              for (int k=0; k<n; k++) {
                  a[j][k] = a[j][k] - dzielnik * a[i][k];
              }
          }
      }
      float det=1;
      for(int i=0;i<n;i++) {
              det = det * a[i][i];      
      }
      return det;
}

int main()
{
 float det;
 int n=3;
 float tab[3][3]={{7,6,7},{1,-2,1},{3,1,-2}};
      
 det=wyznacznik(tab,n);
 printf("%f",det);
      
 {
  int chr;
  puts("\n\nWcisnij enter zeby zakonczyc");
  while ((chr = getchar())!=EOF && chr!='\n');
 } 
}

Nie działający kod:

 #include <iostream>
float wyznacznik (float macierz**, int n) {
      float dzielnik;
      for (int i=0; i<n-1; i++) {
          for (int j=i+1; j<n; j++) {
              dzielnik=a[j][i]/a[i][i];
              for (int k=0; k<n; k++) {
                  a[j][k] = a[j][k] - dzielnik * a[i][k];
              }
          }
      }
      float det=1;
      for(int i=0;i<n;i++) {
              det = det * a[i][i];      
      }
      return det;
}

int main()
{
 float det;
 int n=3;
 float tab[3][3]={{7,6,7},{1,-2,1},{3,1,-2}};
      
 det=wyznacznik(tab,n);
 printf("%f",det);
      
 {
  int chr;
  puts("\n\nWcisnij enter zeby zakonczyc");
  while ((chr = getchar())!=EOF && chr!='\n');
 } 
}

Operuję tylko na macierzach kwadratowych więc wystarczy jedna zmienna n.

Prosiłbym o pomoc :)

0

A do jakich "i" dochodzą twoje pętle? Na moje oko to wartosci n-2.
skoro i<n-1 to największe możliwe i = n-2
Zrób normalne pętle
for (int i=0; i<n; i++)
Ja pisałem że do N-1 żebyś czasami nie zrobił i<=n

0

Ten mój pierwszy działający program liczy wszystko dobrze, i 1 i w 2 programie pętle i wartość n są takie same. Z pętlami jest wszystko dobrze.

Kompilator czepia się:

float wyznacznik (float macierz**, int n) {

PS Dziękuję modowi za zrobienie porządku.

0

Nie no, my sie chyba nie rozumiemy stary. Od samego początku ci tłumaczymy ze musisz zrobić dynamiczna tablicę, a ty robisz

 float tab[3][3];

Przypomina ci to choć troche:

float** macierz = (float**)malloc(sizeof(float*)*n);
for(int i=0; i<N;i++)
  macierz[i]=(float*)malloc(sizeof(float)*n);

?

0

Program gdzie mam na sztywno ustawioną tablicę wrzuciłem żeby "dyskutować" na konkretnym przykładzie i żeby zrozumieć problem. Kod ten chce przerobić żeby funkcja ta była uniwersalna, chce żeby działała obojętnie jakiego rozmiaru tablicę podam przy wywoływaniu tej funkcji.

A kod który teraz powtórzyłeś - nie umiem go wykorzystać.
Jakoś nie wydaje mi się żebym miał to wrzucić przy deklaracji całej funkcji:

 #include <iostream>
float wyznacznik (int n, float** s = (float**)malloc(sizeof(float*)*n); for(int i=0; i<N;i++) a[i]=(float*)malloc(sizeof(float)*n);) {
      float dzielnik;
      for (int i=0; i<n-1; i++) {
          for (int j=i+1; j<n; j++) {
              dzielnik=a[j][i]/a[i][i];
              for (int k=0; k<n; k++) {
                  a[j][k] = a[j][k] - dzielnik * a[i][k];
              }
          }
      }
      float det=1;
      for(int i=0;i<n;i++) {
              det = det * a[i][i];      
      }
      return det;
}

int main()
{
 float det;
 int n=3;
 float tab[3][3]={{7,6,7},{1,-2,1},{3,1,-2}};
      
 det=wyznacznik(n,tab);
 printf("%f",det);
      
 {
  int chr;
  puts("\n\nWcisnij enter zeby zakonczyc");
  while ((chr = getchar())!=EOF && chr!='\n');
 } 
}
0

Nie no stary, bez żartów ;]
Pokazałem ci 2 linijki które miałes zamienić a ty tu jakieś jaja robisz..

#include <stdio.h> //bo ty to chyba w C piszesz?
#include <stdlib.h>

float wyznacznik (int n, float** macierz);

int main()
{
  int n=3;

  float** macierz = (float**)malloc(sizeof(float*)*n);
  for (int i=0; i<n;i++)
    macierz[i]=(float*)malloc(sizeof(float)*n);

  for(int i=0;i<n;i++)
    for (int j=0;j<n;j++)
      macierz[i][j] = rand()%10; //wypełniamy jakimiś losowymi danymi

  float det = wyznacznik (n,macierz);
  printf("%f",det);

  {
    int chr;
    puts("\n\nWcisnij enter zeby zakonczyc");
    while ((chr = getchar())!=EOF && chr!='\n');
  }

  for(int i=0; i<n;i++)
    free(macierz[i]);
  free(macierz);

  return EXIT_SUCCESS;
}

float wyznacznik (int n, float** a)
  {
    float dzielnik;
    for (int i=0; i<n-1; i++)
      {
        for (int j=i+1; j<n; j++)
          {
            dzielnik=a[j][i]/a[i][i];
            for (int k=0; k<n; k++)
              {
                a[j][k] = a[j][k] - dzielnik * a[i][k];
              }
          }
      }
    float det=1;
    for (int i=0;i<n;i++)
      {
        det = det * a[i][i];
      }
    return det;
  }

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