string in mehrere variablen zerlegen (in C)



  • Hallo alle miteinander. Ich habe mich jetzt mal in eurem Forum registriert, weil mir viele Beiträge hier, schon sehr geholfen haben. Darum hoffe ich, das ihr mir nun bei einem (für mich) speziellen Problem helfen könnt. 🙂

    Ich bin im ersten Semester für Wirtschafts-Info, und tüftle nun an meiner ersten Belegarbeit. Hier stoße ich auf folgendes Problem:

    Das Programm solle einen String-Eingabe des Nutzers auswerten. So gibt der Nutzer zb "kaufen auto 50" ein. Nun muss das Programm diesen String auswerten. Und in einem struct den Besitz des jeweiligen User`s um 50 Autos erhöhen.

    Mein Problem ist, das ich den String nicht effektiv auslesen kann. Ich habe es über eine while-Schleife versucht, welche eine if-Bedingungen, in Verbindung mit scanf, nach "kaufen" enthält. Wenn also das erste Wort "kaufen" ist. So wird if betreten. Darauf folgen 2 weiter scanf, welche "auto" und "50" auslesen.

    Das funktioniert auch ganz gut. Aber leider nur, wenn es auch genau so eingegeben wird, wie man es machen sollte. xD

    Wenn jedoch ein Nutzer ein Wort zu wenig angibt. So komme ich natürlich zu dem Problem, das eine weiter Variable erwartet wird. Jedoch wäre das für den Nutzer unverständlich, bzw gar feindlich.

    Am liebsten wäre mir eine Funktion, als welcher ich die Nutzereingabe übergeben kann. Und die mir dann 3 Einzel-Variablen zurück gibt. Mit denen ich weiterarbeiten kann.

    Wenn ich die Sache jetzt richtig verstanden habe, so stehe ich unter anderem vor folgendem Problem.

    1. strings werden doch in C als Zeiger übergeben. Was dazu führt, jede Änderung (zb durch strtok) auch den Original-Eingabe-String des Nutzers verändert.
    2. Ich müsste jede Einzel-Token einem andern separaten String zuweisen. Um sie später auch unabhängig von einander verwenden zu können.

    -------------------------------------------

    Mir ist bewusst, das mein Problem auf euch simple, oder gar kindisch wirkt. Darum bin ich auch für jeden konstruktiven und netten Tip dankbar.

    thx for reading - lg Tarulis



  • warum benutzt du nicht strtok und machst 3 neue strings?
    oder du machst einfach 3 benutzer abfragen und hast die strings gleich getrennt?

    ich bin mir nicht sicher ob ich das problem verstanden habe.



  • nomis86 schrieb:

    warum benutzt du nicht strtok und machst 3 neue strings?
    Kannst du das an einem Bsp zeigen.

    Ich kenne es nur auf diese Art:

    int strtoken(char *str, char *token[])
    {
      int i = 0;
    
      token[0] = strtok(str, " ");
    
      while ( token[i] ) {
        i++;
        token[i] = strtok(NULL, " ");
      }
      return ( i );
    }
    

    Meinst du das so hier? Dem nach würde man einen string an die Funktion übergeben. Dieser wird dann zerlegt. Und in einen "arry" aus sting`s gelegt.

    Ergo müsste ich dann nach der Funktion mit token[1], token[2], token[3], ... die einzelnen Inhalten ansprechen können.

    Oder täusche ich mich da?

    Wie gesagt. Klingt für euch sicher simpel. Aber ich hab irgendwie nen Knoten im Kopf. 😞

    oder du machst einfach 3 benutzer abfragen und hast die strings gleich getrennt?

    Darf ich leider nicht. 😞



  • Ich habe deine Aufgabenstellung so verstanden

    char w0[256], w2[256], w2[256];
    scanf("%255s %255s %255s", w0, w1, w2);
    // Drei Variablen mit den strings
    
    struct user nutzer;
    if (!strcmp("kaufen", w0)) {
        if (!strcmp("auto", w1)) {
            nutzer.autos += atoi(s2);
        }
    }
    

    Aber dann verstehe ich dein Problem nicht.
    Im Prinzip brauchst du gar kein strtok .



  • Leider stoße ich dabei auf Probleme wenn der Nutzer, mehr oder weniger Variablen angibt.

    lg Tarulis



  • Wenn gibt es einen Möglichkeit nachfolgende Zeichen in einer String zu löschen? Hier sollte jetzt zb jemand "anmelden 1" eingeben. Und in dem Falle funktioniert auch alles wie es soll. Nur wenn der Nutzer zb "anmelden 1 2" eingibt, kommt es zum Problem. Genauso wie es ungünstig ist wenn jemand nur "anmelden" eingibt.

    printf("\n>");
    	scanf("%s",&eingabemain);
    
    while (login == 0){
    ///+++++++++++++++++++++++++++ ANMELDEN +++++++++++++++++++++++++++
    	if (((strcmp(eingabemain, "anmelden") == 0)) && (anmelden < 100)){
    		anmelden++;
    		login = 1;
    		printf("\nAnmeldung: erfolgreicht");
    		printf("\nIhre Kundenmummer: %d\n", anmelden);
    		fflush(stdin);
    
    	}
    
    	if (((strcmp(eingabemain, "anmelden") == 0)) && (anmelden >= 100)){
    		printf("\nANMELDUNG FEHLGESCHLAGEN");
    		printf("\nDie maximale Kundenzahl betraegt 100\n");
    	}
    

    Ich habe gelesen das fflush(stdin) alles Nachfolgende löscht. Doch zum einen funktioniert das nicht wirklich. (Zumindest nicht so, wie es es verwendet habe) Und zum anderen würde es nicht das Problem mit der kürzeren Eingaben (nur "anmelden") beheben. ganz davon ab, das ich gelesen haben, das es unter Linux nicht immer funktionieren soll.



  • Du kannst auch mit fgets die ganze Zeile als String einlesen und dann mit sscanf den String auslesen (beachte das doppel-S bei sscanf).



  • scanf schrieb:

    Ich habe deine Aufgabenstellung so verstanden

    char w0[256], w2[256], w2[256];
    scanf("%255s %255s %255s", w0, w1, w2);
    // Drei Variablen mit den strings
    
    struct user nutzer;
    if (!strcmp("kaufen", w0)) {
        if (!strcmp("auto", w1)) {
            nutzer.autos += atoi(s2);
        }
    }
    

    Aber dann verstehe ich dein Problem nicht.
    Im Prinzip brauchst du gar kein strtok .

    Im Prinzip richtig, wenn auch falsch.

    char w0[256], w1[256], w2[256];
    if( 3==scanf("%255s%255s%255s", w0, w1, w2) )
      puts("Eingabe ok");
    else
      puts("Eingabe falsch");
    

    oder gleich mit einer gut wiederverwendbaren Struktur:

    typedef struct {
    char a[100],b[100]; int c; } MeinTyp;
    ...
    MeinTyp meinTyp;
    ...
    if( 3==scanf("%255s%255s%d", meinTyp.a, meinTyp.b, &meinTyp.c) )
      printf("Eingabe ok:\n%s:%s:%d",meinTyp.a,meinTyp.b,meinTyp.c);
    else
      puts("Eingabe falsch");
    

    Alles wie du schon richtig vermutest absolute C Grundlagen.



  • char eingabe1[10] = "E1 leer";
    char eingabe2[10] = "E2 leer";
    char eingabe3[10] = "E3 leer";
    
    	printf("\n>");{
    
    	if( 3==scanf("%s%s%s", &eingabe1, &eingabe2, &eingabe3) )
    		printf("Eingabe ok:\n%s:%s:%s\n\n",eingabe1,eingabe2,eingabe3);
    	else
    		puts("Eingabe falsch");
    

    Wenn ich jetzt zb "a b c" eingeben, so wird wie gewollte "a🅱c" zurück gegeben. Wenn man aber nur "a b" eingibt, so wartet das Programm, bis man den die dritte Variable eintippt. Weil das aber der Nutzer an dieser Stelle nich wissen kann. Sollte stattdessen aber, am besten dort schon die Meldung "Eingabe falsch" ausgeben. Das Selbe solle auch für den Fall "a b c d" gelten.

    Ich möchte einfach sicher gehen, das nur Nutzereingaben verarbeitet werden, welche auch im späteren Verlauf wirklich zu verarbeiten gehen.

    Glaube fast mein Problem ist für euch schon zu einfach, als das ihr euch vorstellen könnte, das Einer dranhängen bleibt.

    lg Tarulis



  • Du hast das Eingabeverhalten in C nicht verstanden. Eingabefunktionen der Standardbibliothek, zu denen auch scanf gehört, warten IMMER bis der Anwender '\n' eingibt und verarbeiten dann den Eingabestream entsprechend der Vorgaben.
    Außerdem hast du das Beispiel nicht korrekt abgetippt und somit wahrscheinlich auch nicht verstanden. & ist zuviel und die Stringlängengrenze hast du auch ignoriert. So wird das nichts.


  • Mod

    Wutz schrieb:

    Du hast das Eingabeverhalten in C nicht verstanden. Eingabefunktionen der Standardbibliothek, zu denen auch scanf gehört, warten IMMER bis der Anwender '\n' eingibt und verarbeiten dann den Eingabestream entsprechend der Vorgaben.

    Naja... Das beschreibt zwar ziemlich genau was in der Praxis passiert, aber eigentlich sehen die Funktionen der Standardbibliothek nur eine Reihe von Zeichen die irgendwie durch den Standardanschluss in des Programm geführt wird. Sie warten nicht auf '\n' bis sie loslegen, sondern darauf, dass überhaupt Zeichen da sind. Zu dieser Funktionalität kann auch gehören auf '\n' in dieser Reihe von Zeichen zu warten, muss aber nicht.
    Das scheinbare Warten auf '\n' liegt daran, dass die Standardeingabe meistens an einem Terminalemulator hängt und dieser liest seine Eingabe wiederum meistens von einer Tastatur. Und da ist die übliche Konvention, dass der Terminalemulator die eingegebenen Zeichen erst weiterreicht, wenn der Anwender Enter drückt. Und deshalb sieht das in C geschriebene Programm erst dann überhaupt eine Eingabe.

    Wenn man die Standardeingabe jedoch an eine andere Quelle hängt, beispielsweise eine Datei, dann legen die Funktionen der Standardbibliothek auch sofort los (außer die für Zeilenweise Eingabe), egal ob in der Datei später noch ein '\n' kommt oder nicht.



  • ANSI C kennt keine Terminalemulation und hängt auch nirgendwo dran. Ein '\n' beendet immer eine Eingabe und kann auch nicht auf ein anderes Zeichen standardkonform geändert werden.
    Dass das Lesen aus anderen Streams als dem Eingabestream anders arbeitet habe ich nie anders behauptet, die Ausführung bezieht sich ausschließlich auf "Eingabe" und auch das Beispiel scanf wurde bewusst gewählt und nicht etwa fscanf/sscanf usw.


  • Mod

    Wutz schrieb:

    ANSI C kennt keine Terminalemulation und hängt auch nirgendwo dran. Ein '\n' beendet immer eine Eingabe und kann auch nicht auf ein anderes Zeichen standardkonform geändert werden.
    Dass das Lesen aus anderen Streams als dem Eingabestream anders arbeitet habe ich nie anders behauptet, die Ausführung bezieht sich ausschließlich auf "Eingabe" und auch das Beispiel scanf wurde bewusst gewählt und nicht etwa fscanf/sscanf usw.

    Du haast mich völlig falsch verstanden. Ich habe weder von den Dateistreams gesprochen, noch dass ANSI C etwas von Terminalemulatoren weiß.

    ANSI C kennt nur die Standardeingabe und weiß sonst gar nichts. Da bei dir aber immer die Standardeingabe über einen Terminalemulator erfolgt, behauptest du hier fälschlicherweise, dass die Einlesefunktionen der Standardbibliothek auf '\n' warten würden. Tun sie aber nicht. Guck mal nach wie du bei dir die Standardeingabe an eine andere Quelle hängen kannst und probier es aus.



  • ANSI C kennt keinen Terminalemulator und fertig. ANSI C kennt aber '\n' und bei Auftreten dessen arbeiten die Standardfunktionen der Bibliothek den stdin-Stream ab, egal ob ein vorgeschalteter Terminalemulator oder was auch immer aus einem <ENTER> oder was auch immer ein '\n' erzeugt und in den Stream gestellt hat.


  • Mod

    Das ist schlicht und einfach falsch. Probiers doch einfach aus.


Anmelden zum Antworten