Leerzeichen bei Wortsortierung erkennen



  • Hallo, habe für die Uni die Aufgabe bekommen, eine Textdatei mit einem Wort pro Zeile zu sortieren. Allerdings wenn bei dem letzten Wort kein Leerzeichen gesetzt wird, die Wörter in einer Zeile sortiert. hat jemand eine Ahnung wie ich das lösen kann?```c

      #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h>
    
    void bubblesort (int size, char **p_dataarray) {
      char *temp;
      temp = (char*)malloc(60 * sizeof(char));
      for (int i=0; i<size-1; ++i){
        for (int j=0; j<=size-i-1; ++j){
          if (strcmp(p_dataarray[j],p_dataarray[j+1])>0) {
            
            strcpy(temp,p_dataarray[j]);
            strcpy(p_dataarray[j],p_dataarray[j+1]);
            strcpy(p_dataarray[j+1],temp);
          } 
        }
      }
      //dient nur als kontrolle
      for(int i=0;i<size;++i)
            printf("%s ",p_dataarray[i]); //Printing elements after bubble sort
      
      return;
    }
    
    void controlFile(char *e, char *a){
      FILE  *fe;
      FILE  *fa;
      fe = fopen(e, "rb");
      fa = fopen(a, "wb");
    
      if(fe==NULL) { //Hiermit wird ausgeschlossenm, dass die Eingabedatei fehlerbehaftet geöffnet/erstellt wurde
        printf("Fehler beim Oeffnen der Eingabedatei"); 
        fclose(fe);
        fclose(fa);
        exit(-1);  
      } else{
          if(fa==NULL) { //Hiermit wird ausgeschlossenm, dass die Ausgabedatei fehlerbehaftet geöffnet/erstellt wurde
            printf("Fehler beim Oeffnen der Ausgabedatei");
            fclose(fe);
            fclose(fa);
            exit(-2);   
          }else{ //dient nur als Kontrolle
            printf("Dateien in Ordnung\n");
            printf("Dateiname:\n %s\n, %s\n",e,a);
          }
        }
    
      return;
    }
    
      
    void allocdata (char ***p_dataarray, int *ptr_size) {
      int size = *ptr_size;
    
      if (size==0){
            return;
      } 
      // Allocate memory for pointers to columns
    
      char **data;
      data = (char**) malloc (size * sizeof (unsigned char*));
      // Allocate the actual memory for data column by column
      for (int i=0; i<size; ++i){
          data[i] = (unsigned char*) malloc (60 * sizeof (unsigned char));
      }
        
      // Return root pointer of 2D array via pointer parameter
      *p_dataarray = data;
      return;
    }
    
    void read ( char ***p_dataarray, int *ptr_size, char *e){
      FILE *fe;
      int size = 0;
      char inputline[60]; //60 aus Angabe  
      char **data_array = NULL;
      char value;
      fe=fopen(e,"rb");
      
      do{
        fgets(inputline, sizeof(inputline), fe);
        if(inputline!=""){
          size++;
          printf("Size %d", size);
        }
      }while(fgetc(fe)!=EOF); //Noch nicht optimal
      *ptr_size = size;
    
      allocdata(&data_array,ptr_size);
    
      for (int i=0; i<size; ++i) {
        fgets(data_array[i],60,fe);
      }
      fclose (fe);
    
      *p_dataarray = data_array;
      return;
    }
    
    
    void override(int size, char **p_dataarray, char *a) {
      FILE  *fa;
      fa = fopen(a, "wb");
      for(int i=0; i<size; i++){
        for(int j=0; j<60;j++){
          putc(p_dataarray[i][j],fa);
        }
            
      }
      fclose(fa);
      return;
    }
    
    void freeStorage (char **p_dataarray, int size) {
      if (size == 0){
        return;
      } 
    
      // First, release columns
      for (int i=0; i<size; ++i){
         free (p_dataarray[i]);
      }
      // Then, release the array of pointers to the columns
      free (p_dataarray);
      return;
    }
    
    void name() { //Abfragen der Dateinamen
      char e[50];
      char a[50];
      e[0]='\0';
      a[0]='\0';
      printf("Eingabe des Namens der Eingangsdatei: ");
      fgets (e, sizeof (e), stdin);
      sscanf(e,"%s",&e);
      printf("Eingabe des Namens der Ausgangsdatei: ");
      fgets (a, sizeof (a), stdin);
      sscanf(a,"%s",&a);
      controlFile(e,a);
    }
    
    int main() { //die Name funktion tut des im moment nicht richtig übergeben deswegen hab ich es jetzt erstmal in der Main
      char **mydata;
      int datasize; 
      char e[50];
      char a[50];
      e[0]='\0';
      a[0]='\0';
      printf("Eingabe des Namens der Eingangsdatei: ");
      fgets (e, sizeof (e), stdin);
      sscanf(e,"%s",&e);
      printf("Eingabe des Namens der Ausgangsdatei: ");
      fgets (a, sizeof (a), stdin);
      sscanf(a,"%s",&a);
      controlFile(e,a);
    
        
      read(&mydata,&datasize,e);
      printf ("Anzahl gelesener Werte: %d\n", datasize);
      bubblesort(datasize,mydata);
      override(datasize,mydata,a);
      freeStorage(mydata,datasize);
      return 0;    
    }
    

    hier ist mein Code, falls jemand gerade Zeit hat und mir helfen könnte wäre sehr nett 🙂
    LG Nikas


  • Mod

    @niklas_13 sagte in Leerzeichen bei Wortsortierung erkennen:

    Allerdings wenn bei dem letzten Wort kein Leerzeichen gesetzt wird, die Wörter in einer Zeile sortiert.

    Was? Du hast ein wohl ein paar Wörter bei deiner Problembeschreibung verschluckt.

    Insgesamt ist mir das viel zu viel Code für solch eine Aufgabe. Das sollte in deutlich unter 50 Zeilen gehen. Zumal du offenbar noch Anfänger bist und dir irgendwo viele schlechte Angewohnheiten abgeschaut hast. Jedenfalls ist das zu viel, um dir den kompletten Code zu reviewen. Aber beim Überfliegen habe ich in nahezu jedem Teil Probleme gesehen. Ohne deutlichere Frage kann man dir daher nicht helfen. Mein Rat wäre tatsächlich, alles deutlich abzuspecken und aufs nötigste zu reduzieren. Du machst in den unnötigen Extrateilen einfach zu viele Fehler, die dann wer weiß was für Auswirkungen an anderer Stelle haben. Konzentrier dich aufs Wesentliche, und mach das dann auch ordentlich. Und wenn du damit Probleme hast, dann kann man dir damit auch konkreter helfen.



  • @niklas_13 sagte in Leerzeichen bei Wortsortierung erkennen:

    Allerdings wenn bei dem letzten Wort kein Leerzeichen gesetzt wird, die Wörter in einer Zeile sortiert.

    Du scheinst ein Problem mit den Eigenschaften von scanf und fgets zu haben.
    fgets liest bis zum '\n' und speichert das mit ab. Wenn es nicht im String ist, dann ist die Zeilel änger als die angegebene Länge.
    scanf liest bei %s bis zu einem Whitespace (Leerzeichen, Newline, Tabulatoren, ...) - die werden auch am Anfang überlesen.

    Zu bubblesort:
    Das malloc braucht ein free.
    Allerdings ist es angebrachter, nur die Pointer zu tauschen und nicht den Inhalt hin und her zu kopieren.

    Zu controlFile:
    Wenn kein Fehler auftaucht, bleiben die Dateien geöffnet, was gerade beim Schreibzugriff problematisch werden kann.
    Eine Datei die nicht geöffnet werden konnte, braucht man auch nicht schließen.
    Ist diese Funktion Teil der Aufgabe?
    Wenn nicht, lass sie weg und gib den Fehler dann aus, wenn er auftritt.

    Zu read:
    Nachdem du die Anzahl der Zeilen ermittelt hast, bist du am Dateiende angekommen. Da bringen weitere Leseversuche auch nichts mehr.

    Zu allocdata:
    Text werden mit char verarbeitet. signed char und unsigned char sind zum Rechnen da. Zumal es egal ist, da strcmp mit char implementiert ist.

    Zu override:
    Wäre es nicht sinnvoller, die Wörter wieder in Zeilen zu schreiben anstatt nahtlos hintereinader weg?
    printf gibt es auch in einer Version für Dateien - hier ist fputs aber sinnvoller.

    Zu name:
    irgendwie solltest du die Namen auch aus der Funktion raus bekommen.

    Es wäre für dich einfacher, wenn du ein ausreichend großes Array von *char benutzt (auch als **char via malloc). Und die Zeilen darin auch nur so groß anlegst, wie die Wörter lang sind (+1 wegen der '\0')



  • Zeile 152,154,159 ist UB.
    Hier mal ein Ansatz zum effektiven Umgang mit Textdateien und dynamischen Stringlisten.
    Und 2 Fehler in deinem bubblesort habe ich auch gleich bereinigt.
    https://onlinegdb.com/BZnJK0vvd

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void bubblesort (int size, char **p_dataarray) {
      char *temp = malloc(1000);
      for (int i=0; i<size-1; ++i){
        for (int j=0; j<size-i-1; ++j){
          if (strcmp(p_dataarray[j],p_dataarray[j+1])>0) {
            
            strcpy(temp,p_dataarray[j]);
            strcpy(p_dataarray[j],p_dataarray[j+1]);
            strcpy(p_dataarray[j+1],temp);
          } 
        }
      }
      free(temp);
    }
    
    int main()
    {
        char **w=0,z[100];
        int n=0;
        /* Testdatenbeschaffung (Datei mit 1 Wort/Zeile) */
        system("sed 's/:.*//' /etc/passwd>/tmp/kuno");
        FILE *f=fopen("/tmp/kuno","r");
        while( fscanf(f,"%99s",z)==1 ) w=realloc(w,++n*sizeof*w),strcpy(w[n-1]=malloc(strlen(z)+1),z);
        fclose(f);
        
        for(int i=0;i<n;++i) puts(w[i]);
        bubblesort(n,w);
        puts("##############################################");
        for(int i=0;i<n;++i) puts(w[i]);
    
        while(n--) free(w[n]); free(w);
        return 0;
    }
    


  • Vielen Dank für die Antworten. Werde mir nochmal die genauen Eigenschaften von den Funktionen anschauen und das Programm nochmal überarbeiten. Sry wenn ich bisschen ungenau zw. zu viel Code geschickt habe. Bin noch neu hier 😕



  • @niklas_13 sagte in Leerzeichen bei Wortsortierung erkennen:

    Sry wenn ich bisschen ungenau zw. zu viel Code geschickt habe. Bin noch neu hier 😕

    Betrachte sowas auch als Anleitung.
    Der Compiler nimmt es sehr genau.
    Wir können noch versuchen etwas zu interpretieren.

    Der Compiler macht, was du ihm sagst, nicht was du meinst.


Log in to reply