Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?
-
Ich kann mit meiner wagen Erinnerung daran jetzt leider kein Beispiel-Code liefern.
Ich meine nur irgendwo aufgegriffen zu haben, dass der Speicher das nicht zwangsweise von links nach rechts abspeichert.
Aber nach weiteren Gedanken macht das Sinn, denn wenn du einen Iterator inkrementierst zeigt er ja wohl auf die nachfolgende Adresse.
-
@Luks-Nuke sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Ich meine nur irgendwo aufgegriffen zu haben, dass der Speicher das nicht zwangsweise von links nach rechts abspeichert.
Der Satz macht für mich keinen Sinn. Also vergessen wir mal Endianness, denn das würde alles nur unnötig kompliziert machen, und ich denke auch nicht dass du das meinst.
Der Speicher speichert das was du ihm gibst, an der Adresse die du verwendest. An der selben Adresse kannst du den Wert danach wieder lesen. Und das war's dann auch schon. Wenn du was an Adresse X schreibst, dann steht das halt dort. Wenn du was an Adresse X+1 schreibst, dann steht das halt an Adresse X+1. Links und rechts/vorne-hinten/Anfang-Ende etc. sind Konzepte die wir da reininterpretieren, haben aber technisch aus Sicht des Speichers keine Bedeutung.
Wo sie eine Bedeutung gewinnen ist wenn man anfängt Datenstrukturen zu implementieren. Da geht's dann aber darum wie die Datenstruktur aufgebaut ist, und was der Code den man schreibt um diese umzusetzen macht. Und nicht darum dass der Speicher irgendwie selbst irgendwas andersrum abspeichert.
Aber nach weiteren Gedanken macht das Sinn, denn wenn du einen Iterator inkrementierst zeigt er ja wohl auf die nachfolgende Adresse.
Er. Nö
Der Iterator zeigt auf das nächste Element. Das muss nicht unbedingt an der nachfolgenden Adresse liegen. Das kann auch davort oder überhaupt ganz woanders liegen. Allerdings abstrahiert der Iterator das ganze soweit, dass bei
IteratorAufEnde-IteratorAufAnfang
wieder das richtige rauskommt. Bei(&*IteratorAufEnde)-(&*IteratorAufAnfang)
könnte allerdings beliebiger Unfug rauskommen.Also. Wenn du mit
++
Zeiger weiterschiebst, dann darfst du danach auch die Zeiger subtrahieren. Und wenn du mit++
Iteratoren weiterschiebst, dann darfst du danach Iteratoren subtrahieren. Was du nichst darfst ist mit++
Iteratoren weiterschieben, und danach Zeiger auf die Elemente subtrahieren.Und da es in diesem Thread um
char
Strings ging die mit Standard Library Funktionen eingelesen werden: diese liegen immer "vorwärts" im Speicher, d.h. ein Weiterspringen zum nächsten Zeichen in Leserichtung entspricht einem Weiterspringen im Speicher zum Byte mit der nächst höheren Adresse. (OK, genaugenommen könnten es multi-byte Strings sein, also sowas wie UTF-8. Dann wäre es nicht das nächste Zeichen sondern die nächste Code-Unit.)
-
Ok stimmt, gibt ja vielerlei Iteratoren. Ich hatte mich mit der Aussage jetzt auf String Iteratoren bezogen.
Danke jedenfalls für die Erläuterung, für mich allerdings nicht die einfachste Lektüre.
-
Erstmal danke für die vielen Antworten. Immerhin wusste ich schon einmal, dass ich strlen simulieren muss. Ich bin in C noch nicht so fit und sehe noch nicht wirklich den Sinn diese Sprache zu lernen, da ich es im Berufsleben niemals brauchen werde. Aber ich versuche mir noch das C-Buch von Bradley L. Jones zu besorgen. Das soll zum lernen ganz gut sein.
Bisher sieht mein geänderter Code so aus. Nur irgendwie habe ich gerade einen Denkfehler, warum mein programm nur eine Zahl einliest:
#include <stdlib.h> #include <string.h> #include <stdio.h> #define MAX 128 int main(){ char *p; int i = 0; char z[MAX]; printf("Gebe maximal 128 Zeichen in einer Zeile ein: "); gets(z); /*ganze Zeile einlesen*/ while(*(p+i)!='\0'){ /*Zähle bis zum Ende der Zeichenkette*/ p = &z[i]; /*Adresse vom Zeichen ermitteln*/ p = z + i; /*Wert vom Zeichen ermitteln*/ printf("Test: %c",*p); /*Ermittelter Wert zu testzwecken ausgeben*/ i++; /*das Array um eins erhöhen*/ return i; } printf("\nAnzahl:%d\n",i); /*gib die Anzahl aus*/ }
-
Du wiederholst 3x die gleiche Rechnung, die du nur einmal brauchst:
(p+i)
,p = &z[i]
,p = z + i
. Das sind drei Beispiele für Zeigerarithmetik, die alle ungefähr das gleiche machen und wahrscheinlich so in deinem Lehrbuch stehen. Aber es ist nicht Sinn der Aufgabe, die alle irgendwo anzubringen. Du musst verstehen was das jeweils macht und mit einem Plan an die Aufgabe gehen.Bestes Beispiel die Zeilen 20 und 21. Was hast du dir dabei gedacht? Würdest du folgendes für sinnvoll erachten?
i = 7; i = 15;
Das ist quasi, was deine Zeilen 20-21 machen.
-
Das Problem ist allerdings das
return i;
, das dafür sorgt, dass direkt ausmain
gesprungen wird und damit das Programm beendet wird.
printf("\nAnzahl:%d\n",i);
wird niemals aufgerufen, wenn die Länge vonp
größer 0 ist.Edit: Ich sehe gerade, dass du
gets
verwendest, mach das nicht.gets
ist mindestens deprecated (imho seit C99, in C2011 ist es komplett rausgeflogen), nimm stattdessenfgets
.
-
Dein Code sieht leider nicht so gut aus. Keine Ahnung wo ich da jetzt mit meckern anfangen soll...
Versuch doch mal nach bereits existierenden
strlen()
Implementationen zu googeln. Da findest du durchaus hilfreiche Beispiele, wie man das macht.Schau dir beispielsweise das hier an:
https://en.cppreference.com/w/cpp/string/byte/strlenDas verfolgt auch @hustbaer 's erwähnten Ansatz.
-
So ich melde mich nochmal erneut. Ich habe mich nochmal erneut daran versucht und habe das mit der nullten Stelle soweit kapiert. Im Internet hat man kaum etwas dazu gefunden, deshalb kam ich irgendwann auch so auf die Idee: Nur irgendwie denke ich, man hätte es noch sauberer lösen können und mehr die Zeigerarithmetik verwenden können. Hier der Code:
#include <stdlib.h> #include <string.h> #include <stdio.h> #define MAX 130 /*1 Byte für Zeichenkette = '\0' | 1 Byte extra, da wir ab i = 0 zählen*/ int main(){ int zahl = 0, i; char z[MAX]; /*Array MAX groß*/ printf("Gebe maximal 128 Zeichen in einer Zeile ein: "); fgets(z, MAX, stdin); /*ließt die ganze Zeile ein bis "MAX" Zeichen erreicht sind*/ for(i=0; *(z+i) != 0; i++) /*Zähle bis zum Ende der Zeichenkette*/ { putchar(*(z+i)); /*Kontrolle: Eingabe = Ausgabe*/ zahl++; } zahl = zahl - 1; /*Minderung wegen der Versetzung um ein Byte*/ printf("Anzahl:%d",zahl); /*Ausgabe Anzahl*/ return 0; }
-
Probierst du deine Programme nicht aus?
PS:
1 Byte extra, da wir ab i = 0 zählen
Ein Array
int i[2];
hat zwei Elemente.i[0]
undi[1]
.
-
@SeppJ sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Probierst du deine Programme nicht aus?
Natürlich probiere ich meine Programme aus. Funktioniert doch. Das ein Array bei 0 anfängt weiß ich
-
@Ravensouth
Teste dein Progamm mal mit nem Textfile als Input wo z.B. "test" (ohne folgenden Zeilenumbruch) drinsteht.
Output:Gebe maximal 128 Zeichen in einer Zeile ein: testAnzahl:3
-
fgets
speichert auch das Newline-Zeichen\n
(im Gegensatz zugets
oderscanf("%s")
- darum das Dekrementieren.Ein Möglichkeit ist mittels dem PP den Format-String für
scanf
zusammenzusetzen:#define STR(X) STRINGIFY(X) #define STRINGIFY(X) #X
und dann
scanf("%" STR(MAX) "s", z);
s.a. Specifying the maximum string length to scanf dynamically in C (like "%*s" in printf)
sowie der abgeänderte Ideone-Code.
-
@Ravensouth sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Das ein Array bei 0 anfängt weiß ich
Ja, aber ich habe den Eindruck, du ziehst die falschen Schlüsse.
-
@Th69
Man kann schonfgets
verwenden. Man muss bloss nachher das abschliessenden\n
wegmachen wenn man es nicht haben will.
-
Ok das fgets mit /n abschließt wusste ich nicht. Danke für diese Information.
-
@SeppJ sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
@Ravensouth sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Das ein Array bei 0 anfängt weiß ich
Ja, aber ich habe den Eindruck, du ziehst die falschen Schlüsse.
Wenn ich
int i[2]
als Array habe, dann müssten dochi[0]
,i[1]
undi[2]
enthalten sein?
-
@Ravensouth
Nein!
int i[2];
hat 2 Elemente ... wie SeppJ oben schon erwähnt hat ...
-
@Ravensouth sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Ok das fgets mit /n abschließt wusste ich nicht. Danke für diese Information.
es ist \n
Das ist eine Escapesequenz und steht für ein Zeichen@Ravensouth sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Wenn ich
int i[2]
als Array habe, dann müssten dochi[0]
,i[1]
undi[2]
enthalten sein?Nein.
Bei der Definition werden die Anzahl der Elemente angegeben.
In diesem Fall 2. Und wenn man bei 0 anfängt kommt man nur bis 1 als Index.
-
@Ravensouth sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Im Internet hat man kaum etwas dazu gefunden,
Ach echt? Schau dir nochmal mein Beispiel an, was ich gepostet habe. Ich zitiers dir sogar nochmal:
@Luks-Nuke sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Das ist übrigens mMn die Musterlösung und benutzt Zeigerarithmetik.
Btw statt
*z(i + 1)
kannst du auch ganz einfachz[i + 1]
schreiben. Damit schälst du die gleiche Birne.Wenn bei meinem gepostetem Vorschlag noch Sachen sind, die du nicht kapierst kannst du gerne hier nachfragen, was genau du nicht verstehst.
-
@hustbaer sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Wenn man mit Zeigern arbeitet und mit
++
zum nächsten Element kommt, dann funktioniertEnde-Anfang
.Das setzt voraus, dass es sich um eine Plattform mit linearen Arbeitsspeicher handelt. Das ist mittlerweile Standard, war aber eben nicht immer der Fall. An mir persönlich ist der Kelch 8088/8086/80286 vorbei gegangen, da muss man neben dem Zeiger auch das Indexregister berücksichtigen. Nimmt man da nur den Zeiger können dort negative Werte herauskommen, wenn man das Indexregister dazu nimmt stimmt wieder alles.