Java's split Funktion
-
hallo,
hab versucht, die ideen umzusetzen / mich damit abzufinden, dass mein c-Programm nicht so schön und kurz werden wird wie ein Perl-Programm. Hier mein aktueller Code:
#include <stdio.h> #define TRUE (1==1) #define FALSE (!TRUE) enum bool {false,true}; /* struct column { bool notNull, int len }; */ // length of the current column // gets counted when a character is printed // gets a reset each time a delimiter is found int currlen = 0; // the current column // gets incremented each time a delimiter is found int currcol = 0; // 'Constructor' for column /* struct column newCol(bool notNull, int len) { struct column ret; ret.notNull = notNull; ret.len = len; return ret; } */ void fillup() { // fills up column with whitespaces /* if (col.len < currlen) { exit programm returning an error } else { for (int i = currlen; i<col.len;i++){ printf(" "); } } */ } void replaceDelim(char *s) { if (*s == '"' && *(s+1) == ';' && *(s+2) == '"') { s+=2; currlen = 0; currcol++; fillup(); printf(":"); } } void printNormal(char *s) { if (!(*s=='"' && *(s+1)=='\0')) { currlen++; printf("%c",*s); } } void split(char *s) { if (*s++ != '"') printf("Fehler"); do { replaceDelim(s); printNormal(s); } while (*++s != '\0'); } int main(void) { /* struct column cols[4]; cols[0] = newCol(TRUE,10); cols[1] = newCol(TRUE,2); cols[2] = newCol(FALSE,8); cols[3] = newCol(TRUE,13); */ split("\"Das\";\"ist\";\"e\"i\"n\";\"Test\""); return 0; }
ein paar Dinge sind mir noch unklar:
1. wie definiere ich die struct? Jedes Mal, wenn ich die Kommentare wegmache bekomme ich beim Komplieren einen Fehler
2. wie ihr seht, habe ich das Erkennen des Delimiters / das Ausgeben von Zeichen die in einer Spalte vorkommen ausgelagert. Jetzt hab ich aber das Problem, dass ich in meiner replaceDelim den Pointer um 2 Zeichen weiterspringen lassen möchte. nur wird in der eigentlichen split-Funktion dann ignoriert, was in replaceDelim mit dem Pointer gemacht wurde. Ich muss den Pointer vermutlich byRef und nicht byVal übergeben (um es einmal in VisualBasic zu formulieren ;))
Aber ein Pointer ist ja schon eine Referenz! Muss ich da einen Pointer auf einen Pointer machen?!
Wie muss ich das schreiben?!
Hab es einfach mal so versucht:void replaceDelim(char **s) { if (**s == '"' && **(s+1) == ';' && **(s+2) == '"') { *s+=2; currlen = 0; currcol++; fillup(); printf(":"); } }
und mache dann in der spilt meinen Aufruf so:
replaceDelim(*s);
allerdings gibt mein Compiler einen "passing arg1 of 'replaceDelim' makes pointer from integer without a cast"-Fehler.
Kann mir da irgendwer weiterhelfen?!danke. guni
-
weiß da keiner mehr weiter?!
-
probier mal das:
#include <stdio.h> // 1. zeigt auf eingabestring // 2. zeigt auf ausgabestring // 3. mindestlaenge der woerter void replaceDelim (char *in, char *out, int length) { int chars = 0; while (*in) // mach fuer alle zeichen... { switch (*in) // welches zeichen haben wir gerade? { case '"': // " <-- auslassen break; case ';': // ; <-- spezialbehandlung while (chars++ < length) // letztes wort auffuellen mit ' ' *out++ = ' '; chars = 0; // wortzaehler reset break; default: // alles andere speichern *out++ = *in; chars++; break; // mitzaehlen fuer's auffuellen } in++; // naechstes zeichen pruefen } while (chars++ < length) // letztes wort auffuellen *out++ = ' '; *out = 0; // string-ende anhaengen } int main() { char out[256]; // <-- muss gross genug sein replaceDelim ("\"Das\";\"ist\";\"e\"i\"n\";\"Test\"", out, 10); // test puts (out); // und? gut oder bloed? }
-
<-- vergessen
-
ach so, da sollen noch doppelpunkte an's ende, kein problem -> füge nach zeile 19 folgendes ein:
out++ = ':';
-
^^edit: sternchen vergessen, so natürlich:
*out++ = ':';
-
hi +fricky.
dein ansatz ist ganz gut, deckt aber nicht ganz meine anforderungen ab, da die spalten ja unterschiedlich lang sein können.
deswegen hab ich mir überlegt, folgende struct zu bauen:
struct column { bool notNull, int len };
(in weiterer Folge muss ich noch entscheiden ob eine Spalte pflichtig ist oder nicht)
in meinem main-Programm will ich dann die Spalten deklarieren:
column col[] = ...
dann übergeb ich an die Funktion split mein col[] und die Funktion kann sich dann raussuchen, bei welchem Feld sie wieviel auffüllen muss:while (chars++ < col[i++]) // letztes wort auffuellen *out++ = ' ';
wie auch immer:
mein eigentliches Problem ist ja zur Zeit
1. dass ich die Struct irgendwie falsch zu deklarieren scheine (-> Code)
2. dass ich mein replaceDelim / printNormal / fillup aus der eigentlichen Split-Funktion auslagern will (aus Übersichtlichkeitsgründen); den pointer an die Unterfunktionen aber zur Zeit so übergebe dass ein s++ in replaceDelim nur lokal durchgeführt wird und die Zählung in der split-Funktion dann nicht übernommen wird!lg, guni
-
Hi!
Guckst du hier, machst du so:typedef int bool; enum {false, true};
Den Aufruf für
void replaceDelim(char **s)
in der Funktion split machst du so:
replaceDelim(**&**s);Ich würde Modulglobal
static char* s;
deklarieren.
Die Parameter müssen nicht ständig durch die Funktionen geschleppt werden.
Ausvoid replaceDelim(char** s);
wird
void replaceDelim();
usw., der Dereferenzierungssternchensalat in den Funktionen verschwindet vollständig.
Ich nehmen an, du bist objektorientierte Programmierung gewöhnt?
Deine Klasse ist jetzt deine *.c-Datei, die Membervariable in diesem Fall der statische char-Zeiger.
-
hi BigBrother,
dein Ansatz gefällt mir ganz gut (abgesehen davon, dass ich lieber Parameter übergebe), aber was soll's ...
jedenfalls bekomm ich jetzt beim Ausführen meines Programmes so einen Fehler:
$ ./converter
8 [main] converter 512 _cygtls::handle_exceptions: Error while dumping sta
te (probably corrupted stack)
Segmentation fault (core dumped)...
ausserdem wird eine .stacktrace-Datei angelegt, aus der ich aber nicht ganz schlau werde:
Stack trace: Frame Function Args 0022CCB8 0040108E (61004690, 0022CE64, 0022CCE8, 00401169) 0022CCC8 00401117 (6116B772, 0000002F, 00401130, 00401155) 0022CCE8 00401169 (00000001, 6116B748, 00660090, 0022CC70) 0022CD98 610060D8 (00000000, 0022CDD0, 61005450, 0022CDD0) 61005450 61004416 (0000009C, A02404C7, E8611021, FFFFFF48)
... was kann ich da machen?!
danke.
guni
-
guni schrieb:
dein Ansatz gefällt mir ganz gut (abgesehen davon, dass ich lieber Parameter übergebe), aber was soll's ...
Kannst du ja auch ruhig so weiter machen, du machst dir die Sache allerdings unnötig schwer.
Ich bin auch kein Fan der totalen Variablenglobalisierung aber in manchen Fällen, wie diesem, bietet es sich zweckmäßigerweise an.
Die statische Variable bleibt ja im Modul gekapselt. Für einen OOPisten ist das eine große Umstellung, verständlich, ging mir nämlich nicht anders.Was deine Stacktracegeschichte betrifft, keine Ahnung. Hab noch nie etwas mit einer Stacktrace-Datei zu tun gehabt.
Wäre evtl. hilfreich, das betreffende Codefragment zu posten.
-
hmm ... keine Ahnung, welches das entsprechende Code-Fragment ist.
Zur Zeit sieht mein Code so aus:#include <stdio.h> typedef int bool; enum bool {false,true}; struct column { bool notNull; int len; }; // length of the current column // gets counted when a character is printed // gets a reset each time a delimiter is found int currlen = 0; // the current column // gets incremented each time a delimiter is found int currcol = 0; static char *s; // 'Constructor' for column /* struct column newCol(bool notNull, int len) { struct column ret; ret.notNull = notNull; ret.len = len; return ret; } */ void fillup() { // fills up column with whitespaces /* if (col.len < currlen) { exit programm returning an error } else { for (int i = currlen; i<col.len;i++){ printf(" "); } } */ } void replaceDelim() { if (*s == '"' && *(s+1) == ';' && *(s+2) == '"') { *s+=2; currlen = 0; currcol++; fillup(); printf(":"); } } void printNormal() { if (!(*s=='"' && *(s+1)=='\0')) { currlen++; printf("%c",*s); } } void split() { if (*s++ != '"') printf("Fehler"); do { replaceDelim(); printNormal(); } while (*++s != '\0'); } int main(void) { /* struct column cols[4]; cols[0] = newCol(TRUE,10); cols[1] = newCol(TRUE,2); cols[2] = newCol(FALSE,8); cols[3] = newCol(TRUE,13); */ s = "\"Das\";\"ist\";\"e\"i\"n\";\"Test\""; split(); return 0; }
man sieht an den Kommentaren, dass ich noch einiges zu basteln plane ...
lg, guni
-
*(s+2)
Das wird wohl den Stackfehler verursachen, beim Abarbeiten des letzten Zeichens.
Es wird auf Speicher hinter der Zeichenkette zugegriffen.