Textdatei auslesen und Buchstaben umkehren ( Codieren ...)



  • Hallo,
    also die Aufgabenstellung ist folgende:

    Program 10: It’s a Message
    The underdeveloped but upwardly mobile country of Galosh has need of a secret code in which to express its
    diplomatic dispatches, so the head cryptographer proposed that first, all sequences of nonvowels (including spaces
    and punctuation) be reversed. The letter “y” is NOT considered to be a vowel. Then, the entire string message
    should be written backwards.
    A program is to be written so that a message sent from the Prime Minister to various aides can be decoded. Two
    examples of messages and their encoded versions are:
    HELLO THERE.
    .ERE THOLLEH
    MAKE THAT EXTRA CHEESE. PEPPERONI GIVES ME HEARTBURN.
    RN.URTBAE HES MEVI GINOREPPE. PESEE CHAXTRET A THEKAM
    All messages will contain either the capital letters, digits (0-9) , a blank, or the following two punctuation
    characters: . , and will be restricted to at most 60 characters. Your program should accept any number of
    encoded messages from the file named message.dat and write their associated decoded results to the display

    Meine Ansatzloesung ist die folgende :

    #include <stdio.h>
    #include <string.h>
    
    int main (void)
    {
      FILE *datei;
      char text[60+1];
      int a;
    
      datei = fopen ("testdatei.txt", "r");
      if (datei != NULL)
        {
          fscanf (datei, "%60c", text);
          text[60] = '\0';
          fclose (datei);
        }
    
      char t[5] = "aeiuo";
    
      for(a=strlen(text); a>=0; a--) {
        printf("%c", text[a]);
    
      }
    
      return 0;
    }
    

    Nun wollte ich eine IF Schleife reinbringen mit :

    if ( strcspn ( text[a], t ) == strcspn ( text[a-1], t ) ) {
    

    Und die wollte ich dann in die for Schleife reinbringen. Danach weiss ich ja ob zwei Konsonanten nebeneinander sind. Dann muss ich diese beiden nur noch tauschen, natuerlich muss ich die for Schleife dann noch abaendern.

    Ich bleibe ab da dann aber stehen und komme nicht weiter, ich versuche es die ganze Zeit irgendwie mit strcspn zu machen, aber ich glaube das geht damit irgendwie nicht, zumal er mir dann immer einen Segmantation Error ausgibt 😞

    Irgendwelche Ideen, oder eine Funktion die hier vielleicht doch sinnvoller ist?



  • C/C++ Code:
    if ( strcspn ( text[a], t ) == strcspn ( text[a-1], t ) ) {

    Irgendwann ist a (a >= 0) dann 0... 0-1 = -1 -> text[-1] ist gegebenenfalls nicht unbedingt genau der Speicherbereich, den Du damit ansprechen wolltest. Soviel zum Thema segmentation fault.

    Desweiteren sollte Dich ein anständiger compiler freundlich darauf hinweisen, dass strcspn zwei Variablen des Typs char * erwartet und bringt Dir nicht den von Dir gewünschten Rückgabewert (Du fütterst char und char * - außerdem: es gibt keine if-Schleifen! Eine If-Anweisung bezeichnet man eher als "Verzweigung", weil Sie im Programmfluss eine Gabelung darstellt (guxtu UML))... Du könntest stattdessen wie folgt hantieren:

    int  konsonant (char c)
    {   // sofern c != '\0' und ein Vokal-> 0 zurückgeben
       char txt[6] = "aeiou";
       if ( !c || strchr (c, txt ) )
          return 0;
       else return 1; // wenn kein Vokal return 1
    
    // wenn a != 0  kannst Du [a-1] ansprechen
    if ( a && konsonant ( text[a] ) && konsonant ( text[a-1] ) ) {
    


  • Du solltest dich erstmal um die Grundlagen kümmern bevor du Details in Angriff nimmst.
    Lesen von Strings aus einer Datei ist bei dir nämlich falsch.



  • Wutz schrieb:

    Du solltest dich erstmal um die Grundlagen kümmern bevor du Details in Angriff nimmst.
    Lesen von Strings aus einer Datei ist bei dir nämlich falsch.

    Warum ist denn das lesen aus der Datei falsch ? Versteh ich nicht.



  • PrettyX schrieb:

    C/C++ Code:
    if ( strcspn ( text[a], t ) == strcspn ( text[a-1], t ) ) {

    Irgendwann ist a (a >= 0) dann 0... 0-1 = -1 -> text[-1] ist gegebenenfalls nicht unbedingt genau der Speicherbereich, den Du damit ansprechen wolltest. Soviel zum Thema segmentation fault.

    Desweiteren sollte Dich ein anständiger compiler freundlich darauf hinweisen, dass strcspn zwei Variablen des Typs char * erwartet und bringt Dir nicht den von Dir gewünschten Rückgabewert (Du fütterst char und char * - außerdem: es gibt keine if-Schleifen! Eine If-Anweisung bezeichnet man eher als "Verzweigung", weil Sie im Programmfluss eine Gabelung darstellt (guxtu UML))... Du könntest stattdessen wie folgt hantieren:

    int  konsonant (char c)
    {   // sofern c != '\0' und ein Vokal-> 0 zurückgeben
       char txt[6] = "aeiou";
       if ( !c || strchr (c, txt ) )
          return 0;
       else return 1; // wenn kein Vokal return 1
    
    // wenn a != 0  kannst Du [a-1] ansprechen
    if ( a && konsonant ( text[a] ) && konsonant ( text[a-1] ) ) {
    

    testfile.c:36: warning: passing argument 1 of âstrchrâ makes pointer from integer without a cast

    Was hat das zu bedeuten ? Wikipedia sagt mir das fuer den zweiten Wert ein integer verlangt wird, ist txt nicht aber ein character ?



  • txt ist ein character-Array, welches an der Stelle überhaupt nicht passt. Das ist es aber nicht, was der Compiler bemängelt - ihm geht es darum, dass du c, welches ein character ist, in ein Argument stopfst, das einen Zeiger auf characters erwartet (in diesem Fall einen String).

    Du hast schlicht die Parameter verwechselt. So ist es richtig:

    strchr(txt, c)
    


  • Danke seldon 🙂

    Man könnte auch sagen, ich hätte die Parameter verwechselt 😉 Aber das war natürlich nur mein kühner Plan, den Thread-Ersteller vom copy & paste abzuhalten (hat bissel gefailed) 🙂



  • char *strchr(const char *, int c); locates byte c in a string, searching from the beginning

    Macht Sinn nachdem ich nochmal nachgeschaut habe welche Werte verlangt werden. Werde mir das Morgen nochmal genauer anschauen, musste das leider so einreichen wie ich es oben hatte und hoffe das ich Teilpunkte bekomme. Will das aber dennoch hinbekommen.

    Achja, warum hast du c != 0 gemacht ? Im Falle von einem Blank ?



  • Das Zeichen '\0' mit dem Wert 0 kennzeichnet in C das Stringende.



  • Ich überlege gerade: Hättest Du erwähnt, dass Du für die Aufgabe benotet wirst, hätte ich mir entweder mehr Mühe gegeben oder Dir fiese unauffällige Fehler eingebaut oder gar nicht geholfen 😉

    Jetzt hast Du auf alle Fälle nicht funktionierenden Code abgegeben und bist Dir trotzdem nicht im Klaren, was das Programm tut...

    Nächstes mal gibt's nur Ansätze 😉



  • Na, jetzt wo's abgegeben ist:

    #include <ctype.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <string.h>
    
    void swap(char *first, char *last) {
      char c = *first;
      *first = *last;
      *last = c;
    }
    
    void reverse(char *first, char *last) {
      while(first < last) {
        swap(first++, --last);
      }
    }
    
    int is_vowel(char c) { 
      return strchr("aeiou", tolower(c)) != NULL;
    }
    
    int main(void) {
      char buffer[1024];
    
      while(fgets(buffer, 1024, stdin) && 0 != strcmp(buffer, "exit\n")) {
        size_t buf_len = strlen(buffer);
        char *first, *last, *buf_end;
    
        /* fgets speichert den Zeilenumbruch mit, den wir hier aber nicht
         * brauchen. Also: weg damit. */
        if(buffer[buf_len - 1] == '\n') {
          --buf_len;
          buffer[buf_len] = '\0';
        }
    
        buf_end = buffer + buf_len;
    
        /* Und jetzt das Ganze umgekehrt: Erst ganzen Buffer umdrehen */
        reverse(buffer, buf_end);
    
        for(first = buffer; first != buf_end; ++first) {
          if(!is_vowel(*first)) {
            for(last = first + 1; *last && !is_vowel(*last); ++last)
              ;
    
            /* Hier zeigt first auf den Anfang eines Bereiches von Konsonanten
             * und last hinter sein Ende. Dann wird umgedreht. */
            reverse(first, last);
    
            /* Und am Ende des Bereiches wird dann weitergesucht. */
            first = last - 1;
          }
        }
    
        puts(buffer);
      }
    
      return 0;
    }
    


  • PrettyP schrieb:

    Ich überlege gerade: Hättest Du erwähnt, dass Du für die Aufgabe benotet wirst, hätte ich mir entweder mehr Mühe gegeben oder Dir fiese unauffällige Fehler eingebaut oder gar nicht geholfen 😉

    Jetzt hast Du auf alle Fälle nicht funktionierenden Code abgegeben und bist Dir trotzdem nicht im Klaren, was das Programm tut...

    Nächstes mal gibt's nur Ansätze 😉

    Verstehe deine Aussage nicht, mehr helfen, mehr Fehler einbauen, oder gar nicht helfen ? Ist genau die gleiche Ausgangssituation, wie sie schon vorher war. Wenn du mir nicht helfen willst, musst du ja nicht 😉

    Desweiteren habe ich gesagt das ich mir den Code spaeter nochmal anschaue und dann versuche es noch hinzubekommen, deswegen versuche ich auch so wenig wie moeglich auf den letzten Post zu schauen, wills ja irgendwann mal selber auf die Reihe bekommen 😃

    Haette mir gerne mehr Muehe gegeben, aber ich habe taeglich Hausaufgaben fuer 4 Faecher und dann verlangt er 3 Programming Assignments fuer einen Tag, plus 3 Tests diese Woche, ich kann ja schlecht nur fuer diesen Kurs lernen. Wie dem auch sei, ich werd weiter dran bleiben. Hab heute erstmal richtig gerlernt wie man variablen deklariert und was Pointer genau sind, macht jetzt alles etwas mehr Sinn 🙂



  • Macht es einen Unterschied ob ich schreibe

    char c = *pointer oder *pointer = char c
    

    ?



  • #include <stdio.h> 
    #include <string.h> 
    
    void swap ( char *erster, char *letzter ) {
    	char c = *erster;
    	*erster = *letzter;
    	*letzter = c;
    }
    
    int  konsonant (char c) {   
       char txt[5] = "aeiou"; 
       if ( !c || strchr (txt, c ) ) 
          return 0; 
    
       else return 1; 
    
    }
    
    int main (void) 
    { 
    
     FILE *datei; 
      char text[60];
      int a = strlen(text);
    
      datei = fopen ("testdatei.txt", "r"); 
      if (datei != NULL) 
        { 
          fscanf (datei, "%60c", text); 
          text[60] = '\0'; 
          fclose (datei); 
        } 
    
      char *erster = text[0];
      char *letzter = text[60]; 
    
    if ( a && konsonant ( text[a] ) && konsonant ( text[a-1] ) ) {
    
    	swap ( erster, letzter );
    
    	}
    
      for(a=strlen(text); a>=0; a--) { 
        printf("%c", text[a]); 
    
      } 
    
      return 0; 
    }
    

    Ich blick gar nicht mehr durch, frag mich warum er bei der Dekleration von char *erster ... immer eine Fehlermeldung rausgibt... Plus integer igrgendwas mit pointer without cast -.- WARUM, das sind doch alles characters ? nix mit integer ... ich raffs einfach net. 😡



  • Zunächst:

    char txt[5] = "aeiou";
    

    ist falsch, weil der Buffer zu kurz ist. Du brauchst fünf Zeichen plus Sentinel, also insgesamt 6. Ist dir bekannt, wie Strings in C aussehen?

    Was deine Compilerwarnung angeht, bei

    char *erster = text[0];
      char *letzter = text[60];
    

    ist text[0] das erste Zeichen in text und text[60] erneut ein Fehler, weil es versucht, das einundsechzigste Zeichen in einem Buffer von 60 Zeichen Länge auszulesen. Ich glaube, du meinst

    char *erster = text;
      char *letzter = text + 60;
    

    ...wobei das in die Programmlogik insofern nicht wirklich passt, als dass der eingelesene String nicht unbedingt genau 60 Zeichen lang sein muss, selbst wenn der Buffer es ist.

    Ferner macht

    fscanf (datei, "%60c", text);
    

    mit einiger Wahrscheinlichkeit nicht das, was du willst.



  • Das hapert hier an so vielen sachen, dass es keinen sinn macht alles in einem programm gleichzeitig zu lernen.

    Guck dir nochmal Zeiger, Strings, Arrays an. Und mach paar einfache Aufgaben dazu, wo nicht alles auf einmal kommt, denn sonst bleiben die Erfolgserlebnisse aus.



  • Isengo222 schrieb:

    WARUM, das sind doch alles characters ? nix mit integer ... ich raffs einfach net. 😡

    char sind auch Integer. Mit einem eingeschränkten Wertebereich.

    Teil doch deine Zeile auf:

    char c;
    c = *erster;
    

Log in to reply