# Minimum aus Array bestimmen



## sirhC6 (2. Juli 2007)

Hallo erstmal zusammen....
bin neu hier im Forum und wollte mich erstmal vorstellen... 

komme aus Stuttgart und studiere im ersten Semester Softwaretechnik und Medieninformatik an der FH Esslingen.

Nun zu meinem Problem...für Euch warscheinlich gar kein Problem.
Und zwar will ich einen Array aus 4 Zahlen anlegen. Die vier Zahlen werden vom User über die Tastatur eingegeben. Nun soll mein Programm die kleinste der Zahlen ermitteln und wieder ausgeben. D.h. Nummer der Komponente und deren Wert....

ich komme nicht weiter an der Stelle an der ich den kleinsten Wert bestimmen lassen soll..
wie geht dass?


Danke schon mal im Vorraus für Hilfe.


----------



## RedWing (3. Juli 2007)

Hallo,

schau doch mal:

```
#include <stdio.h>

int main()
{
    int array[] = {12, 132,32,432,-321,321,-32, 1};
    int min, i = 0;

    min = array[0];
    for (; i < sizeof(array) / sizeof(int); i++) {
        if (array[i] < min)
            min = array[i];
    }
    printf("min = %d\n", min);

    return 0;
}
```

Gruß,
RedWing


----------



## LukeS (3. Juli 2007)

Willkommen erstmal!

Es ist eigentlich nicht sehr schwer die kleinste (oder auch die grösste) Zahl aus einem Array herauszufinden.

- eine Variable "min" deklarieren
- nimm die erste und die zweite Zahl aus deinem Array
- vergleiche die zwei Zahlen
- speichere die kleinere in "min"
- nimm die nächste Zahl in deinem Array
- vergleiche sie mit "min"
- ist sie kleiner als "min" speichere sie in "min". Andernfalls verwirf sie.
- verfahre so mit jeder anderen Zahl in deinem Array

Pseudocode:

```
int nArray[4];
int min;

for (i=0; i<4; i++)
{
    nArray[i] = i;  // das Array mit Werten füllen
}

if (nArray[0] < nArray[1])
   min = nArray[0];
else
   min = nArray[1];

for (int j=2; j<4; j++)
{
    if (nArray[j] < min)
        min = nArray[j];
}
```
Es gibt wahrscheinlich effizienteren Code für dieses Problem. Aber wenn dein Array nur vier Elemente enthält, spielt das keine grosse Rolle.

Gruss LukeS


----------



## sirhC6 (3. Juli 2007)

Hallo,

schau doch mal:

```
#include <stdio.h>

int main()
{
    int array[] = {12, 132,32,432,-321,321,-32, 1};
    int min, i = 0;

    min = array[0];
    for (; i < sizeof(array) / sizeof(int); i++) {
        if (array[i] < min)
            min = array[i];
    }
    printf("min = %d\n", min);

    return 0;
```

Ne Frage zu deinem Programm.....
wie kommst du auf die Werte in deinem array[] (12,132,,,,)
Woher weiss ich dass min=array[0] ist? 

Sorry bin noch nicht so fit mit pointern und arrays....


----------



## fluessig (3. Juli 2007)

min = array[0] ist nur die initialisierung und wird dann überschrieben, sobald ein kleinerer Wert gefunden wird. Die Zeile ist eigentlich überflüssig, da die for-Schleife sowieso mit i = 0 beginnt.

Die Werte sind von ihm beliebig gewählt worden, damit er dir ein lauffähiges Beispiel bieten kann. 

Was ich nicht verstehe ist: sizeof(array) / sizeof(int) - was soll das denn?


----------



## Online-Skater (3. Juli 2007)

@fluessig

Der Ausdruck liefert die Größe des Array oder anders gesagt die Anzahl der Arrayelemente.

```
// für Redwings Beispiel
sizeof(array); // array setzt sich aus Datentyp int * 8(Werte) zusammen
sizeof(int);    // Daten typ int besetzt 4 Bytes
// daraus folgt 4Bytes*8 =32Bytes
sizeof(array) / sizeof(int) // 32:4 = 8 ->Werte somit läuft die Schleife dynamisch egal wieviel Werte
```

Hoffe ich hab das so richtig verstanden ;-)


----------



## deepthroat (3. Juli 2007)

Hi.





fluessig hat gesagt.:


> min = array[0] ist nur die initialisierung und wird dann überschrieben, sobald ein kleinerer Wert gefunden wird. Die Zeile ist eigentlich überflüssig, da die for-Schleife sowieso mit i = 0 beginnt.


Nein, die Zeile ist nicht überflüssig, da wenn man sie wegläßt min mit einem zufälligen Wert belegt wird der theoretisch kleiner sein kann als alle anderen Elemente in dem Array. Man könnte höchstens i mit 1 initialisieren.



fluessig hat gesagt.:


> Was ich nicht verstehe ist: sizeof(array) / sizeof(int) - was soll das denn?


Das hat ja Online-Skater schon erklärt. Noch besser ist allerdings wenn man es unabhängig vom Typ der Arrayelemente macht:
	
	
	



```
unsigned length = sizeof(array)/sizeof(array[0]);
```
Dann ist egal, ob da nun int oder float oder irgendwas in dem Array gespeichert wird - es wird immer die Anzahl der Elemente berechnet.

Gruß


----------



## RedWing (3. Juli 2007)

Hallo,


deepthroat hat gesagt.:


> Noch besser ist allerdings wenn man es unabhängig vom Typ der Arrayelemente macht:
> 
> 
> 
> ...



ich denke mittlerweile das in dem Fall die Verwendung eines Makros zur Bestimmung der Größe eines Arrays mehr Sinn macht, da
1. sizeof eh nur bei Elementen Sinn macht die in ihrer "statischen" Größe variieren können (also bei Datentypen auf verschiedenen Architekturen)
2. das Konstrukt IMO nur die Leserlichkeit des Codes verschlechtert
Arrays sind sowieso immer gleich in ihrer Größe, von daher ist die Verwendung eines Makros wahrsch.  leserlicher ...

```
#define ARRAY_SIZE 8
...
  int array[ARRAY_SIZE] = {12, 132,32,432,-321,321,-32, 1};
...
  for (; i < ARRAY_SIZE; i++) {
...
```

Gruß,
RedWing


----------



## sirhC6 (3. Juli 2007)

Also vielen Dank erstmal für Eure Mühe....

ich hab mich jetzt mal an RedWings Methode gehalten, da ich die verstehe....
Ihr dürft nicht vergessen das ich erst im ersten Semester bin und noch nicht all zu viel drauf hab.... 

Vielen Dank nochmal an alle..


----------



## sirhC6 (3. Juli 2007)

kurze Frage noch.......
wie weise ich die vom User eingegebenen Werte dem Array zu? Will nicht jede einzelne Komponente einzeln zuweisen.

```
scanf("%d %d %d %d", &ar[0],&ar[1],&ar[2],&ar[3]);
```
das muss doch eleganter gehen. Wenn mein array aus 100 Komponenten bestehen würde wär das doch ein Unding...


Ach ja ich will auch noch die Array Komponente ausgeben lassen. Wenn ich aber printf(".......%d",ar[i]) ausgeben lasse schreit der mit eine riesen Zahl hin... Ich poste jetzt noch mal meinen ganzen code:


```
#include <stdio.h>
#define ARRAY_SIZE 4

int main (void)
{
	int ar[4];
	int min, i=0;
	
	printf("Bitte 4 Zahlen eingeben:\n");
	scanf("%d %d %d %d",&ar[0],&ar[1],&ar[2],&ar[3]);

	min=ar[0];
	for(;i<sizeof(ar)/sizeof(int);i++)
	{
		if(ar[i]<min)
			min = ar[i];
	}
	printf("Der Kleinste Wert des Arrays ist '%d' und befindet sich in %d.\n",min,ar[i]);
	return 0;
}
```


----------



## deepthroat (3. Juli 2007)

Hi.

1. Bitte verwende für deinen Code die entsprechenden Tags: [c]..[/c] für C -  [code=cpp]...[/code] für C++ usw..

2. Wozu definierst du die ARRAY_SIZE Variable wenn du sie gar nicht benutzt? 



sirhC6 hat gesagt.:


> kurze Frage noch.......
> wie weise ich die vom User eingegebenen Werte dem Array zu? Will nicht jede einzelne Komponente einzeln zuweisen.
> 
> scanf("%d %d %d %d", &ar[0],&ar[1],&ar[2],&ar[3]);
> ...


Das Zauberwort heißt hier Schleife.




sirhC6 hat gesagt.:


> ```
> int ar[4];
> int min, i=0;
> 
> ...


Du solltest dir mal ganz in Ruhe überlegen was bei der Ausführung des Programmes passiert und welchen Wert die Variablen haben. Mach dir am besten eine Tabelle wo du mitschreibst wie sich der Wert der Variablen ändert.

Du meinst ja offensichtlich, dass die Variable i nach der Schleife den Index des Minimums enthält. Der Wert der Variablen i ist aber nicht mehr kleiner als "sizeof(ar)/sizeof(int)", denn sonst wäre die Schleife ja nicht beendet worden.

Wenn dein Array die Größe 4 hat; also 4 Elemente darin gespeichert werden können, welchen Wert hat i dann nach der Schleife? Und ist es in Ordnung dann auf das i-te Element des Arrays mit 
	
	
	



```
ar[i]
```
 zuzugreifen?

Gruß


----------



## sirhC6 (3. Juli 2007)

Bin gerade dabei da nochmal durchzusteigen. 

Aber könntest du mit diese Zeile nochmal für dummies erklären.... bitte:

```
i<sizeof(ar)/sizeof(int)
```


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> Bin gerade dabei da nochmal durchzusteigen.
> 
> Aber könntest du mit diese Zeile nochmal für dummies erklären.... bitte:
> 
> i<sizeof(ar)/sizeof(int)



sizeof ist ein Operator der die Größe in Bytes der übergebenen Variable oder Typs bestimmt.

Nehmen wir an, ar ist ein Array von int und ist folgendermaßen definiert:

```
int ar[8];
```
D.h. ar ist ein Array von 8 Elementen und es können also 8 int's darin gespeichert werden.

Um *einen* int zu Speichern braucht man üblicherweise 4 Byte. Wenn man nun 8 Stück davon speichern will, braucht man....... 32 Byte.

Mit sizeof kann man jetzt den Speicherbedarf von ar bestimmen und auch den Speicherbedarf eines int.

D.h. sizeof(ar) gibt die Gesamtgröße des Arrays zurück und sizeof(int) den Bedarf eines Elementes des Arrays.

Wenn man weiß wie groß das gesamte Array ist, und man auch weiß wie groß ein einzelnes Element ist (alle Elemente sind gleich groß), kann man einfach durch Division die Anzahl der Elemente ermitteln.

Das heißt für das Array ar ergibt sich "sizeof(ar)/sizeof(int)" = 8. Es kommt also immer der Wert heraus, der bei der Definition in den eckigen Klammern angegeben wurde.

Man könnte auch den Wert immer manuell in der Schleife anpassen wenn man die Größe des Arrays bei der Definition ändert, aber das ist ziemlich fehleranfällig weil man es irgendwann doch vergisst.

Ach, und der Vergleich 
	
	
	



```
i < szieof(ar) / sizeof(int)
```
 ist der übliche kleiner als Vergleich.


Gruß


----------



## sirhC6 (3. Juli 2007)

Okay super danke, hab ich verstanden....

dann könnte ich auch schreiben:


```
for(;i<4;i++)
```

und warum wird hier der Startwert nicht gebraucht?

in der Art von:


```
for(i=0;i<4;i++)
```


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> Okay super danke, hab ich verstanden....
> 
> dann könnte ich auch schreiben:
> 
> ...


Ja, da ar als "int ar[4];" in deinem Programm definiert ist.



sirhC6 hat gesagt.:


> und warum wird hier der Startwert nicht gebraucht?


Die Variable i wurde doch bereits bei der Definition initialisiert und hat bereits den Wert 0. (Tabelle machen! )

Ich ziehe es eigentlich immer vor, die Zählvariable auch in der for-Schleife zu initialisieren. Da hat man einen besseren Überblick.

Gruß


----------



## sirhC6 (3. Juli 2007)

D.h. ich könnte am Anfang einfach nur:

```
int ar[4];
int min, i;
```
schreiben und dann später in der for-Schleife den Startwert setzen right?


----------



## sirhC6 (3. Juli 2007)

Okay, soweit habe ich das i verstanden.

ich hänge jetzt noch an 2 Stellen. 

1. Wie kann ich die Array-Komponente ausgeben lassen?
Mir ist jetzt klar das es nicht ar[ i ] ist da ja eventuell dieser Wert schon durch einen anderen ersetzt wurde. Es ist die Komponente die als letztes min geworden ist. Aber die kann ich ja nicht über ar[ min ] ausgeben lassen.

2. Ich weiss immer noch nicht wie ich die eingegebenen Werte an die Komponenten zuweisen kann ohne sie manuell zuzuweisen....


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> D.h. ich könnte am Anfang einfach nur:
> 
> ```
> int ar[4];
> ...


Ja, genau.

Gruß


----------



## sirhC6 (3. Juli 2007)

Hast du noch was zu den zwei Fragen

Wär echt super...


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> Okay, soweit habe ich das i verstanden.


Gut. Dann hat i nach der Schleife also welchen Wert?

Und darf man dann nach der Schleife auf ar[i] zugreifen?


sirhC6 hat gesagt.:


> 1. Wie kann ich die Array-Komponente ausgeben lassen?
> Mir ist jetzt klar das es nicht ar[i] ist da ja eventuell dieser Wert schon durch einen anderen ersetzt wurde. Es ist die Komponente die als letztes min geworden ist. Aber die kann ich ja nicht über ar[min] ausgeben lassen.


Richtig. Da müßte man sich vielleicht jeweils bei Änderung von i merken (bzw. speichern) welchen Wert i da hatte.  Sprich: du brauchst eine weitere Variable, die du vor der Schleife geeignet initialisierst und immer bei einem neuen Minimum entsprechend ändern mußt.



sirhC6 hat gesagt.:


> 2. Ich weiss immer noch nicht wie ich die eingegebenen Werte an die Komponenten zuweisen kann ohne sie manuell zuzuweisen....


Na, eine Schleife ist doch nur eine Abkürzung für sehr viel Schreibarbeit. Deine Anweisung könntest du ja auch so schreiben


```
scanf("%d", &a[0]);
scanf("%d", &a[1]);
scanf("%d", &a[2]);
scanf("%d", &a[3]);
/* ... usw. */
```
Da fällt sofort auf, das sich jede Zeile nur an einer einzigen Stelle von den anderen unterscheidet. Das ist doch eine tolle Gelegenheit dafür eine Schleife zu schreiben.

Gruß


----------



## Online-Skater (3. Juli 2007)

Mach dir wikrlich mal eine Tabelle wie es deepthroat sagt da kann man sehr viel an Information dazugewinnen, da man dann versteht was der Code macht.
Wenn der User 100 Einträge an das Array machen soll dann gibt es keine Vereinfachung des Problems, bei solchen Programmen arbeite ich immer mit Zufallswerten also schreibe Zufallswerte in dein Array.


```
srand(time(0));
for (int i = 0; i < Arraylaenge; i++)
   ar[i] = rand() % 100;
```

mfg.


----------



## sirhC6 (3. Juli 2007)

Okay.... ich glaube ich habs jetzt...
schau dir mal an ob das so okay ist. Beim Testlauf hatte ich den Anschein als wär alles okay.


```
int main (void)
{
	int ar[4];											/*array besteht aus 4 Komponenten*/
	int min, i ,nm;
	
	printf("Bitte 4 Zahlen eingeben:\n");
	scanf("%d %d %d %d",&ar[0],&ar[1],&ar[2],&ar[3]);	/*Zuweisen der eingegebenen Werte an das Array*/

	min=ar[0];			/*initialisierung. wird überschrieben sobald kleinerer Wert gefunden wird*/
			
	for(i=0;i<sizeof(ar)/sizeof(int);i++)	/*siehe untere Erklärung*/
	{
		if(ar[i]<min)
			nm=i;

		if(ar[i]<min)	/*wenn array i kleiner min ist, wird arry i zum neuen minimum*/
			min = ar[i];
	}
	printf("Der Kleinste Wert des Arrays ist '%d' und befindet sich in ar[%d].\n",min,nm);
	return 0;
}
```


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> Okay.... ich glaube ich habs jetzt...
> schau dir mal an ob das so okay ist. Beim Testlauf hatte ich den Anschein als wär alles okay.


Ja. Es ist fast OK. Aber bevor ich dir sage was noch falsch ist - Preisfrage: welchen Wert hat i nach der Schleife? (und nicht schummeln)

Gruß


----------



## sirhC6 (3. Juli 2007)

Kann es sein dass i immer 4 ist da meine Schleife ja ++1 bis 4 läuft?


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> Kann es sein dass i immer 4 ist da meine Schleife ja ++1 bis 4 läuft?


Ja. Richtig. 

Und deswegen ist es auch nicht OK wenn man auf ar[ i ] ( entspricht ar[4] ) zugreift, denn dieses Element gibt es in dem Array nicht! Die Array Elemente sind "numeriert" von 0 bis 3.

Nun zum Fehler:

Du hast in deinem Code vergessen die Variable nm zu initialisieren. D.h. diese enthält einen zufälligen Wert (Tabelle machen!). Wenn sich nun das Minimum bei ar[0] befindet (also alle anderen Elemente sind >= ar[0]) wird die Variable nm in der Schleife nicht geändert und das ist dann nicht korrekt.

Du setzt ja im Grunde am Anfang min = ar[0]. Dann mußt du da auch den entsprechenden Index speichern.

Dann kann man natürlich auch meist noch etwas vereinfachen bzw. optimieren:

```
int i, nm;

min = ar[0]; nm = 0;

for (i = 1; i < sizeof(ar)/sizeof(int); ++i) {
  if (ar[i] < min) {
    nm = i;
    min = ar[i];
  }
}
```
Gruß


----------



## sirhC6 (3. Juli 2007)

Ahhhhhh...........alles klar.
Danke dir tausend mal.

Um nochmal auf die Schleife für mein scanf zurück zu kommen. Ich habe absolut keine Idee wie ich das realisieren könnte...


----------



## deepthroat (3. Juli 2007)

sirhC6 hat gesagt.:


> Um nochmal auf die Schleife für mein scanf zurück zu kommen. Ich habe absolut keine Idee wie ich das realisieren könnte...


Du mußt doch nur die sich ändernde Komponente jeder Zeile durch eine Variable ersetzen und eine Schleife drumrumbauen:





deepthroat hat gesagt.:


> ```
> scanf("%d", &a[0]);
> scanf("%d", &a[1]);
> scanf("%d", &a[2]);
> ...




```
int j;
for (j = 0; j < sizeof(ar)/sizeof(int); ++j) {
  scanf("%d", &ar[j]);
}
```


----------



## sirhC6 (3. Juli 2007)

Ja.........klingt logisch...
habs nun so in mein i eingegeben. Der will aber nicht. (Stack around the variable ar was corrupted.

Hier nochmal der komplette Code:


```
#include <stdio.h>
int main (void)
{
	int ar[4];											/*array besteht aus 4 Komponenten*/
	int j,min,i,nm;
	
	printf("Bitte 4 Zahlen eingeben:\n");
	for(j=0;j<sizeof(ar)/sizeof(int);++j);
	{	
		scanf("%d",&ar[j]);
	}

	min=ar[0];			/*initialisierung. wird überschrieben sobald kleinerer Wert gefunden wird*/
	nm=0;		
	for(i=0;i<sizeof(ar)/sizeof(int);i++)	/*siehe untere Erklärung*/
	{
		if(ar[i]<min)	/*wenn array i kleiner min ist, wird arry i zum neuen minimum*/
			min = ar[i];
			nm=i;
	}
	printf("Der Kleinste Wert des Arrays ist '%d' und befindet sich in ar[%d].\n",min,nm);
	return 0;
}
```

warum eingentlich ++j und nicht j++ Ist das egal? Funktioniert auf beide Weisen nicht...


----------



## deepthroat (3. Juli 2007)

Ja, ist ein schöner Anfängerfehler - da muss jeder durch. 

Du hast dort die Schleife mit dem Semikolon bereits abgeschlossen. Das Semikolon steht für die leere Anweisung; d.h. in der Schleife passiert nichts. Allerdings wird j natürlich hochgezählt - bis j gleich 4 ist. Nach der Schleife, innerhalb der eckigen Klammern, wird versucht an die Speicherstelle von ar[4] etwas zu speichern, aber die Speicherstelle ar[4] gehört gar nicht mehr zum Array dazu!



sirhC6 hat gesagt.:


> warum eingentlich ++j und nicht j++ Ist das egal? Funktioniert auf beide Weisen nicht...


Das eine ist der Präinkrementoperator, das andere der Postinkrementoperator.

Natürlich gibt's einen Unterschied:
	
	
	



```
int a = 5, b, c;

b = ++a;
c = a++;
```
Nachdem dieser Code ausgeführt wurde ist a = 7, b = 6, c = 6.

Das liegt daran, das ++a (der Präinkrementoperator) im Grunde erst den Wert von a erhöht und dann den neuen Wert zurückgibt. Während a++ (Postinkrementoperator) den Wert von a auch erhöht aber noch den alten Wert von a zurückgibt - also als wenn a erst hinterher erhöht worden wäre.

Wenn du den Rückgabewert des Operators nicht verwendest (so wie in der for-Schleife), ist es egal welchen Operator du nimmst.

Gruß

\edit: Dann hab ich grad noch einen anderen Fehler bemerkt (du mußt schon richtig abschreiben ). Man darf hinter eine Schleife und eine if-Anweisung nur eine Anweisung schreiben. 
	
	
	



```
#
if(ar[i]<min)   /*wenn array i kleiner min ist, wird arry i zum neuen minimum*/
            min = ar[i];
            nm=i;
```
Wenn du das so schreibst, gilt das if nur für die erste Anweisung, nämlich für 
	
	
	



```
min = ar[i].
```
 In diesem Fall muß man die Anweisungen in einen Block zusammenfassen:
	
	
	



```
#
if(ar[i]<min) {  /*wenn array i kleiner min ist, wird arry i zum neuen minimum*/
            min = ar[i];
            nm=i;
}
```


----------



## sirhC6 (3. Juli 2007)

Danke dir vielmals.... jetzt t alles.... und was noch wichtiger ist: Jetzt hab ich alles verstanden.

Bist mein Held


----------

