www.mikrocontroller.net

Forum: PC-Programmierung 2 Dimensionales Array an Funktion übergeben in c


Autor: Christian A. (ferrice)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

möchte ein 2 dimensionales Array an eine funktion übergeben die das dann 
mit printf ausgibt...

Könnt ihr mir bitte sagen was ich da falsch mache?
void ausgabe_intm(int **ptr, int spa, int zei)
{
    int i, j;
    for (i = 0; i < zei; i++)
  {
        for(j = 0; j < spa; j++)
        {
            printf("%d\t", *(*(ptr+i)+j));
        }
        printf("\n");
    }
}

int main (void)
{

int spaa = 2;
int zeia = 2;
int ma[zeia][spaa] = {{1,2},{1,2}};

ausgabe_intm(&ma,spaa,zeia);


return 0;          //Exit
}

schöne Grüße

: Gesperrt durch Moderator
Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist in jeder Hinsicht falsch, ich weiss gar nicht, wo ich anfangen 
soll. Haettest du den Code mal dokumentiert, waere dir bestimmt schnell 
aufgefallen, dass es so nicht gehen kann. Deine Funktion hat keine 
Ahnung, welche Dimensionen das Array hat, ergo kannst du auch nicht 
ausrechnen, auf welche Stelle im Array du zugreifen willst. Zumindest 
die Zeilenbreite muss also mit rein.

int** uebergeben ist falsch, du willst ja mit einem Array von ints 
arbeiten (auch wenn es mehrdimensional ist) und nicht mit einem Array 
mit Zeigern auf Arrays von ints.

Am Ende muss der Zugriff z.B. so aussehen: ptr[( i * Zeilenbreite) + j];

Es waere fuer dich und fuer andere wesentlich einfacher, wenn du 
ordentliche Variablennamen und Kommentare verwenden wuerdest.

Autor: Christian A. (ferrice)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum soll meine Funktion keine Ahnung haben, welche Dim das Array hat?
Ich übergebe ja die Zeilen und die Spalten...

Ein 2 dimensionales Array ist ja ein pointer auf einen pointer, oder 
liege ich da falsch?

kannst du vielleicht meinen code richtig stellen, das würde mir sehr 
helfen...

schöne Grüße

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na so wie Peter schreibt, geht's. Du kannst auch hier nachlesen:

2.11: How do I write functions which accept 2-dimensional arrays when 
the "width" is not known at compile time?
http://www.lysator.liu.se/c/c-faq/c-2.html

=> void ausgabe_intm(int *ptr, int spa, int zei)
=>             printf("%d\t", ptr[i*spa + j]);
=> ausgabe_intm(&ma[0][0], spaa, zeia);

> Ein 2 dimensionales Array ist ja ein pointer auf einen pointer, oder
> liege ich da falsch?

Das erklärt dir die Antwort zu Frage 2.10 ;-)

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. wrote:
> Warum soll meine Funktion keine Ahnung haben, welche Dim das Array hat?
> Ich übergebe ja die Zeilen und die Spalten...

Stimmt, das habe ich in dem Gewusel falsch einsortiert.

> Ein 2 dimensionales Array ist ja ein pointer auf einen pointer, oder
> liege ich da falsch?

Ja, schrieb ich ja schon.

> kannst du vielleicht meinen code richtig stellen, das würde mir sehr
> helfen...

Na, steht doch schon da:

ptr[( i * spa) + j] nehmen.

Und statt int** nur int* verwenden und natuerlich statt &ma nur ma 
uebergeben.

Tip: Dokumentieren ist so, als wuerde man sich seinen Gedankengang 
selbst erklaeren - dabei faellt einem oft schon selbst auf, was einen 
Sinn ergibt und was nicht.

Autor: Horst Mandy (horst-mandy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

am besten ist es, wenn du einen einfachen array benutzt.

z.B. so

void ausgabe_intm(int *mat, int rows, int cols)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for(j = 0; j < cols; j++)
        {
            printf("%d\t", mat[j*rows+i]);
        }
        printf("\n");
    }
}


int main (void)
{
    int rows = 5, cols = 4;
    int ma[] = { 1, 2, 3, 4, 5, // 1. spalte
                 6, 7, 8, 9,10, // 2. spalte
                11,12,13,14,15, // 3. spalte
                16,17,18,19,20  // 4. spalte
                };

    ausgabe_intm(ma, rows, cols);

    return 0;          //Exit
}

Autor: Christian A. (ferrice)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

besten Dank, so funktioniert es.

Was mir allerdings noch nicht ganz klar ist, was bei dieser Zeile genau 
passiert...?
printf("%d\t", ptr[i*spa + j]);

Ein eindimensionales Array ist ja eigentlich nur ein zeiger, der auf 
mehrere speicherstellen zeigen kann.
Ein zweidimensionales Array hingegen, ist dann ein zeiger, wiederrum auf 
einen zeiger zeigt, und dieser zeiger zeigt dann auf eine 
speicherstelle.

Stimmt das so?

Beim funktionsaufruf wird ja dem int pointer (ptr) die adresse des 
ersten pointers des 2 dimensionalen arrays mit der anweisung &ma[0][0] 
übergeben, soweit ich das nachvollziehen kann...

Was bedeuten die eckigen klammern wenn man auf einen pointer 
zugreift...?
also das ptr[]...?

Danke schonmal für eure hilfe...

greets

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit C99-VLAs geht's so:
#include <stdio.h>

void ausgabe_intm(int zei, int spa, int array[zei][spa])
{
  int i, j;

  for (i = 0; i < zei; i++)
  {
    for(j = 0; j < spa; j++)
    {
      printf("%d\t", array[i][j]);
    }
    printf("\n");
  }
}

int main (void)
{

  int spaa = 2;
  int zeia = 2;
  int ma[zeia][spaa];

  ma[0][0] = 1; ma[0][1] = 2;
  ma[1][0] = 1; ma[1][1] = 2;

  ausgabe_intm(zeia, spaa, ma);

  return 0;
}
VLAs lassen sich nicht mit ={...} initialisieren, deswegen habe ich die
Initialisierung durch Zuweisungen ersetzt.

Autor: Horst Mandy (horst-mandy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Anweisung ptr[2] ist gleichbedeutend mit *(ptr + 2) nur 
übersichtlicher.
Array sind in C einfach nur Pointer. Mit den Indices gibt man nur den 
Offset zum Anfang des Arrays an.

Setz hier ptr[j*row + i] einfach einmal ein paar Werte ein, dann wirst 
du verstehen, wie das abläuft. Wenn i=0 werden einfach die ersten 5 
werte im Array als Spalte ausgegeben, wenn i=1 die ersten 5 werte ab dem 
6. und so weiter.


Hoffe, das hilft dir weiter.

Autor: Christian A. (ferrice)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok dass ist mir somit klar...

Aber was ihr mir bitte noch erklären müsst ist folgendes...

Wenn das mit der Ausgabe so funktioniert:
int ma[2][2] = {{1,2,},{1,2}};
int *ptr;
ptr = ma;

printf("%d", ptr[1]);
printf("%d", ptr[2]);
printf("%d", ptr[3]);
printf("%d", ptr[4]);

Dann würde dass doch heißen, dass das 2 dimensionale Array gleich im 
speicher abgebildet ist, wie ein eindimensionales:
Weil beim 1 dimensionalen geht das genau gleich:

int ma[4] = {1,2,1,2};
int *ptr;
ptr = ma;

printf("%d", ptr[1]);
printf("%d", ptr[2]);
printf("%d", ptr[3]);
printf("%d", ptr[4]);

Oder etwa nicht?

Auf der Seite http://www.lysator.liu.se/c/c-faq/c-2.html
 ist bei 2.10 erklärt dass ein 2 dimensionales array bei der übergabe an 
einen pointer in einen pointer auf ein array zerfällt.
Wie kann ich mir das genau vorstellen?
Kann mir das jemand sagen?

Danke Leute :)

Autor: Horst Mandy (horst-mandy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. wrote:
> Dann würde dass doch heißen, dass das 2 dimensionale Array gleich im
> speicher abgebildet ist, wie ein eindimensionales:

Genauso ist es. Wenn du in C einen 2D Array anlegst, dann wird ein 
zusammenhängender Speicherbereich reserviert. Es ist also möglich auch 
einfach über den 2D Array zu iterieren.

z.B.

int array[2][2];

hier wäre array[1][1] dasselbe wie *(array[0] + 3)


Du könntest also array[0] als einfachen Array an deine Funktion 
übergeben und dann normal darüber iterieren. Allerdings kannst du dann 
auch gleich einen normalen Array nehmen.

Ein 2D Array bringt in C kaum Vorteile.

Autor: Tommi Huber (drmota)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im C/C++ Kompendium von Dirk Louis

http://books.google.at/books?id=XPdOBeqXeZMC&pg=PA...

Mehrdimensionale Arrays als Parameter  Seite 348

findest du mehr zu deinem Problem.

Autor: mikromakro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da ich mich im moment der selben problematik widme, hier eine weitere 
variante.

gilt nur, wenn das feld statisch ist, d.h. wenn die anzahl der elemente 
des feldes "fest" sind.

void ausgabe_intm(int feld[2][2])
{
    ...   // so kann auf die Indezes ganz normal zugegriffen werden
    ...
}

int main (void)
{

int ma[2][2] = {{1,2},{1,2}};

ausgabe_intm(ma);


return 0;          //Exit
}


diese varinate ist transparenter, da man gleich sieht, dass der 
funktionsparameter ein feld ist.

habe es so aus meinen lehrbuch, als tipp, uebernommen.

mikromakro

Autor: AHMED ALY (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
kan mir das wer lösen bitte der fehler kann ich nicht beheben


public class Keme{
    private int[][] feld;
    public Keme(){
        int feld = 0;
    }
    public Keme(int[][] feld){
        this.feld = feld;
    }
    public void initial(){
        feld=new int[10][10];
        for(int i=0;i<feld.length;i++){
            for(int j=0;j<feld[i].length;j++){
                feld[i][j]=(i+1)*(j+1);
            }
        }
    }
    public void ausgabe(){
        feld=new int[10][10];
        for(int i=0;i<feld.length;i++){
            for(int j=0;j<feld[i].length;j++){
                feld[i][j]=(i+1)*(j+1);
            }
        }
    }
    public static void main(String [] args){
        Keme x=new Keme();
        System.out.println("feld["+(i+1)+"] * ["+(j+1)+"] = 
"+feld[i][j]);
        x.initial();
        x.ausgabe();

    }
}

DANKE!!

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BITTE!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@AHMED ALY

So gehts nicht.
Einen alten C-Thread fleddern um dann darin eine Java (oder was das auch 
immer sein soll) Frage unterzubringen.
Keine Beschreibung des Fehlers, sondern ein lapidares: Ich brings nicht 
hin.

Das machst du nocheinmal. Aber diesmal ordentlich.
(Thread gesperrt)

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.