Hilfe bei eingabe in C (mit dynamischer Speicherreservierung)



  • also ich hab jetzt von der abgeänderten Version gesprochen, in der ich "von Hand" was eingeben kann:
    erstmal ist "rueckgabe" = 2, dann geht es wohl auch wieder in die Schleife rein, lässt mich aber nichts mehr eingeben, sondern liefert sofort als "rueckgabe" 0 zurück und verlässt die schleife.
    stimmt doch, oder? aber wieso wartet es nciht, bis ich wieder was eingegeben hab?



  • Weil das '\n' noch im Puffer ist.
    Lies die Zeile mit fgets ein und werte diese dann mit scanf aus. So kannst du sicher sein immer eine Zeile neue zu lesen.



  • Mach bei fscanf einfach ein Leerzeichen ganz ans Ende des Format Strings, dann läufts.



  • Ok, also das Problem scheint ja wirklich zu sein, das die Zeile in meiner Datei nicht weiter gewechselt wird.
    ich habs mal so versucht. fgets() kannte ich vorher halt noch nicht, deswegen brauch ich da wohl auch noch ein wenig Hilfe.

    Hier mein neues Programm:

    int main(void)
    {
    
    	char *zeile; //NEU
    	int i=0, rueckgabe=0;
    	float summe=0;
    	Daten *Konto;
    	FILE *fp;
    
    	fp=fopen("Konto.txt", "r");
    
    	if(fp == NULL)	//Test, ob Datei überhaupt vorhanden ist
    	{
    		printf("Datei nicht vorhanden!\n"); return;
    	}
    
    	fgets(zeile, 1000, fp); //NEU
    
    	Konto = (Daten *)malloc(sizeof(Daten));
    
    	rueckgabe = scanf(zeile, "Name: %s Kontostand: %f", &Konto[i].Name, &Konto[i].Haben);
    
    	printf("%f   %d \n", Konto[i].Haben, rueckgabe); //(zur Kontrolle); Bei der Ausgabe MUSS ein Stern vor den Zeiger --> "Name" (bei Eingabe MUSS die Adresse übergeben werden)!
    
    	while(rueckgabe==2)
    	{
    		i++;
    		fgets(zeile ,1000 ,fp); //NEU
    
    		Konto = (Daten *)realloc(Konto, (i+1)*sizeof(Daten));
    
    		rueckgabe = scanf(zeile, "Name: %s Kontostand: %f", &Konto[i].Name, &Konto[i].Haben);
    		printf("%f   %d \n", Konto[i].Haben, rueckgabe);
    
    	}
    
    	printf("i= %d \n",i);
    
    	for(;i>=0;i--)
    	{
    		summe = summe + Konto[i].Haben;
    	}
    
    	printf("Gesamtkontostand: %f" , summe);
    }
    

    Der Teil vor der while Schleife funktioniert wohl schonmal. Nachdem ich fgets() auch in der while-Schleife geändert habe, gibt eclipse beim starten des Porgramms (Compiliert wird ohne Fehlermeldung) folgende Fehlermeldung aus (in rot):

    6 [main] test_C-Projekt 4972 exception::handle: Exception: STATUS_ACCESS_VIOLATION
       1197 [main] test_C-Projekt 4972 open_stackdumpfile: Dumping stack trace to test_C-Projekt.exe.stackdump
    

    Habe ich fgets richtig angewandt? oder müsste es richtig heißen:

    fgets(zeile+i ,1000 ,fp)
    

    ?
    Und wie funktioniert hier genau der Zeilewechsel? "Merkt" sich das Programm, dass beim einlesen der ersten Zeile am ende ein '/n' stand? Oder muss ich noch was tun, damit in der Schleife jedesmal die Zeile gewechselt wird?



  • sorry, ich hab natürlich den Teil vor der main-Fkt so wie vorher:

    #include<stdlib.h>
    #include<stdio.h>
    
    typedef struct
    	{
    		char Name[20];
    		float Haben;
    	}Daten;
    
    int main(void)
    {
    ...
    

    daran lag die Fehlermeldung also nicht



  • Du musst Speicher für "Zeile" reservieren oder ein Array draus machen. zB:

    char buf[200];
    fgets(buf, sizeof(buf), stdin);
    

    "Merkt" sich das Programm, dass beim einlesen der ersten Zeile am ende ein '/n' stand?

    1. fgets() liest bis einschließlich '\n'
    2. Der filestream merkt sich bis wohin du gelesen hast.

    3.

    cooky451 schrieb:

    Mach bei fscanf einfach ein Leerzeichen ganz ans Ende des Format Strings, dann läufts.



  • @ cooky451

    hey vielen dank, du bist ja klasse! Das mit den Leerzeichen funktioniert 🙂
    Aber woran liegt das?



  • ok, ich glaube ich kanns selbst erklären:
    Ohne Leerzeichen hört das Programm nach der letzten Variable auf zu lesen. Mit Leerzeichen liest es auch das '\n' mit, gell?

    Mit fgets() bekomm ichs nicht hin. Ist aber nicht so schlimm, hätte mich nur mal interessiert, da hier so viele meinen, das es damit besser wäre.



  • Ehrlich gesagt kann ich mir selbst nicht so ganz erklären warum es mit einem Leerzeichen funktioniert, das war nur so eine Ahnung. Eigentlich sollte scanf eh alle '\n' ignorieren. Vielleicht weiß hier ja jemand mehr, ich nutze eigentlich auch immer nur fgets..

    Mit fgets musst du dann sscanf benutzen. In etwa so:

    typedef struct
    {
      char name[20];
      float credit;
    } ACC_DATA;
    
    int main()
    {
      int i, retval = 2;
      float amount = 0;
      ACC_DATA *account = 0;
      FILE *file;
    
      file = fopen("test2.txt", "r");
      if(!file)
        exit(-1);
    
      for (i = 0; retval == 2; ++i)
      {
        char buf[0x100];
        if (!fgets(buf, sizeof(buf), file))
          break;
        account = (ACC_DATA*)realloc(account, (i + 1) * sizeof(*account));
        if (!account)
          exit(-2);
        retval = sscanf(buf, "Name: %19s Kontostand: %f", account[i].name, &account[i].credit);
        printf("Name: %s; Guthaben: %f\n", account[i].name, account[i].credit);
      }
    
      fclose(file);
    
      for(;i>=0;i--)
        amount+= account[i].credit;
    
      printf("Gesamtkontostand: %f\n", amount);
    
      free(account);
      system("pause");
      return 0;
    }
    


  • kratob schrieb:

    Hier mein neues Programm:

    Immer noch Müll. Du hast die Hinweise nicht gelesen/umgesetzt.
    Das wird heute nichts mehr mit dir.



  • Wo ist das Prob, das Programm läuft doch jetzt, dank dem Hinweis von cooky451.

    Ich glaube dir ja, das es vielleicht auch anders und einfacher geht, aber ich kann es nunmal nur so machen, wie ich es bis jetzt im Studium gelernt hab...
    Kanns immer noch nicht glauben, dass ich seit Freitag da rummach und am Ende lag es an einem Leerzeichen... ^^



  • Das Leerzeichen in scanf steht für sog. 'Whitespace' Das sind Leerzeichen, Tabulatoren und Zeilenvorschübe.
    Möglicherweise steht in der Datei nach dem Kontostand noch ein Leerzeichen.



  • nein, hab ich schon getested


Anmelden zum Antworten