Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?
-
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.
-
@john-0 sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
@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.
Das ist dem Sprachstandard aber egal. Das Ergebnis von ++ ist garantiert immer größer als der vorherige Wert, und
Ende-Anfang
funktioniert auch garantiert positiv. Wenn du mit ++ über irgendwelche Grenzen laufen würdest, dann hast du den klassischen Fall, dass du einen Pointer erzeugt hast, der hinter ein Array zeigt. Das ist aber sowieso undefiniertes Verhalten und macht dir die obigen Garantien kaputt.Die Legalität von "darf man einen Pointer erzeugen der hinter ein Array zeigt?" ist hier schon zig mal diskutiert worden, und der Fall von segmentiertem Speicher ist genau der Fall, wo es schief gehen könnte. Und vermutlich der Grund, warum der Standard sagt, dass es UB ist.
Jedenfalls kann aus diesem Grund das Array gar nicht über solch eine Grenze verlaufen. Der Pointer zu dem das Array zerfällt ist garantiert geeignet, um das gesamte Array zu adressieren, nicht mehr und nicht weniger.
-
@SeppJ sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Die Legalität von "darf man einen Pointer erzeugen der hinter ein Array zeigt?" ist hier schon zig mal diskutiert worden, und der Fall von segmentiertem Speicher ist genau der Fall, wo es schief gehen könnte. Und vermutlich der Grund, warum der Standard sagt, dass es UB ist.
Aber zeigt nicht
std::end(my_array)
hinter mein Array? Und darf ich nichtend(array) - begin(array)
rechnen für die Länge? Das ist UB?
Edit: oh verdammt, hier ist C ohne ++. Ist da irgendwo ein Unterschied, der das in C++ gültig macht? Denn ansonsten hätte ich glaube ich ein Problem.
-
@wob sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
@SeppJ sagte in Zeichenkette einlesen und mittels Zeigerarithmetik die Anzahl der Zeichen ausgeben?:
Die Legalität von "darf man einen Pointer erzeugen der hinter ein Array zeigt?" ist hier schon zig mal diskutiert worden, und der Fall von segmentiertem Speicher ist genau der Fall, wo es schief gehen könnte. Und vermutlich der Grund, warum der Standard sagt, dass es UB ist.
Aber zeigt nicht
std::end(my_array)
hinter mein Array? Und darf ich nichtend(array) - begin(array)
rechnen für die Länge? Das ist UB?
Edit: oh verdammt, hier ist C ohne ++. Ist da irgendwo ein Unterschied, der das in C++ gültig macht? Denn ansonsten hätte ich glaube ich ein Problem.Ich habe es jetzt nicht so exakt auf das letzte Byte gemeint. Eins hinter das Array ist noch ok.