Forum: PC-Programmierung Zeiger in C Problem


von Markus (Gast)


Lesenswert?

Servus Leute, ich sitze nun bereits 4 Stunden an einer dummen Aufgabe 
und immer wenn ich gedacht habe ich hätte sie hinbekommen werd ich 
entäuscht.

Mein hauptproblem liegt darin ich soll eine struktur person erstellen wo 
name, vorname und geburtstag drinn stehen.

das habe ich auch ohne probs hinbekommen. dem array habe ich dann mit 
strcpy irgenwelche Zeichen zugefügt und auf dem Bildschirm ausgegeben.

Nun soll eine Funktion geschrieben werden mit Übergabeparameter: Zeiger 
der eine Struktur von person enthält.

ich bin so vorgegangen:

#include "include files.h"
void f1 (struct person*);
void f2 (struct person*);


struct person
  {
    char firstname[20];
    char name[20];
    char birthday[20];
  };

int main (void)
{
  struct person sUserpers;

  strcpy(sUserpers.firstname, "Matthias");
  strcpy(sUserpers.name, "Knab");
  strcpy(sUserpers.birthday, "24.03.1988");
  printf("%s\n", sUserpers.firstname);
  printf("%s\n", sUserpers.name);
  printf("%s\n\n", sUserpers.birthday);

  f1(&sUserpers);
  f2(&sUserpers);

  getch();
  return 0;

}





void f1 (struct person* neu1)
{
  neu1->firstname;

  printf("Firstname:\n");
  scanf ("%s", neu1);

}





void f2 (struct person* neu1)
{
  neu1->firstname;
  printf("%s", neu1);

}


das ganze gibt mir auch das aus was ich eingetippt habe. wenn ich es 
aber nun mit weiteren funktionen erweitere für die anderen beiden arrays 
dann wird mir für alle immer nur die letzte eingabe ausgegeben.
woran liegt dass? und noch ne frage kann ich auch direkt mehrere Zeiger 
an eine Funktion übergeben? ich habe es mit kommas, &, | usw probiert 
aber es klappt irgendwie nicht.

von Nico22 (Gast)


Lesenswert?

Genau so, wie du normalerweise mehrere Variablen übergibst:

int myfunc(int a, int b);

int my_pointer_func(int *a, int *b);

von Antwort (Gast)


Lesenswert?

Dein Problem liegt soweit ich es verstanden habe darin, das du nach dem 
Aufruf von f1 zwar einen neuen Namen (oder was auch imer) eingeben 
kannst, dieser aber nicht übernommen wird. Dies liegt eifnach daran das 
du bei Scanf einen pointer auf einen string (char array) benötigst. Du 
übergibst aber die Addresse auf dein ganzes struct.
1
scanf ("%s", neu1); //hier übergabe des pointers auf das struct
Das funktioniert solange, wie du nur auf "firstname" zugreifst, da die 
startaddresse des firstname-arrays identisch ist mit der startadresse 
des structs, bei den anderen arrays stimmt dies dann aber nicht mehr. Du 
müsstest deinen Code wie folgt anpassen.

Markus schrieb:
> void f1 (struct person* neu1)
> {
>   neu1->firstname;
>
>   printf("Firstname:\n");
>   scanf ("%s", neu1->firstname);
>   scanf("%s", neu1->name)
>
> }

von sebastians (Gast)


Lesenswert?

Diese Anweisung tut nix:
> neu1->firstname;

von Antwort (Gast)


Lesenswert?

sebastians schrieb:
> Diese Anweisung tut nix:
>> neu1->firstname;
Doch, sie funktioniert Einwandfrei

von Antwort (Gast)


Lesenswert?

Hier mal ein kurzes Testprogramm:
1
#include <stdint.h>
2
#include <stdio.h>
3
#include <conio.h>
4
5
struct Person{
6
  char firstname[20];
7
  char secondname[20];
8
};
9
10
void f1(struct Person* bla){
11
  printf("Bitte firstname eingeben: \n");
12
  scanf("%s",bla->firstname);
13
  printf("Bitte secondname eingeben:\n");
14
  scanf("%s", bla->secondname);
15
}
16
17
void f2(struct Person* bla){
18
  printf("Firstname");
19
  printf(bla->firstname);
20
  printf("\n");
21
  printf("Second Name:");
22
  printf(bla->secondname);
23
  getch();
24
25
}
26
int main(void){
27
  struct Person Erster;
28
29
  f1(&Erster);
30
  f2(&Erster);
31
  return 0;
32
}

von Markus (Gast)


Lesenswert?

Nico22 schrieb:
> int my_pointer_func(int *a, int *b);

schon probiert und da kommt halt eben ein fehler:

Unbehandelte Ausnahme bei 0x5dbbde8f (msvcr100d.dll) in Aufgabe 4.exe: 
0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x00000014.

und er zeigt auf die zeile:

*(char *)pointer = (char)ch;
                                    pointer = (char *)pointer + 1;

von Markus (Gast)


Lesenswert?

alles klar hab meinen fehler. ich hab die ganze zeit unterschiedliche 
namen in den übergabewert für den zeiger reingeschrieben. hätte nicht 
gedacht dass es nur mit einem funktioniert.

danke an alle.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> Nico22 schrieb:
>> int my_pointer_func(int *a, int *b);
>
> schon probiert und da kommt halt eben ein fehler:
>
> Unbehandelte Ausnahme bei 0x5dbbde8f (msvcr100d.dll) in Aufgabe 4.exe:
> 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x00000014.
>
> und er zeigt auf die zeile:
>
> *(char *)pointer = (char)ch;
>                                     pointer = (char *)pointer + 1;

Dann steckst dsu falsche POinter in die Funktion hinein.
Ausserdem ist es ziemlich witzlos, über Code zu spekulieren, den man 
nicht kennt.

Ausserdem: Was sollen die Casts da?
Wenn du Pointer umcasten musst (mit deinem jetzigen Wissensstand), dann 
machst du mit Sicherheit einen schweren Fehler.

von Hc Z. (mizch)


Lesenswert?

Antwort schrieb:
> sebastians schrieb:
>> Diese Anweisung tut nix:
>>> neu1->firstname;
> Doch, sie funktioniert Einwandfrei

Ich würde (bei Deinem Kenntnisstand) solche Hinweise nicht einfach 
wegwischen.  Diese Anweisung tut nämlich wirklich nichts.

Dann solltest Du bei Deinem Compiler alle Warnings einschalten (-Wall 
beim gcc).  Und die Warnungen, die dann kommen, auch nicht ignorieren. 
Denn sowohl Deine Argumente für printf als auch scanf in den 
Unterfunktionen im Originalcode sind oberfaul.  Da muss etwas kommen. 
Und hilfreiche Hinweise müssen auch ausgegeben werden.

von Antwort (Gast)


Lesenswert?

Die einzigen Warnungen die ich erhalte (Visual Studio 2008) besagen das 
scanf als unsicher deklariert wurde und man stattdessen lieber scanf_s 
verwenden soll (um buffer overflows zu verhindern).

Dann kläre mich mal auf was genau mein Fehler sein soll. Würde mich 
jetzt schon interessieren.

von Markus (Gast)


Lesenswert?

ich habe nix umgecastet. diese fehlermeldung zeigt ja nicht mal in 
meinen code sondern in einen anderen von vusial studio . wie man 
eigentlich auch sieht da mein code ja oben steht.

weiß jetzt grad nicht mehr wie der code heißt da der fehler ja weg ist.

von Hc Z. (mizch)


Lesenswert?

Antwort schrieb:
> Dann kläre mich mal auf was genau mein Fehler sein soll.

Gerne.  Das Argument ist beide Male „neu1“.  Das ist vom Typ „struct 
person *“.  Da der Formatstring „%s“ lautet, wird aber ein „char *“ 
benötigt.  Nochmal eine der beiden Fehlerstellen:
1
void f1 (struct person* neu1)
2
{
3
  neu1->firstname;                   // Tut nichts
4
5
  printf("Firstname:\n");
6
  scanf ("%s", neu1);                // struct person * bei %s
7
8
}

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:

> meinen code sondern in einen anderen von vusial studio . wie man
> eigentlich auch sieht da mein code ja oben steht.

Dein Code da oben gilt schon lange nichts mehr, weil du ihn in der 
Zwischenzeit ja verändert hast.

Und selbst wenn, passt dein Code mit dem hier, das du als Vorgabe für 
deine Frage benutzt hast
> >> int my_pointer_func(int *a, int *b);
>
> schon probiert und da kommt halt eben ein fehler:

in keinster Weise zusammen

> weiß jetzt grad nicht mehr wie der code heißt da der fehler ja weg ist.

Das heißt nicht viel.
Durch Testen kann man immer nur das Vorhandensein von Fehlern 
nachweisen, nie das Fehlen. Nur weil ein Code nicht gleich abstürzt, 
heißt das noch lange nicht, das er fehlerfrei ist.

von Antwort (Gast)


Lesenswert?

Hc Zimmerer schrieb:
> Gerne.  Das Argument ist beide Male „neu1“.  Das ist vom Typ „struct
> person *“.  Da der Formatstring „%s“ lautet, wird aber ein „char *“
> benötigt.  Nochmal eine der beiden Fehlerstellen:
Falsch, in meinen Beispielen wird beides mal ein char pointer übergeben. 
Nämlich z.B. neu1->firstname. Da firstname ein char array ist erhält man 
durch Angabe des arraynamens ohne weitere klammern oder sonstiges den 
pointer darauf. Es ist identisch zu &(neu1->firstname[0])

Sieh dir meinen  Post von 22:13 Uhr noch einmal genau an.

von Markus (Gast)


Lesenswert?

kann mir bitte nochmal jemand helfen? sitze nun schon seit etlichen 
stunden an der nächsten aufgabe. habe sie nach skript geschrieben und 
auch mal in das buch "c von a bis z" reingeschaut nur werd ich daraus 
nicht wirklich schlau.

und zwar soll ich mehrdimensionale arrays an eine funktion übergeben. 
das klappt auch wunderbar. nur muss ich bei zahlen die kleiner 10 sind 
eine 0 vorschieben. dies habe ich mit einer if abfrage gemacht nur 
klappt es nie egal was ich mache.

kann mir jemand nochmal kurz helfen kann ja eigentlich nicht so viel 
falsch sein. der wert wird ja übergeben.


#include "include files.h"

void f1 (int iy, int ix, int aZahlen[10][10]);

int main (void)
{
    int aZahlen [10][10];
    printf("Zahl eingeben: ");
    scanf("%s", &aZahlen[0][0]);
    f1(0, 0, aZahlen);
    getch();
}

void f1 (int iy, int ix, int aZahlen[10][10])
{
  if (aZahlen[0][0] >= 1)
    {
      printf("%s", aZahlen);
    }
    else
    {
      printf("0%s", aZahlen);
    }
}

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:

>     int aZahlen [10][10];

>     scanf("%s", &aZahlen[0][0]);

Ähm.
Seit wann ist denn %s das korrekte Formatzeichen für einen int?

Detto
     printf("%s", aZahlen);

Da ist es sogar noch schlimmer.
aZahlen ist ein ganzes Array, also viele int. Genau genommen 10 * 10 
also 100 Stück. Und die willst du alle mit einem popeligen %s, der für 
Strings gedacht ist ausgeben.

Nochmal zurück an den Anfang, 3. oder 4. Stunde und nachsehen, welche 
Formatierzeichen es gibt, wann und wo sie verwendet werden müssen.

von Hc Z. (mizch)


Lesenswert?

Antwort schrieb:
> Falsch, in meinen Beispielen wird beides mal ein char pointer übergeben.

Ja, da bin ich ducheinandergekommen, wer was schrieb.  Wie ich aber 
ebenfalls schrieb, bezieht sich das mit dem char * auf das 
Originalposting.  Und in meiner anderen Antwort habe ich das sogar 
zitiert, es wäre somit unschwer erkennbar gewesen, auf was ich mich 
bezog.

Für Dich war das „tut nichts“:

Antwort schrieb:
> sebastians schrieb:
>> Diese Anweisung tut nix:
>>> neu1->firstname;
> Doch, sie funktioniert Einwandfrei

Du schriebst darauf „Doch, sie tut einwandfrei“.  Ohne das „Doch“ wäre 
das noch angegangen, denn natürlich tut das einwandfrei - nichts.

von Markus (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ähm.
> Seit wann ist denn %s das korrekte Formatzeichen für einen int?

he danke man ohne flax. hatte vorher schon %d drinn stehn dacht aber 
dass es nicht stimmen kann weil dann werte von über 200000 immer da 
standen und mit %s wurde mir das richtige ausgegeben.

auf jedenfall scheint es so dass als ich %d am anfang benutzt habe noch 
was falsch war und es mir deshalb so einen mist ausgegeben hat. 
mittlerweile funktioniert das ganze.

es sind immer die kleinen dinge die einem kopfzerbrechen bereiten.

von DirkB (Gast)


Lesenswert?

Markus schrieb:
> hatte vorher schon %d drinn stehn dacht aber
> dass es nicht stimmen kann weil dann werte von über 200000 immer da
> standen und mit %s wurde mir das richtige ausgegeben.

über 200000 war dann die Adresse von aZahlen.

Mit    scanf("%s", &aZahlen[0][0]); hast du Die Zahl als Text (String) 
eingelesen und ab aZahlen abgelegt.
Mit  printf("%s", aZahlen); hast du den String wieder ausgegeben.
Denn &aZahlen[0][0] == aZahlen

von Antwort (Gast)


Lesenswert?

Hc Zimmerer schrieb:
> Antwort schrieb:
>> Falsch, in meinen Beispielen wird beides mal ein char pointer übergeben.
>
> Ja, da bin ich ducheinandergekommen, wer was schrieb.  Wie ich aber
> ebenfalls schrieb, bezieht sich das mit dem char * auf das
> Originalposting.  Und in meiner anderen Antwort habe ich das sogar
> zitiert, es wäre somit unschwer erkennbar gewesen, auf was ich mich
> bezog.
>
Achso, das klärt natürlich alles auf.
> Für Dich war das „tut nichts“:
>
> Antwort schrieb:
>> sebastians schrieb:
>>> Diese Anweisung tut nix:
>>>> neu1->firstname;
>> Doch, sie funktioniert Einwandfrei
>
> Du schriebst darauf „Doch, sie tut einwandfrei“.  Ohne das „Doch“ wäre
> das noch angegangen, denn natürlich tut das einwandfrei - nichts.

Und meine Aussage war auf mein Beispiel bezogen, nicht auf das original. 
Da haben wir aneinander vorbei geredet.

von Hc Z. (mizch)


Lesenswert?

Ja, alles klar.  Also beidseitige Verwechslung :-).  Passiert mal.

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.