Struktur

Neue Frage »

Auf diesen Beitrag antworten »
lilli. Struktur

Hallo,
habe wieder ein Problem mit folgender Aufgabe:

Eine Textdatei kunde.txt liegt vor, die in einer Textzeile einen Kundensatz speichert.
Anrede Vorname Name Strasse Hausnummer Postleitzahl Stadt.

Die Postleitzahl kann nur aus einer Folge der Ziffer 0-9 bestehen. Jeder Kundensatz schließt mit einem newline (\n) am Ende der Zeile. Die Felder eines Datensatzes sind durch Leerzeichen getrennt. Eine Beispieldatei könnte z. B. so aussehen:
Herr Martin Mustermann Musterweg 42 40210 Düsseldorf
Frau Barbara Becker Burgweg 999 28777 Bremen
Schreiben Sie ein C-Programm, dass alle Kundennamen (mit Vornamen und Anrede) ausgibt, die in Düsseldorf unter der Postleitzahl 40210 wohnen.

Meine Ideen:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
struct kunde {
    char anrede;
    char vorname;
    char name;
    char strasse;
    int hausnr;
    int plz;
    char stadt;
};

Ich weiß leider nicht was ich hier machen soll. Ich glaube nicht, dass ich einfach etwas mit printf ausgeben darf. Kann mir jemand bitte helfen?
 
Auf diesen Beitrag antworten »
Karlito

Hallo lilli,

ich denke eine modifizierte printf-Ausgabe sollte hier reichen. Lies die Datei doch Zeichenweise und gib diese immer nur bis zum dritten Leerzeichen pro Zeile aus. Die Leerzeichen zählen und am Ende der Zeile den Leerzeichenzähler zurücksetzen.

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Ich habe damit leider noch Probleme. Wie gebe ich denn Dateien nur bis zum nächsten Leerzeichen aus?

struct kunde k1 = { "Herr","Martin","Mustermann","Musterweg",42,40210,"Duesseldorf"};
printf("%s %s %s %s %d %d %s \n", k1.anrede, k1.vorname, k1.name, k1.strasse, k1.hausnr, k1.plz, k1.stadt);
Auf diesen Beitrag antworten »
Karlito

Sollt ihr denn unbedingt ein struct verwenden?
 
Auf diesen Beitrag antworten »
lilli.

nein steht ja nicht in der aufgabe. ich hab nur an struct gedacht
Auf diesen Beitrag antworten »
Karlito

Ich würde hier kein struct verwenden.

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv){
	FILE *fptr;
	char current_char;
	int space_counter = 0;

	fptr = fopen("kunde.txt", "r");
	
	while(!feof(fptr)){
		fread(&current_char, sizeof(char), 1, fptr); 
		if(current_char == ' '){
			space_counter++;
		}
		if(space_counter<3){
			printf("%c", current_char);
		}
		if(current_char == '\n' && space_counter != 0){
			space_counter = 0;
			printf("\n");
		}
	}

	return 0;
}


VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Das sieht schwer aus geschockt . Aber fread /fopen hatten wir schon und so sollten wir es auch lösen.
Ich weiß leider nicht wie ich den Kundensatz reinbringe. Wenn ich dein Programm abspielen lasse kommt keine Ausgabe.
Auf diesen Beitrag antworten »
Karlito

Du musst eine Datei "kunde.txt" erstellen. Bei mir sieht sie so aus:

code:
1:
2:
Herr Martin Mustermann Musterweg 42 40210 Düsseldorf
Frau Barbara Becker Burgweg 999 28777 Bremen


VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Die Datei lässt sich bei mir nicht öffnen:
code:
1:
2:
3:
4:
5:
6:
7:
8:
int main()
{
    FILE *a;
    a = fopen("kunde.txt", "w");
    fprintf(a,"Herr Martin Mustermann Musterweg 42 40210  Duesseldorf");
    fclose(a);
}
Auf diesen Beitrag antworten »
Karlito

Du kannst die Datei doch mit dem Editor anlegen. Dazu braucht es kein selbst geschriebenes Programm.

Aber wenn die Datei noch nicht exisitert und du willst sie mit fopen zum schreiben öffnen, dann musst du "w+" verwenden.
Auf diesen Beitrag antworten »
lilli.

wir müssen das schriftlich machen, ist eine aufgabe aus einer probeklausur
Auf diesen Beitrag antworten »
lilli.

Hab das jetzt mal auch mit dem Editor einfach gemacht.
Das Programm gibt mir aber nur Herr Martin Mustermann aus
Auf diesen Beitrag antworten »
lilli.

also das mit dem Counter hab ich jetzt verstanden, aber wie krieg ich das hin, dass nur die gewünschten Daten ausgegeben werde. Also wie überspringt er die Adresse?
Auf diesen Beitrag antworten »
as_string

Hallo,

vielleicht noch ein paar andere Punkte was die c-lib betrifft.
Ich verwende eigentlich ganz gerne fgets() wenn ich eine Datei zeilenweise lesen muss.
Bei einem solchen Datensatz wäre eventuell strtok() ein gangbarer Weg, besser noch eine "verbesserte" Version, wie strtok_s() bei MS VC oder so.

Aber nur so als Tipp, die Lösung von Karlito ist natürlich vollkommen ok und hat sicherlich auch Vorteile. Z. B. würde der Ansatz mit strtok mehrere aufeinander folgende Leerzeichen zu einem Trenner zusammen fassen, was eventuell auch gar nicht ganz richtig wäre, auch wenn es bei den hier gezeigten Daten kein echtes Problem darstellen würde.

Gruß
Marco
Auf diesen Beitrag antworten »
Karlito

@ lilli
Hast Du noch irgendetwas an meinem Code modifiziert? Bei mir läuft es so ohne Probleme, bis auf die Tatsache, dass wohl noch Sonderzeichen Ausgegeben werden, welches das Dateiende kodieren.

@as_string
Danke für die Anmerkung. Aber strtok würde hier wirklich nicht funktionieren, da so keine leeren Felder zulässig wären. Ansonsten ist das sicher die elegantere Methode. Ich habe auch über fscanf nachgedacht, bin aber bei einer naiven Variante geblieben, weil das mit nur wenigen pointern auskommt und somit für Einsteiger mMn am freundlichsten ist.
Auf diesen Beitrag antworten »
lilli.

Bei mir wird Folgendes ausgegeben:
Herr Martin Mustermann
Frau Barbara Becker

Aber eigentlich sollte ja nur der Datensatz für Düsseldorf angegeben werden mit der PLZ
Auf diesen Beitrag antworten »
lilli.

und ich habe deinen code nicht verändert
Auf diesen Beitrag antworten »
Karlito

Entschuldigung, das habe ich überlesen. Ich denke dann könnte es sinnvoll sein, mit einem struct zu arbeiten. Und mit fscanf.

Wenn dir dazu nichts einfällt, schreibe ich ein entsprechendes Programm, aber versuche mal bitte selbst eins zu schreiben.

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Fscanf ist doch dafür da am Ende selbst etwas zu schreiben/einzulesen?
Stimmt der Aufbau so jetzt muss ich nur noch fscanf einfügen oder fprintf, ich muss ja nur was ausgeben

#include <stdio.h>
#include <stdlib.h>

struct kunde {
char anrede;
char vorname;
char name;
char strasse;
int hausnr;
int plz;
char stadt;
};


int main(void) {
int c;
FILE *datei;

datei=fopen("kunde.txt", "r");
if(datei != NULL) {
while( (c=fgetc(datei)) != EOF)
putchar(c);
}

}
Auf diesen Beitrag antworten »
Karlito

Mit dem Programm gibst du einfach nur aus, was du einliest. Außerdem brauchst du für das struct Feldlängen, da hier ja nicht nur ein einzelnes Zeichen gelesen werden soll, sondern ein string (char-Array).

fscanf kann verwendet werden, um daten aus einer datei zu lesen (nicht verwechseln mit scanf). fprintf schreibt in dateien. Das brauchst du hier auch nicht.

printf bietet sich an, da du dann einfach soetwas machen kannst:
code:
1:
printf("%s %s %s\n", kunde.anrede, kunde.vorname, kunde.name);


Schau dir mal fscanf an und wie man damit dateien auslesen kann. Ich gehe derweil mal in die Mensa Abendbrot essen Augenzwinkern

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

ok danke ich versuch es mal.
und guten Appetit ;D
Auf diesen Beitrag antworten »
lilli.

Hab die Werte eingelesen und versucht auszugeben, was aber leider nicht klappt.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
#include <stdio.h>
#include <stdlib.h>

struct kunde {
    char anrede[50];
    char vorname[50];
    char name[50];
    char strasse[50];
    int hausnr;
    int plz[8]; //wegen 0-9
    char stadt[];
};


int main(void) {
   int c;
   FILE *datei;
   struct kunde k;

   datei=fopen("kunde.txt", "r");
   while(!feof(datei)){
    fscanf(&k,sizeof(struct kunde),1,datei);
    printf("%s %s %s %d %s",k.anrede, k.vorname, k.name, k.plz, k.stadt);
   }
   fclose(datei);
}
Auf diesen Beitrag antworten »
Karlito

Der Ansatz ist ganz gut, hat aber ein paar Mängel:

- du hast fscanf falsch verwendet
- warum hat stadt keine länge?
- plz würde ich als string deklarieren, das macht das leben leichter
- genauso die hausnummer

Dann fehlt noch der Vergleich auf Düsseldorf und 40210.

Versuchs noch mal.

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Kann ich anstelle von scanf auch fread nutzen? Und wie macht man VergleicheP?
Auf diesen Beitrag antworten »
lilli.

Hab was gefunden mit strcmp. Muss ich if-Anweisungen aufstellen?
Auf diesen Beitrag antworten »
Karlito

Fread geht auch. Ich finde fscanf hier aber Praktischer. strcmp ist hier genau der richtige Ansatz Ich war mal so frei:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

//beachte, dass char nicht ausreicht! Es handelt sich um Strings.
//Strings sind nichts anderes als char-Arrays.
typedef struct kunde {
    char anrede[50];
    char vorname[100];
    char name[100];
    char strasse[200];
    char hausnr[10]; //Hausnummern enthalten auch oft Buchstaben, deswegen kein int
    char plz[6]; //muss mindestens 6 lang sein, wegen \0 Terminierung! char[] wegen führender 0
    char stadt[100];
} kunde_t;

int main(int argc, char **argv){
  FILE *fptr;
  kunde_t kunde;

  fptr = fopen("kunde.txt", "r");

  while(!feof(fptr)){
    //Die Zahlen hinter den s geben ein Limit für 
    //die Länge an, so dass nicht über die Länge des
    //Ziel-Arrays hinaus gelesen werden kann
    //Wichtig! Das Limit muss eins kleiner sein
    //als die Länge des Arrays, da nach den eingelesenen
    //Zeichen noch die Terminierung eingefügt wird
    fscanf(fptr, "%49s%99s%99s%199s%9s%6s%99s", 
        kunde.anrede,
        kunde.vorname,
        kunde.name,
        kunde.strasse,
        kunde.hausnr,
        kunde.plz,
        kunde.stadt);

    //strcmp gibt nicht! 1 zurück, wenn sich die beiden strings unterschreiden,
    //sondern eine Zahl, die Auskunft über den Unterschied gibt.
    if(!strcmp(kunde.stadt, "Düsseldorf") && !strcmp(kunde.plz, "40210")){
      printf("%s %s %s\n", kunde.anrede, kunde.vorname, kunde.name);
    }
  }

  return 0;
}


VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

vielen dank aber bei mir wird nix ausgegeben unglücklich
Auf diesen Beitrag antworten »
Karlito

Dann schaue bitte mal nach unterschieden zwischen dem Vergleich und der Textdatei. Außerdem könnte es ein Problem mit Sonderzeichen geben. Also versuche mal bitte "ü" durch "ue" bei Düsseldorf auszutauschen.

Ich habe es bei mir getestet und es läuft. Ich verwende jedoch Linux. Es kann durchaus sein, solltest Du Windwos verwenden, dass es dort zu Problemen kommt.

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Ja lag am ü. Stimmt folgende Ausgabe:

Herr Martin Mustermann.

Sind ja dann alle Kundennamen die in Düsseldorf wohnen
Auf diesen Beitrag antworten »
Karlito

Schön, freut mich zu hören! Solltest Du irgendetwas an meinem Programm nicht verstehen, dann gerne nachfragen.

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

Vielen lieben Dank smile , hab alles soweit verstanden smile
Auf diesen Beitrag antworten »
lilli.

nur noch eine Sache. Was sagt diese Zeile aus, das was in Klammern steht?
int main(int argc, char **argv)
Auf diesen Beitrag antworten »
Karlito

Das ist die Deklaration der main Funktion. Diese ist bei C-Programmen immer der Einstiegspunkt für die Ausführung des Programmes. Bei einem Lauffähigen Programm wird immer als erstes die main-Funktion aufgrufen und die gesamte Programmausführung endet mit ihr.

Die Main Funktion hat meist folgenden Prototyp:
int main(int, char**);

Das heitß, dass sie einen Integer zurückgibt (der Kann von einem anderen Programm nach der Ausführung geprüft werden, dabei heißt 0 dass alles OK ist und alles andere dass irgendetwas nicht in Ordnung ist). Weiterhin werden beim Aufruf des Programmes der main Funktion immer 2 Parameter übergeben. Die Anzahl der Argumente (oder aus Parameter) auf der Kommandozeile (argc = argument count) und ein array mit den Kommandozeilenparameter selbst (argv = argument vector).
Dabei ist argc immer mindestens 1, da der erste Parameter immer der Programmname selbst ist.

Argumente eines Programmes sind die Dinge die man oft hinter den Aufruf des Programmes schreibt. So zum beispiel unter windows für den shutdown-befehl "shutdown \s \t 0". Dieses Programm hätte 3 Argumente und damit wäre argc=4. Weiterhin wären argv[0] ="shutdown.exe", argv[1] = "\s", argv[2] = "\t" und argv[3] = "0".

Du kannst das gerne mal mit folgendem Programm ausprobieren:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdlib.h>
#include <stdio.h>

//der andere Name der Parameter von main soll dir 
//nur zeigen, dass die namen  keine rolle spielen.
//Es muss nur der Prototyp int main(int, char **) 
//übereinstimmen
int main (int anzahl_argumente, char **argumente){
	int i;
	for (i=0;i<anzahl_argumente; i++){
		printf("argumente[%d]: \"%s\"\n", i, argumente[i]);
	}

	return 0;
}


Führe einfach das erzeugte Programm auf der Kommandozeile mit verschiedenen Parametern (beliebig) aus.

VG,

Karlito
Auf diesen Beitrag antworten »
lilli.

danke, das war echt verständlich großes Grinsen
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »