Data2006
Anmeldungsdatum: 7. November 2021
Beiträge: 461
|
Moin zusammen, ich habe bischen YouTube weiter geguckt. Kam dann ein Video mit einer Struktur. Habe ich direkt mit Personen[anzahl] angelegt. Jetzt stecke ich wieder fest. Bei der Eingabe wird im 1. Datensatz der Vorname übersprungen. Und die Ausgabe stimmt auch nicht. 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 | #include <stdio.h>
#include <string.h>
struct Person
{
char vorname[10];
char name[10];
char wohnort[15];
};
int main()
{
int anzahl, i;
printf("Wie viele Datensätze wollen Sie eingeben? ");
scanf("%d",&anzahl);
struct Person Personen[anzahl];
for(i=0; i<anzahl;i++)
{
printf("\n%d. Datensatz:\n",i+1);
printf("Vorname: ");
fgets(Personen[i].vorname,10,stdin);
printf("Name: ");
fgets(Personen[i].name,10, stdin);
printf("Wohnort: ");
fgets(Personen[i].wohnort,15, stdin);
}
printf("\n\n");
for(i=0; i<anzahl;i++)
{
printf("%d. Datensatz:\n",i+1);
printf("%s %s\n", Personen[i].vorname, Personen[i].name);
printf("%s\n", Personen[i].wohnort);
}
return 0;
}
|
Ich denke es liegt an fgets und/oder scanf. Richtig? Wie kann ich den Fehler korrigieren? Statt
| struct Person Personen[anzahl];
|
kann man doch bestimmt mit Zeiger machen:
| struct Person *Personen[anzahl];
|
Lieben Dank und gute Nacht,
Heiko Bearbeitet von rklm: Syntaxhighlighting. Bitte mach Dich dringend mit Forum/Syntax vertraut, nutze das Syntaxhighlighting und die Vorschaufunktion!
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 461
|
Moin zusammen. Ich habe noch was probiert. Und zwar getchar(); eingestreut:
printf("Wie viele Datensätze wollen Sie eingeben? ");
scanf("%d",&anzahl);
getchar();
struct Person Personen[anzahl]; Die Eingabe funktioniert jetzt auch. Nur bei der Ausgabe kommt immer zwischen Personen[i].vorname und Personen[i].name ein Zeilenvorschub.
Woher kommt der und wie kann ich den lösen? Liegt das an printf(...) und/oder fgets(...)? Lieben Dank,
Heiko
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Hallo! Ich kenne zwar dein Video nicht, aber entweder hast du nicht richtig aufgepasst oder da fehlen Grundlagen. Data2006 schrieb: Jetzt stecke ich wieder fest. Bei der Eingabe wird im 1. Datensatz der Vorname übersprungen. Und die Ausgabe stimmt auch nicht.
Nicht ausprobiert, vermutlich fehlt ein man fflush kann man doch bestimmt mit Zeiger machen:
| struct Person *Personen[anzahl];
|
Du hast eine Definition erstellt mit struct Person {…}; . Davon erstellst du eine Instanz mit struct Person Personen[anzahl]; . Ein Pointer soll worauf zeigen bei deiner Idee? Also entweder musst du mit malloc/calloc/whatever einen Speicherbereich reservieren, auf den dann dein Zeiger zeigt oder im Stack bereits eine Instanz angelegt haben, auf die du dann zeigen kannst. Ansonsten zeigt dein Pointer ja irgendwohin, im schlimmsten Fall auf einen gültigen Speicherbereich. Dann bekommst du an anderer Stelle Probleme, bspw. beim Auslesen eines Namens, wenn kein '\0' im besagten Bereich ist. Daher initialisiert man Pointer für gewöhnlich mit NULL, damit das Programm bei einem Zugriff an der Stelle geplant abstürzt.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
Das liegt an fgets(). Diese Funktion gibt dir auch den Zeilenwechsel, mit dem du die Eingabe beendet hast. Wenn du den nicht haben willst, musst du den selber entfernen. Aber vorher prüfen ob der auch wirklich da ist. Bei längeren Eingaben kann der fehlen weil vorher abgebrochen wurde. 10 Zeichen sind nicht viel.
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 461
|
So, hier mal das Video: https://www.youtube.com/watch?v=uHoWpdICjhE Wenn ich ein * davor setze, habe ich ein Array mit Zeigern auf die Struktur Person. Und statt . Operator muß ich dann → Operator nehmen. Wie bekomme ich das letzte Zeichen am besten weg? Oder andere Funktion nehmen?
Oder selber ne Funktion holeZeile oder so. Mit getchar() die Zeichen bis zum Enter lesen. Wie gesagt bei Basic gab es ne Funktion left$. Schade das es sowas nicht gibt. Lieben Dank,
Heiko
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 461
|
Dakuan schrieb: Das liegt an fgets(). Diese Funktion gibt dir auch den Zeilenwechsel, mit dem du die Eingabe beendet hast. Wenn du den nicht haben willst, musst du den selber entfernen. Aber vorher prüfen ob der auch wirklich da ist. Bei längeren Eingaben kann der fehlen weil vorher abgebrochen wurde. 10 Zeichen sind nicht viel.
Als Vorname und Namen reicht keine 10 Felder? Ok, ich kann das auch auf 50 setzen. Das sollte nun aber reichen. Lieben Dank,
Heiko
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Data2006 schrieb: So, hier mal das Video: https://www.youtube.com/watch?v=uHoWpdICjhE
Ich gucke aus Prinzip kein YT, aber vielleicht interessiert sich jmd anders dafür. Wenn ich ein * davor setze, habe ich ein Array mit Zeigern auf die Struktur Person. Und statt . Operator muß ich dann → Operator nehmen.
Nein. Dann hast du einen Pointer auf ein nicht existierendes Array. Du musst dann erst Speicher reservieren → man malloc / man calloc .
Wie bekomme ich das letzte Zeichen am besten weg? Oder andere Funktion nehmen?
Bspw. mit oben erwähntem fflush. Oder while getchar() bis nix mehr kommt. Fehlerbehandlung einbauen, wie Dakuan erwähnt hat! Wie gesagt bei Basic gab es ne Funktion left$. Schade das es sowas nicht gibt.
Für was left? Brauchst du einen Substring? left$("lalala", 2) ? Das ginge in C bspw. mit memcpy , bzw. besser strncpy . Musst nur mit UTF-8 ggf. aufpassen.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
Als Vorname und Namen reicht keine 10 Felder?
Es gibt so Vornamen wie "Karl-Heinz" oder "Klaus-Dieter". Wenn die mit Bindestrich sind, gehört das immer zusammen.
Wie bekomme ich das letzte Zeichen am besten weg?
Das können auch mehrere unerwünschte Zeichen sein, wie in meinem aktuellen Projekt. Da mache ich das so: 1
2
3
4
5
6
7
8
9
10
11
12 | void trimm_line( char * line ) {
unsigned char * p = (unsigned char *)line;
int i = strlen( line );
p += i;
while( i-- ){
if ( *--p <= 0x20 ){
*p = '\0';
} else {
return;
}
}
}
|
Das macht jetzt allerdings etwas mehr, indem es alle Zeichen kleiner oder gleich SPACE (0x20) entfernt. In meinem Fall sind das regelmäßig CR/LF Sequenzen ("\r\n") und wenn die nicht da sind passiert auch nichts. Wenn ich jetzt keinen Denkfehler gemacht habe, müsste das in deinem Fall etwa so aussehen:
| ...
fgets(Personen[i].vorname,10,stdin);
trimm_line( &Personen[i].vorname );
...
|
Ich habe das jetzt aber nicht ausprobiert. Wenn der Compiler meckert, will er noch 2 weitere Klammern haben. Ps: das (unsigned char*) ist damit nicht versehentlich UTF-8 codierte Zeichen abgeschnitten werden.
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 461
|
Vielen Dank. Ich habe auch schon eine Lösung gefunden:
#include <stdio.h>
#include <string.h>
struct Person
{
char vorname[10];
char name[10];
char wohnort[15];
};
int main()
{
int anzahl, i;
printf("Wie viele Datensätze wollen Sie eingeben? ");
scanf("%d",&anzahl);
getchar();
struct Person Personen[anzahl];
for(i=0; i<anzahl;i++)
{
printf("\n%d. Datensatz:\n",i+1);
printf("Vorname: ");
fgets(Personen[i].vorname,10,stdin);
Personen[i].vorname[strlen(Personen[i].vorname)-1]=0;
printf("Name: ");
fgets(Personen[i].name,10, stdin);
Personen[i].name[strlen(Personen[i].name)-1]=0;
printf("Wohnort: ");
fgets(Personen[i].wohnort,15, stdin);
Personen[i].wohnort[strlen(Personen[i].wohnort)-1]=0;
}
printf("\n\n");
for(i=0; i<anzahl;i++)
{
printf("%d. Datensatz:\n",i+1);
printf("%s %s\n", Personen[i].vorname, Personen[i].name);
printf("%s\n\n", Personen[i].wohnort);
}
return 0;
}
|
Data2006
(Themenstarter)
Anmeldungsdatum: 7. November 2021
Beiträge: 461
|
Mußte die Länge noch was anpassen:
#include <stdio.h>
#include <string.h>
struct Person
{
char vorname[20];
char name[20];
char wohnort[25];
};
int main()
{
int anzahl, i;
printf("Wie viele Datensätze wollen Sie eingeben? ");
scanf("%d",&anzahl);
getchar();
struct Person Personen[anzahl];
for(i=0; i<anzahl;i++)
{
printf("\n%d. Datensatz:\n",i+1);
printf("Vorname: ");
fgets(Personen[i].vorname,20,stdin);
Personen[i].vorname[strlen(Personen[i].vorname)-1]=0;
printf("Name: ");
fgets(Personen[i].name,20, stdin);
Personen[i].name[strlen(Personen[i].name)-1]=0;
printf("Wohnort: ");
fgets(Personen[i].wohnort,25, stdin);
Personen[i].wohnort[strlen(Personen[i].wohnort)-1]=0;
}
printf("\n\n");
for(i=0; i<anzahl;i++)
{
printf("%d. Datensatz:\n",i+1);
printf("%s %s\n", Personen[i].vorname, Personen[i].name);
printf("%s\n\n", Personen[i].wohnort);
}
return 0;
} Jetzt scheint es zu gehen. LG und gute Nacht,
Heiko
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Prima! Auch wenn es wenig Sinn macht, hier wäre dein Code mit *Personen.
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 | #include <stdlib.h> // malloc und free
#include <stdio.h>
#include <string.h>
struct Person
{
char vorname[20];
char name[20];
char wohnort[25];
};
int main()
{
int anzahl, i;
printf("Wie viele Datensätze wollen Sie eingeben? ");
scanf("%d",&anzahl);
getchar();
struct Person *Personen = NULL;
Personen = malloc( anzahl * sizeof( struct Person ) ); // Speicher reservieren
for(i=0; i<anzahl;i++)
{
printf("\n%d. Datensatz:\n",i+1);
printf("Vorname: ");
fgets(Personen[i].vorname,20,stdin);
Personen[i].vorname[strlen(Personen[i].vorname)-1]=0;
printf("Name: ");
fgets(Personen[i].name,20, stdin);
Personen[i].name[strlen(Personen[i].name)-1]=0;
printf("Wohnort: ");
fgets(Personen[i].wohnort,25, stdin);
Personen[i].wohnort[strlen(Personen[i].wohnort)-1]=0;
}
printf("\n\n");
for(i=0; i<anzahl;i++)
{
printf("%d. Datensatz:\n",i+1);
printf("%s %s\n", Personen[i].vorname, Personen[i].name);
printf("%s\n\n", Personen[i].wohnort);
}
free(Personen); // Speicher wieder freigeben
return 0;
}
|
Interessanter wäre es das so aufzubauen: | struct Person { char *Vorname; char *Nachname; char *Ort };
|
Aber das kommt sicher später 😉
|