String parsen



  • Hallo Forum,

    ich möchte einen String parsen, der die beiden Kommandos \n und \t enthält. Der
    String soll zum einen durch das Kommando \n geteilt werden und zum anderen anhand
    einer bestimmten Zeilenlänge. Ist ein Text also länger als erlaubt soll er
    geteilt werden und zwar zwischen zwei Wörtern.

    Beispiel, Zeilenlänge 20:
    Text:
    "Blindtext\n\nIch bin ein Blindtext und mir geht es gut."
    Ausgabe:
    Blintext

    Ich bin Blindtext
    und mir geht es gut.

    Weiterhin soll der Text mit vier Leerzeichen eingerückt werden wenn das Kommando \t auftaucht.

    Die Frage ist jetzt wie ich sinnvollerweise vorgehe und ob es schon Lösungen
    für ähnliche Probleme gibt. Ich habe angefangen, in dem ich den Text zunächst
    anhand der \n Kommandos in mehrere Zeilen zerlege. Dafür verwende ich strtok().
    Anschließend prüfe ich ob der Text in eine Zeile passt oder ob er zu lang ist.
    Wenn er zu lang ist zerlege ich den Text in einzelne Wörter mittels strtok()
    und füge sie so lange zusammen bis die Zeile voll ist. Bei der Methode werden
    jedoch mehrere \n in Folge nicht erkannt, weiterhin muss das Kommando \n noch
    eingeführt werden.

    Für alle Infos bin ich dankbar.
    Grüße Hans

    int split_text(char *text, char **lines, int line_length, int max_lines)
    {
        int   count_rows = 0, tmp;
        char  delimiter[] = " ";
        const char  newline[] = "\n";
        char *p_line, *r_line, *line, *end;
    
        char  search[]  = "\n\n";
        char  replace[] = "\n \n";
    
        // Speicherplatz allozieren
        line = malloc( sizeof(char) * line_length);
    
        // String line leeren
        line[0]  = '\0';
    
        // Text anhand newline Befehl teilen
        end    = text + strlen(text) + 1;
        p_line = strtok(text, newline);
    
        while(p_line != NULL && count_rows < max_lines) {
            text += strlen(p_line) + 1;
    
            // Text passt in eine Zeile
            if(strlen(p_line) < line_length) {
    
                lines[count_rows] = malloc(strlen(p_line)+1);
                strcpy(lines[count_rows], p_line);
    
                // String line leeren
                line[0] = '\0';
                count_rows++;
            }
    
            // Text passt nicht in eine Zeile
            else {
    
                // Text anhand eines Leerzeichen teilen
                r_line = strtok(p_line, delimiter);
    
                // Solange die Zeile nicht voll ist
                while(r_line != NULL && count_rows < max_lines) {
    
                	tmp = strlen(line)+strlen(r_line)+1;            	
    
                    // Strings verbinden wenn sie die Zeilenlänge nicht erreichen
                    if( tmp < line_length) {
                    	if(strlen(line) != 0) strcat(line, " ");
                        strcat(line, r_line);
                    }
    
                    // Ansonsten speichern
                    else {                	
                    	lines[count_rows] = malloc(strlen(line)+1);
                    	strcpy(lines[count_rows], line);
                    	line[0] = '\0';
                    	count_rows++;
                    	strcat(line, r_line);
                    }
    
                    // Naechstes Wort anfordern
                    r_line = strtok(NULL, delimiter);
                }
    
                lines[count_rows] = malloc(strlen(line)+1);
                strcpy(lines[count_rows], line);
                line[0] = '\0';
                count_rows++;
            }
    
            // Naechste Zeile anfordern
            if(text >= end) {
                break;
            }
            p_line = strtok(text, newline);
        }
    
        free(line);
        return count_rows;
    }
    
    int main(int argc, char *argv[])
    {
    	char **lines;
    	int max_char = 50;
    	int max_line = 30;
    	int i, count_rows;
    
    	char text[] = {"Blindtext\n\n\nIch bin ein Blindtext und ich stehe dazu. Folgende Punkte sind mir wichtig:\n\t1. Blind sein\n\t2. Sonstiges"};
    	lines = malloc( sizeof(char*) * max_line );
    
    	count_rows = split_text(text, lines, max_char, max_line);
    	printf("Count rows: %d\n", count_rows);
    
    	for(i=0; i<count_rows; i++) {
    		printf("%2d: %s\n", i+1, lines[i]);
    	}
    
    	return 0;
    }
    


  • Hans Brackhaus schrieb:

    Für alle Infos bin ich dankbar.

    ich finde deine funktion viel zu gross, für das was sie machen soll.
    🙂



  • ;fricky schrieb:

    ich finde deine funktion viel zu gross, für das was sie machen soll.
    🙂

    Wow, hast du studiert für einen so konstruktiven Vorschlag?



  • versuch mal so:

    void split_text (char *in, char *out, int line_len)
    {
      int spc=0, cnt=0, n=0, m=0;
    
      while (in[n])
      {
        if (in[n] == ' ')
          spc = n;
        else if (in[n] == '\n')
          cnt = 0;
        else if (in[n] == '\t')
        {
          out[m++] = ' ';
          out[m++] = ' ';
          out[m++] = ' ';
          out[m++] = ' ';
          cnt += 4;
          goto check;
        }
        out[m++] = in[n];
        cnt++;
    check:
        if (cnt >= line_len)
        {
          cnt = 0;
          m = m - n + spc;
          n = spc;
          out[m++] = '\n';
        }
        n++;
      }
      out[m] = 0;
    }
    

    🙂



  • Danke für den Tipp,

    ich muss jedoch die Zeilen trennen und einzeln ansprechen. Daher habe ich alle Zeilenumbrüche mit \0 überschrieben. Dann funktionierte es nach meinen Wünschen.

    Grüße Hans

    [cpp]
    int split_text (char *in, char *out, int line_len)
    {
        int spc = 0, cnt = 0, n = 0, m = 0;
        int cnt_rows = 0;
    
        while(in[n]) {
            if (in[n] == ' ') {
                spc = n;
            } else if (in[n] == '\n') {
                cnt = 0;
                in[n] = '\0';
                cnt_rows++;
            } else if (in[n] == '\t') {
              out[m++] = ' ';
              out[m++] = ' ';
              out[m++] = ' ';
              out[m++] = ' ';
              cnt += 4;
              goto check;
            }
    
            out[m++] = in[n];
            cnt++;
    
        check:
            if (cnt >= line_len) {
                cnt = 0;
                m = m - n + spc;
                n = spc;
                out[m++] = '\0';
                cnt_rows++;
            }
            n++;
        }
    
        out[m] = 0;
        return cnt_rows+1;
    }
    
    int main(int argc, char *argv[])
    {
        ...
    
        count_rows = split_text(text, lines, max_char);
        // Testausgabe
        for(i=0; i<count_rows; i++) {
            printf("%s\n", lines);
            lines += strlen(lines)+1;
        }
    
        ...
    }
    [/cpp]
    


  • Hans Brackhaus schrieb:

    Danke für den Tipp,
    ich muss jedoch die Zeilen trennen und einzeln ansprechen. Daher habe ich alle Zeilenumbrüche mit \0 überschrieben. Dann funktionierte es nach meinen Wünschen.

    gern geschehen. du hättest aber nicht alle {'s in die vorherige zeile schubsen müssen, das sieht ja furchtbar aus.
    🙂


Anmelden zum Antworten