länge einer zeichenkette und kopieren von zeichenketten mit zeigern in c++ ?

code - (Computer, PC, programmieren)

4 Antworten

Das mit den rohen Zeiger ist ja eher C-Style als C++!

Die Länge der Zeichenkette wird einfach abgezählt wie folgt:

  • pg erhält die Adresse von quelle
  • quelle ist ein Zeiger und enthält die Adresse vom Anfang des strings "Ich bin eine Zeichenkette".
  • per Zeigerarithmetik läuft pg mit jedem while-Schritt einen Adressschritt weiter. Die Adresse von pg wird somit nach hinten verschoben. Wenn '0' erreicht ist, hat pg die Adresse vom Ende von quelle.
  • nach der while-Schleife wird die End-Adresse von der Anfangsadresse abgezogen.
  • dass '0' abgebrochen wird, ist i.O., da zuerst hochgezählt wird und dann abgebrochen.

Die Kopie ist ebenfalls logisch:

  • pz erhält die Adresse des Anfang svon ziel gesetzt (& = Adresse, [0] ist das erste Element, also der Anfang).
  • pg wird wieder (!) auf den Anfang von quelle gesetzt. Jetzt werden die Adressen von pg und pz gleichzeitig hochgelaufen und mit jede Schritt der Inhalt von pg in pz kopiert. Man hätte wohl theoretisch noch die '0' mit kopieren können, hier wird die '0' jedoch als Abbruch verwendet.
  • Folglich muss bei pz hinten noch ein '0' angesetzt werden.

Rückfragen gerne.

Aber nochmals: Das ist wirklich Pure-C-Style (wenn man das mit Assembler programmiert, sieht es ähnlich aus :-), mit C++ löst man das schöner. Aber zum Lernen wichtig und gut!

Woher ich das weiß:eigene Erfahrung – Hobby und teilweise beruflich

ohwehohach  06.03.2017, 13:27

Sogar in C würde man das schöner lösen ;-)

1
RealAutism 
Beitragsersteller
 06.03.2017, 13:59
@ohwehohach

ok super danke hab jetzt eigentlich alles verstanden, aber erhält *pq nicht den Inhalt des Datenobjektes, für die Adresse hätte man ja den &-Operator benutzen müssen oder nicht? und ist es also generell dasselbe ob ich *pq = quelle (zeile 10) oder nur pq = quelle (zeile 16) setze, weil der stern gibt ja eigentlich an, dass es sich um einen zeiger handelt?

1
nobytree2  06.03.2017, 14:11
@RealAutism

Das ist nicht *pq!

Sondern:

Char*           pq;

Es wird ein Zeiger auf char (also char*) eingeführt, mit dem Namen pq.

Das Problem ist, wenn man Zeiger einführt, kann man nicht schreiben:

Int* Zeiger1, Zeiger2, Zeiger3, Zeiger4, 

sondern man muss schreiben

Int* Zeiger1, *Zeiger2, *Zeiger3, *Zeiger4.

Jeder Zeiger muss mit * gekennzeichnet werden, deswegen finde ich die Darstellung in Zeile 7 eher verwirrend.

Besser trennen:

char ziel[maxZeichen]; 
char* pg;             

Das erste ein Char-Array (verwendbar auch als char-Zeiger), das zweite char-Zeiger.

Den &-Operator nutzt nur dann, wenn Du die Adresse von einer Variablen haben willst, nicht zur Einführung eines Zeigers.

Z.B. 
char* pg;
pg=&ziel[0];

Der Unterschied Zeile 10 und 16:

Bei Zeile 10 wird zusätzlich noch pq als Zeiger eingeführt. Wenn Du Zeile 10 trennst, wird es verständlich

char *pq;    // Einführung char-Zeiger;
pq=quelle;  // gib der Zeigervariable einen Inhalt

Dann ist es identisch zu 16.
 

1
nobytree2  06.03.2017, 14:28
@nobytree2

Zugegeben, es ist verwirrend, denn der * ist doppeldeutig:

Um einen Zeiger einzuführen, schreibst Du

Variablentyp *   Name_des_Zeigers

Um den Inhalt eines Zeigers zu erhalten, verwendest Du auch den Stern.

Z.B.

int i=3;
int h;
int* z;
z=&i; // z erhält die Adresse von i
h= *z; // h erhält 3.

Mit * kann man nicht nur einen Zeiger in die Welt setzen, sondern auch darauf zugreifen, worauf er verweist. Er verweist auf die Adresse z.B 0000:11111 (Formal wohl falsch), in dieser Adresse ist eine 3. Diese 3 wird über h = *z gezogen.

Möglich ist auch:

int i=3;
int h;
int* z;
int* z2;
int** zz;
int** zz2;
z=&i; // z erhält die Adresse von i
zz=&z; // zz erhält die Adresse von z;
z2=*z; // z2 erhält 3
zZ2=*z2 // zz2 erhält auch 3

Die ersten * dienen der Zeiger-Einführung.

Die folgenden & dienen dazu, sich die Adressen geben zu lassen.

Wenn das * nicht dazu benutzt wird, einen Zeiger einzuführen, bedeutet *, dass auf den Inhalt, auf den der Zeiger verweist, zugegriffen wird.

Möglich ist auch

int i;
int* z;
z=&i;
*z=3; damit ist auch i = 3
1
RealAutism 
Beitragsersteller
 06.03.2017, 14:43
@nobytree2

oh mann so viele möglichkeiten.... :D  ich begrenze mich mal auf die die wir gemacht haben um nicht durcheinander zu kommen für die Klausur sollte es dann langen, zumal wir sowieso zu 90% code analysieren sollen und nicht selber programmieren. wobei man kann darüber streiten, was schwieriger ist, also selbst programmieren oder gegebenen code analysieren :D

1

Ich weiß gerade nicht genau was du willst... Wenn du an die Länge kommen willst, mach doch einfach das hier:

char* kette = "We are number one!";
int length;

std::string s = kette;
length = kette.length();

oder falls das nicht klappt:

char* kette = "We are number one!";
int length = 0;
for(char c = '-'; c != NULL) { c = kette[length]; length++; }length--;

priesterlein  06.03.2017, 12:05

Wenn du ihm schon mit codebeispielen, die nichts mit seinem zu tun haben, antworten willst, dann empfehle ihm doch wenigstens keine falsche Syntax.

0

Zeile 11:

Der Code soll feststellen, wieviele Zeichen in der Quelle sind. da das Ziel nur eine begrenzte Anzahl Zeichen aufnehmen kann, will der Programmierer sicherstellen, dass die Quelle ins Ziel passt.

Zeile 12:

Die Anzahl der Zeichen in der Quelle wird auf die Variable len geschrieben. Interessanterweise wird die 0 nicht mitgezählt.

Zeile 14:

Durch die Abfrage, dass die Quellenlänge (len) kleiner als die Zielänge (maxZeichen) ist, wird sichergestellt, dass sowohl die Quellenzeichen als auch die terminierende null in das Ziel passt. Falls das Ziel die Länge null hätte, wäre es ab hier sehr interessant.


RealAutism 
Beitragsersteller
 06.03.2017, 00:10

ok ich glaub ungefähr hab ich es verstanden muss glaub ich noch ne nacht drüber schlafen mache schon zu lange heute :D aber eine sache noch, wieso dann noch die letzte zeile *pz = '\0'; ?

0
nobytree2  06.03.2017, 07:26
@RealAutism

wieso dann noch die letzte zeile *pz = '\0';

Damit der String mit einer '0' beendet wird. Das ist wichtig für viele String-Funktionen. Woran sollte man sonst erkennen, wo der String endet? Von der Variable ziel kennen wir nur den Anfang, daran folgen im Speicher ein Haufen Zeichen, das Ende müsste man entweder in einem gesonderten Zeiger speichern oder aber das Ende durch ein spezifisches Zeichen - bei Strings die '0' kennzeichnen.

Dass '0' nicht mitgezählt wird, ist i.O., da zuerst pq hochgezählt wird und dann abgebrochen. Wenn beispielsweise der String 2 Zeichen lang ist, läuft pg mit zwei Schritten vorwärts, passt also.

Das Ziel hat die als Array die Länge Maxlaenge, als String eine zufällige Länge, da das '0' noch nicht gesetzt ist (was nichts schadet, da ziel noch nicht als String verwendet wird, wichtig ist nur, dass der Speicherplatz reserviert ist, bevor dort hineingeschrieben wird).

Wenn die Quelle als String eine Null-Länge hat, jedoch mit '0' begrenzt ist, klappt der Kopieralgo auch.

1

Der Code funktioniert eventuell nicht, da der String "quelle" nicht explizit nullterminiert ist.

Ansonsten macht der Code prinzipiell das, was die andern schon geschrieben haben

1) Länge des Quellstrings zählen

2) Alle Zeichen aus Quellstring in Zielstring kopieren

3) Zielstring nullterminieren

Aus meiner Sicht ist das aber nur eine Testimplementierung, um zu zeigen, wie man strlcpy implementieren könnte.


nobytree2  06.03.2017, 13:58

Muss ich explizit 0-terminieren?. Wenn für quelle bereits Speicher reserviert wird, müsste doch auch eine Null-Terminierung gesetzt sein. Nicht erforderlich ist ja bei char* ="[Inhalt]" ein new oder malloc().

Denn es wird ja nicht nur ein Zeiger gesetzt, sondern auch ein Array.

Allerdings programmiere ich nie char s* = "asdlfjad", aber char* müsste gleich sein wie char[] (?)

http://stackoverflow.com/questions/7564033/difference-between-char-and-char

0
ohwehohach  06.03.2017, 14:05
@nobytree2

Nein. Ein char* hat mit einem char[] nichts zu tun. Das eine ist ein Zeiger auf einen Speicherbereich, das andere ist ein Array. Man kann sich einen String in C zwar vorstellen wie ein char[], aber char* und char[] sind nicht dasselbe.

Die Zeile

char* text = "Hallo Welt";

setzt nur den Pointer "text" auf den Anfang des Speicherbereichs, der den String "Hallo Welt" beinhaltet.

Eines der größten Probleme in C ist die richtige Behandlung von Zeichenketten. Hier treten am häufigsten Pufferüberläufe, etc. auf, unter anderem, weil die Programmierer die Nullterminierung falsch machen.

Zwar habe ich gerade gelesen, dass Strings, die wie oben deklariert sind (also als char* mit konstantem Inhalt) immer implizit nullterminiert sind, im Gegensatz dazu sind char[] aber niemals automatisch nullterminiert!

Du müsstest also immer schreiben:

char[] text = "Hallo Welt\0";
1