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:
BlintextIch 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 Hansint 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.