Forum: PC-Programmierung Programm zur Datenanalyse schreiben (C)


von Anja (Gast)


Lesenswert?

Hallo wir haben von unseren Informatiklehrer eine Gruppenhausaufgabe 
bekommen, die wir eigentlich alleine Lösen sollten.
Nun fällt unser Unterricht allerdings aus (Lehrer wird sehr lange Krank 
sein) und die Hausaufgaben werden nun nicht mehr abgegeben, deshalb 
wollte ich hier einmal fragen, wie man auf die Lösung kommt, bzw was an 
dem unteren Code* falsch läuft



Aufgabe:
In der Datei “staedte.csv” sind die Städte eines Bundeslands, das 
Bundesland selbst und die Anzahl der Bewohner dieser
Städte, getrennt durch Semikolons, aufgelistet.
Schreibe ein Programm, das für ein gegebenes Bundesland alle Städte 
findet, in denen mindestens eine vorgegebene
Anzahl n an Menschen leben. Die Ausgabe soll mit Hilfe der Funktion 
write_file in die Datei “resultat.txt” erfolgen,
und für jeden Eintrag eine Zeile enthalten, die das Format Die Stadt 
Nürnberg hat 505664 Einwohner. befolgt. Zur
Vereinfachung kannst du davon ausgehen, dass die Länge dieses Strings 
niemals 100 Zeichen überschreitet.
In dieser Aufgabe sollen das Bundesland und die Anzahl n als Parameter 
direkt beim Aufruf des Programms übergeben
werden. Einen beispielhaften Aufruf mit Parametern kannst du in Listing 
2 Zeile 3 sehen. In C stehen die übergebenen
Parameter als char** argv zur Verfügung. In argv[1] und argv[2] werden 
jeweils das erste und das zweite
Argument übergeben. (argv[0] ist für den Programmnamen reserviert.)

Verfügbarer Code:

intput3.c  (darf nicht verändert werden)
1
#include <stdio.h> 
2
#include <stdlib.h> 
3
#include <errno.h> 
4
#include <string.h> 
5
#include "input3.h" 
6
7
int MAX_LAENGE_STR = 255; 
8
int MAX_LAENGE_ARR = 100; 
9
10
void write_file(char *result[], int len) { 
11
    FILE *fp = fopen("resultat.txt", "w"); 
12
    if (fp == NULL){ 
13
        perror("resultat.txt"); 
14
        exit(1); 
15
    } 
16
    for (int i=0; i<len; i++) { 
17
        fprintf(fp, "%s\n", result[i]); 
18
    } 
19
    fclose(fp); 
20
} 
21
22
int read_file(char *dateiname, char staedte[][MAX_LAENGE_STR], char laender[][MAX_LAENGE_STR], int bewohner []) { 
23
    FILE *fp = fopen(dateiname, "r"); 
24
25
    if (fp == NULL){ 
26
        perror(dateiname); 
27
        exit(1); 
28
    } 
29
30
    char stadt[MAX_LAENGE_STR]; 
31
    char land[MAX_LAENGE_STR]; 
32
    int anzahl; 
33
    int i = 0; 
34
    int len; 
35
36
    while(fscanf(fp, "\"%[^\"]\";\"%[^\"]\";%d\n", stadt, land, &anzahl) != EOF) 
37
    { 
38
        if (i >= MAX_LAENGE_ARR) { 
39
            printf("ERROR: Die Datei ist größer als erwartet!"); 
40
            return i; 
41
        } 
42
        len = strlen(stadt) + 1; 
43
        strncpy(staedte[i], stadt, len-1); 
44
        staedte[i][len-1] = '\0'; 
45
46
        len = strlen(land) + 1; 
47
        strncpy(laender[i], land, len-1); 
48
        laender[i][len-1] = '\0'; 
49
50
        bewohner[i] = anzahl; 
51
        i++; 
52
    } 
53
    fclose(fp); 
54
    return i; 
55
}

input3.h (darf nicht verändert werden)
1
extern int MAX_LAENGE_ARR; 
2
extern int MAX_LAENGE_STR; 
3
4
void write_file(char *result[], int len); 
5
int read_file(char *dateiname, char staedte[][MAX_LAENGE_STR], char laender[][MAX_LAENGE_STR], int bewohner []);

staedte.csv
1
"Essen";"Nordrhein-Westfalen";574635 
2
"Bremen";"Bremen";547340 
3
"Dresden";"Sachsen";523058 
4
"Leipzig";"Sachsen";522883 
5
"Hannover";"Niedersachsen";522686 
6
"Nürnberg";"Bayern";505664 
7
"Duisburg";"Nordrhein-Westfalen";489599 
8
"Bochum";"Nordrhein-Westfalen";374737 
9
"Wuppertal";"Nordrhein-Westfalen";349721 
10
"Bonn";"Nordrhein-Westfalen";324899 
11
"Bielefeld";"Nordrhein-Westfalen";323270 
12
"Mannheim";"Baden-Württemberg";313174 
13
"Karlsruhe";"Baden-Württemberg";294761 
14
"Münster";"Nordrhein-Westfalen";279803 
15
"Wiesbaden";"Hessen";275976


Und hier der Code* :
1
#include <stdio.h> 
2
#include <stdlib.h> 
3
#include <string.h> 
4
#include "input3.h" 
5
6
/* Die Konstanten: 
7
*  int MAX_LAENGE_STR - die maximale String Länge 
8
*  int MAX_LAENGE_ARR - die maximale Array Länge 
9
*  sind input3.c auf jeweils 255 und 100 definiert 
10
*/ 
11
12
int main(int argc, char **argv) { 
13
    if (argc < 3) { 
14
        printf("Aufruf: %s <anzahl> <bundesland>\n", argv[0]); 
15
        printf("Beispiel: %s 100 Bayern\n", argv[0]); 
16
        printf("Klein-/Großschreibung beachten!\n"); 
17
        exit(1); 
18
    } 
19
    int anzahl = atoi(argv[1]); 
20
    char *bundesland = argv[2]; 
21
22
    // Statisch allokierter Speicher 
23
    char staedte[MAX_LAENGE_ARR][MAX_LAENGE_STR]; 
24
    char laender[MAX_LAENGE_ARR][MAX_LAENGE_STR]; 
25
    int bewohner[MAX_LAENGE_ARR]; 
26
27
    int len = read_file("staedte.csv", staedte, laender, bewohner); 
28
29
    // Hier implementieren 
30
    char ** jg; 
31
    int cc = 0; 
32
    int cc_jg = 0; 
33
34
    for(int i = 0; i < len; i++) { 
35
        if((strcmp(bundesland, laender[i]) == 0) && (bewohner[i] >= anzahl)) { 
36
            cc ++; 
37
        } 
38
    } 
39
40
    jg = (char **) malloc(MAX_LAENGE_ARR*sizeof(char *));; 
41
    for (int j = 0; j < len; j++) { 
42
        jg[j] = (char*)malloc(MAX_LAENGE_STR*sizeof(char)); 
43
    } 
44
45
    for(int i = 0; i < len; i++) { 
46
        if((strcmp(bundesland, laender[i]) == 0) && (bewohner[i] >= anzahl)) { 
47
            sprintf(jg[cc_jg], "Die Stadt %s hat %d Einwohner.", staedte[i], bewohner[i]); 
48
            cc_jg++; 
49
        } 
50
    } 
51
52
// Mithilfe von write_file(...) soll das Ergebnis in die "resultat.txt" 
53
    write_file(jg, cc_jg); 
54
55
    // Dynamisch allozierter Speicher muss hier freigegeben werden. 
56
    for(int l = 0; l < cc; l++) { 
57
        free(jg[l]); 
58
    } 
59
    free(jg); 
60
    return 0; 
61
}



Der Code an sich müsste funktionieren, nur wird keine TxT erstellt, also 
irgendwas stimmt dort nicht.

Ich weiß es ist viel, aber ihr seht die Probleme doch bestimmt schneller 
als wir:)

Mit freundlichen Grüßen

Anja

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hmm, hier funktioniert es:
1
$ ./main 250000 Hessen
2
$ cat resultat.txt 
3
Die Stadt Wiesbaden hat 275976 Einwohner.
4
$ ./main 250000 Sachsen
5
$ cat resultat.txt
6
Die Stadt Dresden hat 523058 Einwohner.
7
Die Stadt Leipzig hat 522883 Einwohner.

Fehler, der allerdings die Funktion nicht beeinträchtigt: du allozierst 
in jg[i] "len" Arrays, gibst davon aber unten nur "cc" wieder frei. 
Eigentlich wolltest du wohl auch nur "cc" allozieren.

Effizienter lässt sich das machen, indem man den Vergleich nicht zweimal 
laufen lässt, sondern bei jeden Treffer zuerst das entsprechende Array 
jg[i] alloziert und danach mit sprintf() füllt. Dann brauchst du nur 
eine der Variablen "cc" und "cc_jg".

von Anja (Gast)


Lesenswert?

Jörg W. schrieb:
> Hmm, hier funktioniert es:
> $ ./main 250000 Hessen
> $ cat resultat.txt
> Die Stadt Wiesbaden hat 275976 Einwohner.
> $ ./main 250000 Sachsen
> $ cat resultat.txt
> Die Stadt Dresden hat 523058 Einwohner.
> Die Stadt Leipzig hat 522883 Einwohner.
>
> Fehler, der allerdings die Funktion nicht beeinträchtigt: du allozierst
> in jg[i] "len" Arrays, gibst davon aber unten nur "cc" wieder frei.
> Eigentlich wolltest du wohl auch nur "cc" allozieren.
>
> Effizienter lässt sich das machen, indem man den Vergleich nicht zweimal
> laufen lässt, sondern bei jeden Treffer zuerst das entsprechende Array
> jg[i] alloziert und danach mit sprintf() füllt. Dann brauchst du nur
> eine der Variablen "cc" und "cc_jg".

Hallo:)

Wie hast du das hinbekommen?

Bzw wie hast du es geschafft, dass du eine Eingabe hin bekommst? vlt 
liegt da unser Problem.

Ui, danke ich werde es mal verbessern, soweit ich es bei mir zum laufen 
bekomme.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Anja schrieb:
> Bzw wie hast du es geschafft, dass du eine Eingabe hin bekommst?

Steht doch oben, die Eingabe erfolgt auf der Kommandozeile. War in der 
Aufgabenstellung so gefordert.

von Jemand (Gast)


Lesenswert?

Was haben eigentlich Semikolons in einer CSV-Datei verloren?

von Anja (Gast)


Lesenswert?

Jörg W. schrieb:
> Anja schrieb:
>> Bzw wie hast du es geschafft, dass du eine Eingabe hin bekommst?
>
> Steht doch oben, die Eingabe erfolgt auf der Kommandozeile. War in der
> Aufgabenstellung so gefordert.

Achso stimmt, leider benutze ich CodeBlocks, gibt es da eine Möglichkeit 
dies so einzugeben?

von Anja (Gast)


Lesenswert?

Anja schrieb:
> Jörg W. schrieb:
>> Anja schrieb:
>>> Bzw wie hast du es geschafft, dass du eine Eingabe hin bekommst?
>>
>> Steht doch oben, die Eingabe erfolgt auf der Kommandozeile. War in der
>> Aufgabenstellung so gefordert.
>
> Achso stimmt, leider benutze ich CodeBlocks, gibt es da eine Möglichkeit
> dies so einzugeben?

Hat funktioniert, ich bedanke mich und wünsche noch eine gute Nacht

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jemand schrieb:
> Was haben eigentlich Semikolons in einer CSV-Datei verloren?

In deutscher Umgebung mehr als üblich, da das Komma bei uns 
Dezimaltrenner ist.  Trotzdem nennt sie deshalb niemand SSV-Datei. ;-)

von Cmdr Data (Gast)


Lesenswert?

Jemand schrieb:
> Was haben eigentlich Semikolons in einer CSV-Datei verloren?

Character Separated Values, vielleicht?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.