Forum: PC-Programmierung Was mache ich falsch mit pointer, array


von David O. (antimonit)


Lesenswert?

Hallo, ich verstehe nicht warum mein Programm zur Berechnung von 
Matrizen, keine größere Zeilenanzahl als 4 zulässt, ab zeile = 5 stürzt 
das Programm immer ab. Bei Zeilenwerten unter 5 funktioniert alles 
einwandfrei.
Über eine Antwort würde ich mich sehr freuen:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <time.h>
4
5
#define nl printf("\n");
6
7
//Hier werden der Matrix Werte übergeben(und hier ist wohl auch der Fehler:
8
void init(int **matrix, int zeile, int spalte){
9
  int zahl, eingabe, i, k;
10
  printf("Jeden Wert einzeln(0), oder nur mit einem einigen Wert initialisieren(1)"); nl
11
  scanf("%d", &eingabe);
12
  
13
//Jede Zahl einzeln initialisieren:
14
  if(eingabe==0){
15
    printf("Initialisiere die Matrix:"); nl
16
    for(i=0; i<zeile; i++ ){
17
      for(k=0; k<spalte; k++)  {
18
      scanf("%d", &zahl);
19
      matrix[i][k]=zahl;
20
      }
21
    }
22
//Mit nur einen Zahl initialisieren:
23
  }else{
24
    printf("Welche Zahl?"); nl
25
    scanf("%d", &zahl);
26
    for(i=0; i<zeile; i++ ){
27
      for(k=0; k<spalte; k++)  {
28
        matrix[i][k]=zahl;
29
//        printf(" %d ", i);        KOntrolle von i, mit dem Ergnis, das es gar nicht alle Spalten der 5. Zeile abgearbeitet werden
30
//        *(*(matrix+i)+k)=zahl;      Alternativschreibweise
31
      }
32
    }
33
  }
34
}
35
//Hier bekommen alle Werte einer Matrix den Wert 0:
36
void init_zero(int **matrix, int zeile, int spalte){
37
  int i, k;
38
  for(i=0; i<zeile; i++ ){
39
    for(k=0; k<spalte; k++)  {
40
    
41
    matrix[i][k]=0;
42
    }
43
  }
44
}
45
//Hier wird die Matrix ausgegeben:
46
printm(int **matrix, int zeile, int spalte){
47
  int i, k;
48
  
49
  for(i=0; i<zeile; i++ ){
50
    for(k=0; k<spalte; k++)  {
51
    printf("%d\t", matrix[i][k]);  
52
    }
53
    nl
54
  }
55
}
56
//Hier werden der Matrix Zufallswerte übergeben:
57
void init_random(int **matrix, int zeile, int spalte){
58
  int zahl, i, k;
59
  time_t t;
60
     srand((unsigned) time(&t));
61
     zahl=rand()%10;
62
  for(i=0; i<zeile; i++ ){
63
    for(k=0; k<spalte; k++)  { 
64
    zahl=rand()%10;
65
    matrix[i][k]=zahl;
66
    }
67
  }
68
}
69
70
//Hier bekommt die Matrix die Anzahl der Zeilen und Spalten:
71
int ** structm(int **matrix, int zeile, int spalte){
72
73
  int i;
74
  matrix=malloc(zeile*sizeof(int));
75
  if(matrix==NULL){
76
  printf("kein Speicherplatz vorhanden"); nl
77
  return 0;
78
  }  
79
  
80
  for(i=0; i<zeile; i++){
81
    matrix[i]=malloc(spalte*sizeof(int));
82
    if(matrix[i]==NULL){
83
  printf("kein Speicherplatz vorhanden"); nl
84
  return 0;      
85
    }
86
  }
87
  return matrix;
88
}
89
//Hier werden die 2 Matrizen multipliziert:
90
int multi(int **matrix, int **matrix2, int spalte, int zeile, int spalte2, int zeile2, int **result){
91
  if(spalte!=zeile2){
92
    printf("keine Multiplikation möglich");
93
    return 0;
94
    }
95
96
    int i, k, l;
97
98
    for (i = 0; i < zeile; i++) {  
99
        for (k = 0; k < spalte2; k++) {    
100
            for (l = 0; l < zeile2; l++) {  
101
                result[i][k] += matrix[i][l] * matrix2[l][k];  
102
            } 
103
    }
104
  }
105
  printm(result, zeile, spalte2);
106
  
107
  
108
  return 0;
109
}
110
111
112
int main(int argc, char *argv[]) {
113
  int spalte=0, zeile=0 , i;
114
  int spalte2=0, zeile2=0;
115
  int  **matrix;
116
  int  **matrix2;
117
  
118
  printf("Gebe die Spalten- und Zeilenanzahl ein:"); nl
119
  scanf("%d %d", &spalte, &zeile );
120
/*
121
  matrix=malloc(zeile*sizeof(int));
122
  if(matrix==NULL){
123
  printf("kein Speicherplatz vorhanden"); nl
124
  return 0;
125
  }  
126
  
127
  for(i=0; i<zeile; i++){
128
    *(matrix+i)=malloc(spalte*sizeof(int));
129
    if(matrix[i]==NULL){
130
  printf("kein Speicherplatz vorhanden"); nl
131
  return 0;      
132
    }
133
  }
134
*/  
135
136
//Abarbeitung der ersten Matrix
137
  matrix=structm(matrix, zeile, spalte);
138
  init(matrix, zeile, spalte);
139
  printm(matrix, zeile, spalte);
140
  nl
141
  
142
//Abarbeitung der zweiten Matrix  
143
  printf("Gebe die Spalten- und Zeilenanzahl ein:"); nl
144
  scanf("%d %d", &spalte2, &zeile2 );
145
  
146
  matrix2=structm(matrix2, zeile2, spalte2);
147
//  init_random(matrix2, zeile2, spalte2);
148
  init(matrix2, zeile2, spalte2);
149
  printm(matrix2, zeile2, spalte2);
150
  
151
  
152
//Multiplikationsmatrix
153
  int **result;
154
  result= structm(result, zeile, spalte2);
155
  init_zero(result, zeile, spalte2);
156
  
157
//  Multilpikation
158
  multi(matrix, matrix2, spalte, zeile, spalte2, zeile2, result);
159
  
160
  
161
  
162
  return 0;
163
}
Gruß
Antimonit

--

Bitte C-Quelltext in [ c ] [ /c ] einschließen.

-rufus

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1
//Hier bekommt die Matrix die Anzahl der Zeilen und Spalten:
2
int ** structm(int **matrix, int zeile, int spalte){
3
4
  int i;
5
  matrix=malloc(zeile*sizeof(int));
6
  if(matrix==NULL){
7
  printf("kein Speicherplatz vorhanden"); nl
8
  return 0;
9
  }  
10
  
11
  for(i=0; i<zeile; i++){
12
    matrix[i]=malloc(spalte*sizeof(int));
13
    if(matrix[i]==NULL){
14
  printf("kein Speicherplatz vorhanden"); nl
15
  return 0;      
16
    }
17
  }
18
  return matrix;
19
}

>   matrix=malloc(zeile*sizeof(int));


Das ist Murks. matrix ist kein int*, sondern ein int**, also ist hier 
sizeof int nur dann zufälligerweise korrekt, wenn sizeof int == sizeof 
int* ist.

Warum übergibst Du der Funktion den Parameter "matrix"? Was erhoffst Du 
Dir davon?


> #define nl printf("\n");


Gewöhn Dir das gleich wieder ab. Du kannst auch einfach \n an Deine 
Ausgaben anhängen, so, wie es der Rest der Welt auch macht.

von David O. (antimonit)


Lesenswert?

Okay, klingt einleuchtend, aber wie würde es dann korrekt aussehen?
Den Parameter "matrix" übergebe ich weil ich der Matrix Speicher 
zuweisen will.

Ist denn der Rest mit dem "int **matrix"(zum Beispiel bei den 
Funktionen) richtig, oder ist bei mir alles eher zufällig geglückt...für 
bestimmte Werte.

Okay, danke für den Hinweis beim "nl".

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

David O. schrieb:
> Den Parameter "matrix" übergebe ich weil ich der Matrix Speicher
> zuweisen will.

Da Du die Variable mit dem Rückgabewert der Funktion überschreibst, geht 
das gut, aber es ist überflüssig und nutzlos, das als Parameter zu 
übergeben.

Wolltest Du tatsächlich den übergebenen Parameter verändern, müsstest Du 
a) den Rückgabewert der Funktion nicht an matrix zuweisen und b) einen 
Pointer auf matrix übergeben und den innerhalb Deiner Funktion 
dereferenzieren:
1
//aufruf
2
3
int** mm;
4
5
if (!structm(&mm, 3, 4))
6
{
7
  //fehlerbehandlung
8
}
9
10
11
12
13
//Hier bekommt die Matrix die Anzahl der Zeilen und Spalten:
14
int ** structm(int ***matrix, int zeile, int spalte)
15
{
16
  int i;
17
18
  *matrix = malloc(zeile * sizeof (int*));
19
  if (*matrix == NULL)
20
  {
21
    printf("kein Speicherplatz vorhanden\n");
22
    return 0;
23
  }  
24
  
25
  for (i = 0; i < zeile; i++)
26
  {
27
    *matrix[i] = malloc(spalte * sizeof (int));
28
    if (*matrix[i] == NULL)
29
    {
30
      printf("kein Speicherplatz vorhanden\n");
31
      return 0;      
32
    }
33
  }
34
  return *matrix;
35
}

Der Rückgabewert hat hier keinen weiteren Gebrauchswert als daß er im 
Erfolgsfall nicht 0 ist, was beim Aufruf entsprechend ausgewertet werden 
kann. Du könntest die Funktion daher auch irgendeinen anderen Typen als 
int** zurückgeben lassen, ein einfacher int würde reichen, der 0 bzw. 1 
annimmt.

Findest Du nicht auch, daß ein paar Leerzeichen den Code lesbarer 
machen?

von David O. (antimonit)


Lesenswert?

Rufus Τ. F. schrieb:
> Da Du die Variable mit dem Rückgabewert der Funktion überschreibst, geht
> das gut, aber es ist überflüssig und nutzlos, das als Parameter zu
> übergeben.
>
> Wolltest Du tatsächlich den übergebenen Parameter verändern, müsstest Du
> a) den Rückgabewert der Funktion nicht an matrix zuweisen und b) einen
> Pointer auf matrix übergeben und den innerhalb Deiner Funktion
> dereferenzieren:

Ja, danke, das stimmt...

Hab die Korrektur jetzt mal eingefügt(In der Funktion structm), jetzt 
geht allerdings gar nicht mehr, wo also hängts bei mir noch, der Rest 
sieht meiner Meinung nach richtig aus....bzw ich raff es nicht...

Rufus Τ. F. schrieb:
> Findest Du nicht auch, daß ein paar Leerzeichen den Code lesbarer
> machen?

Ja, da ist schon was dran :)

von Rolf M. (rmagnus)


Lesenswert?

Rufus Τ. F. schrieb:
> *matrix = malloc(zeile * sizeof (int*));

Ich würde den Compiler selber den richtigen Typ finden lassen:
1
*matrix = malloc(zeile * sizeof **matrix);

>     *matrix[i] = malloc(spalte * sizeof (int));
>     if (*matrix[i] == NULL)

Das müßte heißen:
1
    (*matrix)[i] = malloc(spalte * sizeof (int));
2
    if ((*matrix)[i] == NULL)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Ich würde den Compiler selber den richtigen Typ finden lassen:

Das ist wartungsfreundlicher. Punkt für Dich.

> Das müßte heißen:

Du hast natürlich auch hier recht.

Alternativ könnte man schreiben

matrix->[i] = malloc(...)

aber das würde vermutlich wieder Leute auf die Barrikaden bringen, die C 
unlesbar finden.

von David O. (antimonit)


Lesenswert?

Danke für die Hinweise, nur stürzt das Programm immer noch direkt nach 
der Eingabe von Zeile und Spalte ab.

von David O. (antimonit)


Lesenswert?

Problem gelöst: Es hätte bei der ersten Allokierung:
1
  matrix=(int **)malloc(zeile*sizeof(int*));
heißen müssen.
Dann funktioniert es für alle Werte.
Großes Dankeschön für die Hilfe und die Hinweise.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Rufus Τ. F. schrieb:
> matrix->[i] = malloc(...)

Gaht das? Ich glaube nicht. Den "->"-Operator kann man in C doch nur auf
einen Struct-Pointer anwenden.

Rufus Τ. F. schrieb:
> aber das würde vermutlich wieder Leute auf die Barrikaden bringen, die C
> unlesbar finden.

Dafür wäre evtl. Folgendes ganz gut geeignet:
1
  i[*matrix] = malloc(...);

Damit spart man sich die runden Klammern in
1
  (*matrix)[i] = malloc(...);

was den Code deutlich kürzer und übersichtlicher macht ;-)

von Rolf M. (rmagnus)


Lesenswert?

Yalu X. schrieb:
> Rufus Τ. F. schrieb:
>> matrix->[i] = malloc(...)
>
> Gaht das? Ich glaube nicht.

Ich auch nicht. a->b ist die Entsprechung von (*a).b. Aber (*matrix).[i] 
ergibt keinen Sinn. Damit ergibt auch matrix->[i] keinen.

von Mikro 7. (mikro77)


Lesenswert?

Yalu X. schrieb:
> Dafür wäre evtl. Folgendes ganz gut geeignet:
>
>
1
>   i[*matrix] = malloc(...);
2
>
>
> was den Code deutlich kürzer und übersichtlicher macht ;-)

Könnte bei denen für Verwirrung sorgen die nicht wissen dass:
a[i] == *(a+i) == *(i+a) == i[a] ist. ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.