# Ergänzung Anweisung mit PTR



## Java The Hutt (14. Feb 2019)

Hallo,

Ich habe folgende Aufgabe in C, leider habe ich keinen Lösungsansatz. Eventuell kann mir jemand sagen, wie die Lösung lautet und dazu bitte eine Erklärung hinzufügen 


Ergänzen Sie die for – Anweisung im folgenden Programm so, dass alle 3 Parameter durch den Zeiger ptr definiert werden! Ergänzen Sie auch die anderen unvollständigen Anweisungen.


```
#include <stdio.h>
#include <conio.h>

short abc(char *txt){ char *ptr;
for (.....................; ........................ ;......................... );
return ..................................;
}

int main() {
char txt[25] = "Hallo Welt";
int i = 0;
printf("\nIhr Text: "); 
gets(txt); 
fflush(stdin); 
printf("\n Der Text enthält %d Zeichen.", abc(txt)); 
getch()
return 0;
}
```


----------



## mihe7 (14. Feb 2019)

Java The Hutt hat gesagt.:


> Ich habe folgende Aufgabe in C, leider habe ich keinen Lösungsansatz.




```
Zu Beginn: 

txt
|
v
Text im Speicher$
^
|
ptr

Es gilt: ptr - txt == 0

Am Ende:

txt
|
v
Text im Speicher$
                ^
                |
               ptr

Es gilt: ptr - txt == 16
```
Das '$' wird hier aus Gründen der Darstellung verwendet. Bei Dir wird das Ende der Zeichenkette durch eine 0 markiert.


----------



## Java The Hutt (14. Feb 2019)

Hmm... hier mein Lösungsansatz. Der leider nicht funktioniert...


```
#include <stdio.h>
#include <conio.h>

char abc(char *txt)
{
    char *ptr;
    //Lösungsansatz, überlegung:
        // Pointer soll die Adresse annehmen von Txt.
        // Pointer soll maximal erhöht werden, bis er die letzte Stelle von Txt erreicht hat
    for (*ptr == *txt ; *ptr<*txt ; *ptr++  );
    printf("Ausgabe erscheint nur, wenn ein Printf hier steht")
    // Pointer - Text = Anzahl der Stellen.
    return ((*ptr) - (*txt));
}

int main()
{
    char txt[25];
    int i = 0;
    printf("\nIhr Text: ");
    gets(txt);
    fflush(stdin);
    printf("\n Der Text enthaelt %d Zeichen.", abc(txt));
    getch();
    return 0;
}
```


----------



## thecain (14. Feb 2019)

Was funktioniert nicht? 

warum vergleichst du *ptr mit *txt?

Was erwartest du von der Anweisung im for?


----------



## Java The Hutt (14. Feb 2019)

thecain hat gesagt.:


> Was funktioniert nicht?
> 
> warum vergleichst du *ptr mit *txt?
> 
> Was erwartest du von der Anweisung im for?



Ich wollte die Stelle meines (Ptr) an die erste Stelle des Textes (txt) setzen.
Das ganze soll solange gehen, bis Ptr an der letzten Stelle von Txt ist.

und zurückgeben möchte ich dann den Zahlenutnerschied von Txt und meinem Pointer, sprich, die Buchstabenanzahl


----------



## thecain (14. Feb 2019)

Dann musst du eine Zuweisung machen und keinen vergleich.
Dann musst du dir überlegen, wie du erkennst, wann der Text zuende ist, da du ja die Länge nicht kennst, nur den Startpointer. @mihe7 hat da ja einen guten Hinweis gegeben.


----------



## Java The Hutt (14. Feb 2019)

thecain hat gesagt.:


> Dann musst du eine Zuweisung machen und keinen vergleich.
> Dann musst du dir überlegen, wie du erkennst, wann der Text zuende ist, da du ja die Länge nicht kennst, nur den Startpointer. @mihe7 hat da ja einen guten Hinweis gegeben.



Das hatte ich eig probiert 
Also,

```
char *ptr = txt;
```
 damit habe ich meinem Pointer die Speicheradresse von dem Text (txt)


```
for (*ptr = 0; *ptr < *txt; *ptr++);
```
Damit versuche ich, dem Pointer den Startwert 0 zugeben. Die Schleife soll solange durchlaufen, bis Ptr die größe von txt hat. und solange Ptr um 1 erhöhen.
Damit versuche ich gedanklich, dass Txt an seiner Stelle bleibt, aber mit jedem Durchlauf bis Txt Pointer erhöht wird um die Anzahl der Buchstaben in dem Char.

```
return ((*ptr) - (*txt));
```
Danach möchte ich, dass Text vom Ptr abgezogen wird, sodass ein Zahlenwert erscheint...
Aber es klappt leider nicht


----------



## thecain (14. Feb 2019)

Java The Hutt hat gesagt.:


> Damit versuche ich, dem Pointer den Startwert 0 zugeben


Wie kommst du darauf das *txt die Länge ist?

Da stimmt so einiges nicht, auch an den Überlegungen. Dir fehlen viele Grundlagen zu Pointer. Lies dir die lieber nochmals durch.


----------



## Java The Hutt (14. Feb 2019)

Ich habe jetzt das ganze nochmal einfach aufgebaut. 

```
int main()
{

    int Zahl[] = {5,1,2,3,4,4,432,4,34,4,4,4,324,43,34,43,432};
    int *PtrZahl;
    PtrZahl = Zahl;
    printf("\nAnzahl Zahlen: \t\t\t\t %d",sizeof(Zahl) / sizeof(*PtrZahl));

    char buchstabe [] = {'H', 'a', 'l', 'l', '\0'};
    char * PtrBuchstabe;
    PtrBuchstabe = buchstabe;
    printf("\nAnzahl Buchstaben:\t\t\t %d",(sizeof(buchstabe)/sizeof(*PtrBuchstabe))-1);


    char zeichenkette [] = "Hallo Welt ich bin die Zeichenkette";
    char * PtrZeichenkette;
    PtrZeichenkette = zeichenkette;
    printf("\nAnzahl Zeichen der Zeichenkette: \t %d", (sizeof(zeichenkette)/sizeof(*PtrZeichenkette))-1);


}
```

Das klappt so soweit.

Wenn ich nun aber die Funktion übergebe und sämtliche Zählungen gleich lasse, erhalte ich nicht mehr den richtigen Wert.


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

char funktionzaelen(char *zeichenkette){


    char * PtrZeichenkette;
    PtrZeichenkette = zeichenkette;
    printf("\nAnzahl Zeichen der Zeichenkette: \t %d", (sizeof(zeichenkette)/sizeof(*PtrZeichenkette))-1);

}

int main()
{


    char zeichenkette [] = "Hallo Welt ich bin die Zeichenkette";
    funktionzaelen(zeichenkette);
}
```

Ich schließe darauf, dass es ein Problem bei der Übergabe an die Funktion gibt. Kann mir da jemand helfen?


----------



## mihe7 (14. Feb 2019)

@Java The Hutt in meinem "Bild" kannst Du annehmen, dass ptr der Fuß des Pfeils ist, *ptr die Pfeilspitze.

Anders formuliert: ptr speichert eine Adresse, *ptr kennzeichnet den Wert, der an dieser Adresse steht.


----------



## mihe7 (14. Feb 2019)

Java The Hutt hat gesagt.:


> Hmm... hier mein Lösungsansatz.


Die Lösung MUSS genauso aussehen, wie sie vorgegeben ist. Das ist ein Lückentext. Du darfst nur die Lücken füllen.


----------



## Java The Hutt (14. Feb 2019)

mihe7 hat gesagt.:


> Die Lösung MUSS genauso aussehen, wie sie vorgegeben ist. Das ist ein Lückentext. Du darfst nur die Lücken füllen.


Kannst du mir bitte zeigen, wie du es lösen würdest?


----------



## Java The Hutt (14. Feb 2019)

Bzw oder gemeinsam

Ich würde als erstes, den Wert festlegen den der Ptr annehmen soll:

```
short abc(char *txt)
{
    char *ptr;
    ptr = &txt[0];

    for (; ; );
    return ;
}
```


----------



## Java The Hutt (14. Feb 2019)

Java The Hutt hat gesagt.:


> Bzw oder gemeinsam
> 
> Ich würde als erstes, den Wert festlegen den der Ptr annehmen soll:
> 
> ...


----------



## mihe7 (14. Feb 2019)

Das sieht schon mal nicht schlecht aus. 

Nachtrag: Du hast als Parameter einen Pointer, den kannst Du direkt einem anderen Pointer zuweisen.


----------



## Thallius (14. Feb 2019)

```
for(ptr = txt; *ptr != 0; ptr++);
return ptr - txt;
```


----------



## mihe7 (14. Feb 2019)

@Thallius jetzt bin ich schon fast erschrocken, dass @Java The Hutt plötzlich die Lösung aus dem Ärmel schüttelt


----------



## Java The Hutt (14. Feb 2019)

Bevor ich die Lösung gesehen hatte, war ich soweit:

```
short abc(char *txt)
{
    char *ptr;
    for (ptr = txt; *ptr < 25 ; (*ptr)++);
    return ptr-txt;
```

Daher eine Frage;
Warum != 0?

Edit:
Weil \0 das Beenden des Strings ist?


----------



## Java The Hutt (14. Feb 2019)

In der Aufgabe ist in der Main Funktion die Variable I vorhanden. Wofür steht diese?


----------



## mihe7 (14. Feb 2019)

Java The Hutt hat gesagt.:


> Daher eine Frage Fragen;


Das ist gut, dass Du Dich nicht mit der fertigen Lösung zufrieden gibst.

Stell Dir mal den Speicher als ein großes Array vor, ein Byte folgt dem nächsten. Sagen wir mal, ab Adresse 1000 stünde der Text, den Deine Funktion verarbeiten soll.

Du bekommst einen Zeiger auf diesen Text. Ein Zeiger speichert einfach eine Adresse, ganz analog zum Array-Index. Dein txt-Parameter hätte in diesem Beispiel einfach den Wert 1000. 

Deine Funktion bekommt also nur die Startadresse, woher soll sie nun wissen, wo der Text endet? In C lautet die Regel für Zeichenketten, dass diese mit einer 0 terminiert werden. D. h. die Zeichenkette belegt ein Byte mehr als sie Text enthält.

Beispielhaft könnte der Speicher so belegt sein (die Spalte Zeichen dient nur der Darstellung):


```
Addr Wert Zeichen
1000 0x54 'T'
1001 0x65 'e'
1002 0x73 's'
1003 0x74 't'
1004 0x00
```


----------



## Java The Hutt (14. Feb 2019)

Okay vielen Dank!
Da hat bei meinen Lösungen oft nicht ganz soooo viel gefehlt 

Kannst du mir noch die Frage mit der variablen I beantworten?


----------



## mihe7 (14. Feb 2019)

Java The Hutt hat gesagt.:


> Kannst du mir noch die Frage mit der variablen I beantworten?


Ich sehe nur i und die wird nirgends benutzt -> dient wohl nur der allgemeinen Verwirrung


----------



## Java The Hutt (16. Feb 2019)

Eine weitere Frage zu einem anderen Programm:



Spoiler: Programmcode





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

struct dop_short
{

    short x,y;
};
struct dop_short d1;

short d2[2];

void set_struct(struct dop_short *d){
d->x = d->y = 1;
}

void set_vek(short *d2)
{
    d2[0] = d2[1] = 1;
}



int main()
{
    d1.x = d1.y = 2;
    set_struct (&d1);
    printf("\n%d \t %d", d1.x, d1.y);
    short d2[2];
    d2[0] = d2[1] = 2;
    set_vek (d2);
    printf("\n%d \t %d", d2[0], d2[1]);

}
```




Meine Frage, warum ruft man 
	
	
	
	





```
printf("\n%d \t %d", d1.x, d1.y);
```
 mit dem Punkt-Zugriffsoperator auf und nicht mit dem -> Zugriffsoperator? Wenn ich den -> Zugriffsoperator nehme, bekomme ich einen Fehler. "Invalid Type Argument of "->" (have struct dop_short)
Ich habe bisher die Erfahrung gemacht, dass man Strukturen, die mit einem -> belegt werden auch so aufruft.


----------



## httpdigest (16. Feb 2019)

Weil `d1` ein struct ist und kein Zeiger auf ein struct. Der Klassen/Struct-Member-Zugriffsoperator `->` kann z.B. bei `a->b` als Shortcut für den Ausdruck `(*a).b` verwendet werden.
Siehe: https://stackoverflow.com/questions/4263796/pointer-dereference-operator-vs

In der von dir gezeigten `set_struct` Funktion z.B. wird ein Pointer auf den struct übergeben, um das struct für den Aufrufer sichtbar zu verändern. Und dort wird dann entsprechend auch `->` verwendet. Genauso gut hätte aber auch: `(*d).x = (*d).y = 1` geschrieben werden können.


----------

