# Anfänger Problem mit C



## Nico1989 (13. Oktober 2013)

Hi Community!

Ich bin ganz neu auf dem Board da ich bis vor kurzem noch nichts mit C oder anderen Programmiersprachen zu tun hatte. Nun aber schon  und wie es in diesem Bereich üblich ist bereitet mir mein erstes wirkliches Problem Kopfzerbrechen 

Also: Die Aufgabenstellung laut meinem Lehrbuch ist, das ich ein Wechselgeld-Programm schreiben soll.
Es soll einen Wert wie 5,55 in die Minimalste kombination aus Münzen aufteilen.
5,55 => 2 * 2Euro, 1 * 1 Euro, 1 * 50 Cent, 1 * 5 Cent

Meine Lösungsidee:
Ich nehme den eingegebenen Wert und ziehe davon immer die höchst mögliche Münze bis man unter null fällt dann probiert man es mit der nächsten usw.
5,55 - 2 - 2 - 1 - 0,50 - 5

Code habe ich dazu auch schon aber er startet einfach nicht und ich versteh es bei gott nicht warum :O


```
#include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char* argv[])
    {
      int i = 0;
      int j = 0;
      float cm = atof(argv[1]);
      float values[6]={2.0, 1.0, 0.50, 0.20, 0.10, 0.05, 0.02, 0.01};  
      int numberOf[6]={0,0,0,0,0,0,0};
      while (cm != 0);
      {
        if (cm >= values[i])
        {
          cm = cm - values[i];
          numberOf[j] = numberOf[j] + 1;
        }
        else
        {
          i = i+1;
          j = j+1;
        }    
      }
      printf("Erg = %f/n", numberOf[0]);
    }
```

Die Ausgabe ist noch nicht komplett ich wollte damit nur testen aber aus dem testen ist ja leider nichts geworden :/

Ich bin Dankbar für jede Hilfe!

LG Nico


----------



## sheel (13. Oktober 2013)

Hi und Willkommen bei tutorials.de 

deine theoretische Lösungsidee ist so ok.
Also solang die höchstmögliche Münze abziehen, bis nichts mehr geht.
(Zumindest, wenn man solche Münzen hat,
wie es eben Euromünzen gibt, funktioniert das so in jedem Fall.
Falls es auch 30-cent-Münzen etc. gäbe wirds kompilizierter, aber das ist hier ja unwichtig)

Beim Code ist Nachbesserungsbedarf, aber "einfach nicht starten" sollte jedenfalls nicht passieren.

Was passiert genau?
Windows/Linux/...? Welche IDE, welcher Compiler?
Was hast du genau gemacht und was ist die Reaktion darauf?
Irgendwelche Fehler oder Warnungen (welche)?


----------



## Nico1989 (13. Oktober 2013)

Also ich Code unter Ubuntu mit dem gcc compiler als editor hab ich geany, Fehler treten beim Compilen garkeine auf, nach eingabe der Parameter startet es aber allen anschein nach hängt es danach in einer Dauerschleife fest...oder was ich immer, der Curser bleibt einfach stehen _ und blinkt bis ich mit strg+c abbreche.


----------



## sheel (13. Oktober 2013)

Dann startet es ja doch 
Und ja, du hast eine Endlosschleife und noch einige andere Probleme:

Ich fang mal ganz oben an, mit den int´s i und j.
Die verwendest du zum Zugriff auf die beiden Arrays. Gut.
Aber, du brauchst ja immer nur den selben Index.
Zum values[0] gehört numberOf[0], values[1] gehört zu numberOf[1] usw.
Nicht wirklich ein Fehler, aber da würde ein einzelnes int i reichen

Die Zeile mit "float cm":
Was tust du, wenn der Benutzer dem Programm keinen Parameter mitgegeben hat
oder wenn der Parameter keine Zahl ist, sondern zB. "hallo"?
So etwas sicherer:

```
float cm;
if(argc != 2 || !sscanf(argv[1], "%f", &cm))
{
    printf("Bitte nur mit einer Zahl als Parameter aufrufen\n");
    return;
}
```
Detailerklärung dazu gibts bei Bedarf gerne.

Dann das Array values:
Du schreibst [6], in den {} danach sind aber 8 Werte.
(da sollte der gcc eigentlich jammern. Versuch beim Kompilieren die Option "-Wall")
Also entweder [8], oder in dem Fall kann man auch einfach [] nehmen.
Dann wird die Anzahl der Zahlen in {} genommen.

numberOf sollte auch 8 sein statt 6, und in den {} stehen nur 7 Nuller statt 8.
(Zugriffe über die Arraygrenze raus sind nicht nur zu vermeiden,
um schöneren Code oder sowas zu haben,
sondern können ziemlich gravierende und schwer findbare Probleme machen.)

Die while-Schleife: Nach der Bedingung hast du ein ;
Das ist eine nette Falle in C, es ist sprachlich komplett in Ordnung, aber selten das, was man will.
Der ; bewirkt nämlich, dass der ganze Schleifenbereich genau dort wieder aus ist.
Der Codeblock in {} darunter steht nur so da, hat mit der Schleife nichts mehr zu tun.
Also, solange cm nicht 0 ist, tu gar nichts.
Und wenn cm am Anfang nicht 0 ist wirds durch "Gar nichts" auch nie 0 werden
-> Endlosschleife.
Weg mit dem ;


Der Rest schaut nicht schlecht aus.
Am Schluss vllt. nicht nur numberOf[0], sondern alle numberOf´s ausgeben.


----------



## Nico1989 (13. Oktober 2013)

Sehr verständlich und brauchbar erklärt besten Dank ! Ich versuchs gleich aus ! 
Du solltest unterrichten


----------



## Nico1989 (13. Oktober 2013)

sodale hab deine verbesserungen nachgetragen alderdings bekomme ich als ergebnis -nan kann es sein das hierbei probleme beim rechnen mit dem Datentyp "float" gibt ? ich weiß leider noch nicht wie sich der intern verhält aber könnte ja möglicherweise ein rundungsfehler oder dergleichen entstehen, oder lieg ich da falsch ?


----------



## sheel (13. Oktober 2013)

Ah, das hab ich oben übersehen.

Es kann Rundungsfehler geben, ja, aber bei so einfachen Beträgen (zwei Kommastellen)
sollte das nicht passieren. Das Ergebnis ist dann außerdem "nur" eine leicht falsche Zahl, nicht Nan.

Das Problem ist, dass du ein int mit %f ausgeben willst.
%f ist für float, aber valueOf besteht ja aus int.
%d (oder auch %i) also.


----------



## Nico1989 (13. Oktober 2013)

Danke soweit sogut, doch jetzt ist ein weiteres problem aufgetaucht 
Diese Werte Funktionieren: 0,07 , 0,50 3,50 usw. aber sobald zwischen räume drinnen sind wie sie zb. bei 2,02 wären funktioniert es nicht also schätz ich mal das es bei dem weiterzählen irgendwo noch hackt. Doch ich komm einfach nicht drauf ich bin es jetzt mehrmals am zettel durchgegangen.


----------



## sheel (13. Oktober 2013)

Zeig deinen aktuellen Code nochmal


----------



## Nico1989 (13. Oktober 2013)

Die Ausgabe und die Parameter Abfrage am anfang gehört natürlich noch geändert. Ich sorge mich momentan um die funktionalität noch am meißten 

```
#include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char* argv[])
    {
      int i = 0;
      float cm = atof(argv[1]);
      float values[]={2.0, 1.0, 0.50, 0.20, 0.10, 0.05, 0.02, 0.01};  
      int numberOf[]={0,0,0,0,0,0,0,0};
      while (cm != 0)
      {
      printf("Erg cm = %d/n",cm);
        if (cm >= values[i])
        {
          cm = cm - values[i];
          numberOf[i] = numberOf[i] + 1;
        }
        else
        {
          i = i+1;
        }    
      }
      printf("Erg = %d/n", numberOf[0]);
      printf("Erg = %d/n", numberOf[1]);
      printf("Erg = %d/n", numberOf[2]);
      printf("Erg = %d/n", numberOf[3]);
      printf("Erg = %d/n", numberOf[4]);
      printf("Erg = %d/n", numberOf[5]);
      printf("Erg = %d/n", numberOf[6]);
      printf("Erg = %d/n", numberOf[7]);
    }
```


----------



## Caligulaminus (13. Oktober 2013)

Das liegt an den floats. Die können sowas wie 0.1 nicht exakt darstellen. Daher wird dein cm auch nicht genau Null.
Es wundert mich eigentlich, daß das nicht explodiert.
Für Geldbeträge immer ganzzahlige Variablen(z.B. int) nehmen. Du rechnest dann einfach in Cent und paßt lediglich die Ausgabe an.


----------



## sheel (13. Oktober 2013)

(Jup, auch grad gemerkt, das sogar bei den einfachen Beträgen Rundungsfehler auftreten )

Also, den argv-Parameter kannst du noch als float nehmen, aber dann *100
und mit Cent-int weitermachen...


----------



## Nico1989 (13. Oktober 2013)

jop danke an euch 2 funktioniert jetzt, bin auch relativ zufrieden mit den testfällen einer ist jedoch aufgetaucht beim das prog wieder in einer endlos schleife hengt und zwar bei 9,89 bei 1,89 oder 0,89 funktioniert es wiederrum ...komisch irgendwie


----------



## Nico1989 (13. Oktober 2013)

Hier mein aktueller Code 
Nochmals danke für die Mühe! Is echtn geiles Board hier 

```
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char* argv[])
{
  float cm = atof(argv[1]);    
  if(argc != 2 || !sscanf(argv[1], "%f", &cm))
  {
          printf("Please only use numbers als params \n");
          return;
  }    
  int i = 0;
  int values[]={200, 100, 50, 20, 10, 5, 2, 1};  
  int numberOf[]={0,0,0,0,0,0,0,0};
  cm = cm * 100;
  while (cm != 0)
  {
    if (cm >= values[i])
    {
      cm = cm - values[i];
      numberOf[i] = numberOf[i] + 1;
    }
    else
    {
      i = i+1;
    }    
  }
  printf(" 2 Euro x %d\n", numberOf[0]);
  printf(" 1 Euro x %d\n", numberOf[1]);
  printf("50 Cent x %d\n", numberOf[2]);
  printf("20 Cent x %d\n", numberOf[3]);
  printf("10 Cent x %d\n", numberOf[4]);
  printf(" 5 Cent x %d\n", numberOf[5]);
  printf(" 2 Cent x %d\n", numberOf[6]);
  printf(" 1 Cent x %d\n", numberOf[7]);
```


----------



## sheel (13. Oktober 2013)

Du rechnest ja noch immer mit dem float cm 
Mach statt

```
float cm = atof(argv[1]);    
  if(argc != 2 || !sscanf(argv[1], "%f", &cm))
  {
          printf("Please only use numbers als params \n");
          return;
  }
```
das:

```
float cmf = atof(argv[1]);    
  if(argc != 2 || !sscanf(argv[1], "%f", &cmf) || cmf < 0.0)
  {
          printf("Please only a number as params \n");
          return;
  }   
  int cm = (int)(cmf * 100.0);
```
und dafür weiter unten die Zeile mit *100 weg.
(Hab auch noch eine weitere Prüfung gemacht, ob die Zahl positiv ist)

Übrigens, die vielen printf am Schluss passen doch gut zu einer Schleife


----------



## Nico1989 (13. Oktober 2013)

perfekt danke ! jetzt mich zu 100% zufrieden damit  dann mach ich mich mal ans nächste Beispiel


----------

