diff options
| author | Thomas Schmucker <ts@its1.de> | 2025-04-11 12:07:18 +0200 |
|---|---|---|
| committer | Thomas Schmucker <ts@its1.de> | 2025-04-11 12:07:18 +0200 |
| commit | 754fe554f289e6ea1933815a1f772bfd34b20d92 (patch) | |
| tree | 63ca2ec817b2cb84ae2b5203097635b590275b5c /readme.md | |
| parent | 8bf373e0dd4cfb5773e28ba6d1d1dc0f5c7254ec (diff) | |
| download | libcsv-754fe554f289e6ea1933815a1f772bfd34b20d92.tar.gz libcsv-754fe554f289e6ea1933815a1f772bfd34b20d92.tar.bz2 libcsv-754fe554f289e6ea1933815a1f772bfd34b20d92.zip | |
better documentation for code blocks in readme
Diffstat (limited to 'readme.md')
| -rw-r--r-- | readme.md | 34 |
1 files changed, 17 insertions, 17 deletions
| @@ -73,7 +73,7 @@ Lösung: => Selber schreiben! | |||
| 73 | Nehmen wir an, wir schreiben eine Funktion zur CSV-Verarbeitung. | 73 | Nehmen wir an, wir schreiben eine Funktion zur CSV-Verarbeitung. |
| 74 | Das Grundgerüst sieht dann etwa so aus: | 74 | Das Grundgerüst sieht dann etwa so aus: |
| 75 | 75 | ||
| 76 | ~~~ | 76 | ~~~c |
| 77 | bool | 77 | bool |
| 78 | processFile(const char *filename) | 78 | processFile(const char *filename) |
| 79 | { | 79 | { |
| @@ -92,7 +92,7 @@ processFile(const char *filename) | |||
| 92 | 92 | ||
| 93 | Wir fügen als erstes etwas Code hinzu: | 93 | Wir fügen als erstes etwas Code hinzu: |
| 94 | 94 | ||
| 95 | ~~~ | 95 | ~~~c |
| 96 | csv_t csv; | 96 | csv_t csv; |
| 97 | csv_init(&csv); | 97 | csv_init(&csv); |
| 98 | 98 | ||
| @@ -107,7 +107,7 @@ Dieser Code erzeugt ein neues `csv_t`-Objekt im Speicher welches anschließend d | |||
| 107 | 107 | ||
| 108 | Dann wird der Datenstrom `in` zeilenweise in den Speicher eingelesen und innerhalb der Schleife verarbeitet. Die Anzahl der Felder pro Zeile wird mit Hilfe der Funktion `csv_nfields()` ermittelt. Alternativ liefert auch der Returnwert von `csv_read()` die Feldanzahl: | 108 | Dann wird der Datenstrom `in` zeilenweise in den Speicher eingelesen und innerhalb der Schleife verarbeitet. Die Anzahl der Felder pro Zeile wird mit Hilfe der Funktion `csv_nfields()` ermittelt. Alternativ liefert auch der Returnwert von `csv_read()` die Feldanzahl: |
| 109 | 109 | ||
| 110 | ~~~ | 110 | ~~~c |
| 111 | // ... | 111 | // ... |
| 112 | size_t nf; | 112 | size_t nf; |
| 113 | while ( (nf = csv_read(&csv, in)) != 0 ) { | 113 | while ( (nf = csv_read(&csv, in)) != 0 ) { |
| @@ -130,7 +130,7 @@ Wenn nichts weiter angegeben ist, gehen wir von einem Komma (`,`) als Feldtrenne | |||
| 130 | 130 | ||
| 131 | Wir berücksichtigen dies bei der Initialisierung eines `csv_options_t`-Objektes. | 131 | Wir berücksichtigen dies bei der Initialisierung eines `csv_options_t`-Objektes. |
| 132 | 132 | ||
| 133 | ~~~ | 133 | ~~~c |
| 134 | csv_options_t csv_options = csv_default_options; | 134 | csv_options_t csv_options = csv_default_options; |
| 135 | csv_options.field_delimiter = '"'; | 135 | csv_options.field_delimiter = '"'; |
| 136 | csv_options.field_separator = ','; | 136 | csv_options.field_separator = ','; |
| @@ -155,7 +155,7 @@ Bei der Verarbeitung können verschiedene Fehler auftreten, die ein robustes Pro | |||
| 155 | 155 | ||
| 156 | Die beste Variante, die dem klassischen Exceptions am nächsten kommt, sind die beiden C-Funktionen `setjmp()` und `longjmp()`, mit deren Hilfe wir nun die Fehlerbehandlung umsetzen. Wir benötigen dafür die beiden Felder `cb_error` und `cb_error_arg` des `csv_options`-Objektes: | 156 | Die beste Variante, die dem klassischen Exceptions am nächsten kommt, sind die beiden C-Funktionen `setjmp()` und `longjmp()`, mit deren Hilfe wir nun die Fehlerbehandlung umsetzen. Wir benötigen dafür die beiden Felder `cb_error` und `cb_error_arg` des `csv_options`-Objektes: |
| 157 | 157 | ||
| 158 | ~~~ | 158 | ~~~c |
| 159 | jmp_buf env; | 159 | jmp_buf env; |
| 160 | csv_options.cb_error = csvErrorHandler; | 160 | csv_options.cb_error = csvErrorHandler; |
| 161 | csv_options.cb_error_arg = &env; | 161 | csv_options.cb_error_arg = &env; |
| @@ -163,7 +163,7 @@ csv_options.cb_error_arg = &env; | |||
| 163 | 163 | ||
| 164 | `cb_error` ist ein Zeiger auf eine Callback-Funktion, die im Falle eines Fehlers aus der CSV-Bibliothek heraus aufgerufen wird. Ihr werden ein Fehlerwert vom Typ `csv_err_t` sowie ein Zeiger auf benutzerdefinierte Daten -- in unserem Fall ein Zeiger auf eine `jmp_buf`-Variable -- mit übergeben: | 164 | `cb_error` ist ein Zeiger auf eine Callback-Funktion, die im Falle eines Fehlers aus der CSV-Bibliothek heraus aufgerufen wird. Ihr werden ein Fehlerwert vom Typ `csv_err_t` sowie ein Zeiger auf benutzerdefinierte Daten -- in unserem Fall ein Zeiger auf eine `jmp_buf`-Variable -- mit übergeben: |
| 165 | 165 | ||
| 166 | ~~~ | 166 | ~~~c |
| 167 | static void | 167 | static void |
| 168 | csvErrorHandler(csv_err_t err, void *cb_arg) | 168 | csvErrorHandler(csv_err_t err, void *cb_arg) |
| 169 | { | 169 | { |
| @@ -176,7 +176,7 @@ Mit Hilfe des Parameter `err` wird eine einfache Fehlermeldung protokolliert. An | |||
| 176 | 176 | ||
| 177 | Die Hauptschleife in unserer Funktion sieht nun so aus: | 177 | Die Hauptschleife in unserer Funktion sieht nun so aus: |
| 178 | 178 | ||
| 179 | ~~~ | 179 | ~~~c |
| 180 | csv_options_t csv_options = csv_default_options; | 180 | csv_options_t csv_options = csv_default_options; |
| 181 | csv_options.field_delimiter = '"'; | 181 | csv_options.field_delimiter = '"'; |
| 182 | csv_options.field_separator = ','; | 182 | csv_options.field_separator = ','; |
| @@ -218,7 +218,7 @@ case CSV_ERR_IO_READ: | |||
| 218 | 218 | ||
| 219 | **Fehlercodes** für die Callbackhandler: | 219 | **Fehlercodes** für die Callbackhandler: |
| 220 | 220 | ||
| 221 | ~~~ | 221 | ~~~c |
| 222 | typedef enum { | 222 | typedef enum { |
| 223 | CSV_ERR_OK = 0, | 223 | CSV_ERR_OK = 0, |
| 224 | CSV_ERR_OUT_OF_MEMORY = -1, | 224 | CSV_ERR_OUT_OF_MEMORY = -1, |
| @@ -230,7 +230,7 @@ typedef enum { | |||
| 230 | 230 | ||
| 231 | **Optionen** für das Parsen eines CSV-Streams: | 231 | **Optionen** für das Parsen eines CSV-Streams: |
| 232 | 232 | ||
| 233 | ~~~ | 233 | ~~~c |
| 234 | typedef struct { | 234 | typedef struct { |
| 235 | int field_delimiter; | 235 | int field_delimiter; |
| 236 | int field_separator; | 236 | int field_separator; |
| @@ -249,7 +249,7 @@ extern const csv_options_t csv_default_options; | |||
| 249 | 249 | ||
| 250 | **Contextobjekt** zur Aufnahme der aktuell gelesenen Zeile: | 250 | **Contextobjekt** zur Aufnahme der aktuell gelesenen Zeile: |
| 251 | 251 | ||
| 252 | ~~~ | 252 | ~~~c |
| 253 | typedef struct { | 253 | typedef struct { |
| 254 | csv_options_t *csv_options; | 254 | csv_options_t *csv_options; |
| 255 | /* additional internal fields */ | 255 | /* additional internal fields */ |
| @@ -260,7 +260,7 @@ typedef struct { | |||
| 260 | 260 | ||
| 261 | **Initialisieren** | 261 | **Initialisieren** |
| 262 | 262 | ||
| 263 | ~~~ | 263 | ~~~c |
| 264 | void csv_init(csv_t *csv); | 264 | void csv_init(csv_t *csv); |
| 265 | void csv_init_opt(csv_t *csv, const csv_options_t *const csv_options); | 265 | void csv_init_opt(csv_t *csv, const csv_options_t *const csv_options); |
| 266 | ~~~ | 266 | ~~~ |
| @@ -277,7 +277,7 @@ Mit der Funktion `csv_init_opt()` und einem angepassten `csv_options_t`-Objektes | |||
| 277 | 277 | ||
| 278 | **Manuelles Freigeben** | 278 | **Manuelles Freigeben** |
| 279 | 279 | ||
| 280 | ~~~ | 280 | ~~~c |
| 281 | void csv_cleanup(csv_t *csv); | 281 | void csv_cleanup(csv_t *csv); |
| 282 | ~~~ | 282 | ~~~ |
| 283 | 283 | ||
| @@ -290,7 +290,7 @@ Parameter | |||
| 290 | 290 | ||
| 291 | **Zeilenweises Lesen** | 291 | **Zeilenweises Lesen** |
| 292 | 292 | ||
| 293 | ~~~ | 293 | ~~~c |
| 294 | size_t csv_read(csv_t *csv, FILE *in); | 294 | size_t csv_read(csv_t *csv, FILE *in); |
| 295 | ~~~ | 295 | ~~~ |
| 296 | 296 | ||
| @@ -305,7 +305,7 @@ Rückgabe | |||
| 305 | 305 | ||
| 306 | **Feldzugriff** | 306 | **Feldzugriff** |
| 307 | 307 | ||
| 308 | ~~~ | 308 | ~~~c |
| 309 | size_t csv_nfields(const csv_t *const csv); | 309 | size_t csv_nfields(const csv_t *const csv); |
| 310 | const char *csv_field(const csv_t *const csv, size_t idx); | 310 | const char *csv_field(const csv_t *const csv, size_t idx); |
| 311 | ~~~ | 311 | ~~~ |
| @@ -322,7 +322,7 @@ Rückgabe | |||
| 322 | 322 | ||
| 323 | **Fehlercodes als Textmeldung** | 323 | **Fehlercodes als Textmeldung** |
| 324 | 324 | ||
| 325 | ~~~ | 325 | ~~~c |
| 326 | const char *csv_err_str(csv_err_t csv_err); | 326 | const char *csv_err_str(csv_err_t csv_err); |
| 327 | ~~~ | 327 | ~~~ |
| 328 | 328 | ||
| @@ -351,11 +351,11 @@ Table: Makros | |||
| 351 | 351 | ||
| 352 | Soll beispielsweise das in Deutschland viel häufiger vorkommende Semikolon (`;`) statt einem Komma (`,`) standardmäßig als Trennsymbol zwischen den Feldern einer CSV-Datei benutzt werden sieht der Aufruf zum Compilieren so aus: | 352 | Soll beispielsweise das in Deutschland viel häufiger vorkommende Semikolon (`;`) statt einem Komma (`,`) standardmäßig als Trennsymbol zwischen den Feldern einer CSV-Datei benutzt werden sieht der Aufruf zum Compilieren so aus: |
| 353 | 353 | ||
| 354 | ~~~ | 354 | ~~~sh |
| 355 | cc -DCSV_DEFAULT_SEPARATOR="';'" -o csv-german.o -c csv.c | 355 | cc -DCSV_DEFAULT_SEPARATOR="';'" -o csv-german.o -c csv.c |
| 356 | ~~~ | 356 | ~~~ |
| 357 | 357 | ||
| 358 | Anschließend wird die Datei `csv-german.o` statt `csv.o` zum Projekt dazugelinkt. | 358 | Anschließend wird die Datei `csv-german.o` statt `csv.o` zum Projekt dazu gelinkt. |
| 359 | 359 | ||
| 360 | Die Headerdatei (`csv.h`) bleibt unverändert. | 360 | Die Headerdatei (`csv.h`) bleibt unverändert. |
| 361 | 361 | ||
