Forum: PC-Programmierung einfaches C programm problem


von Peter S. (ungoliant)


Lesenswert?

hi there~

hab vor ner woche mit C angefangen und bin gleich schon an meine grenzen 
gestossen Oo
waere echt lieb wenn mich jmd zu der loesung meines problems fuehren 
koennte.
ziel des progs ist es einen buchstaben durch einen anderen zu ersetzen.
mein problem, das programm ignoriert quasi meine zeile 23. wenn ich fuer 
die funktion 'tausch'  'b' als eine konstante benutze funktioniert es 
wie es soll. hier der code
1
#include <stdio.h>
2
#include <string.h>
3
4
#define MAX 80
5
6
void tausch(char *s, char alt, char neu){
7
  while (*s){
8
    if (*s == alt)
9
      *s = neu;
10
    *s++;
11
  }
12
}
13
14
main(){
15
  char text[MAX];
16
  char a;
17
  char b;
18
  printf("\nText her : ");
19
  gets(text);
20
  printf("\nwelcher buchstabe soll ersetz werden ? : ");
21
  scanf("%c",&a);
22
  printf("\ndurch welchen buchstaben ersetzen ? : ");
23
  scanf("%c",&b);                            // ZEILE 23
24
  printf("\nAlso %c durch %c",a,b);          
25
  tausch(text,a,b);
26
  printf("\n\n%s",text);
27
}

vielen Dank im voraus

: Bearbeitet durch User
von B. S. (bestucki)


Lesenswert?

Das Problem ist, wenn du nur ein Zeichen eingibtst und danach Enter 
drückst, dass in b '\n' gespeichert wird. Gib zwei Zeichen 
hintereinander ein und drück erst danach Enter. Nun sollte dein Programm 
wie gewünscht funktionieren (habs nicht getestet).

Das selbe Problem hatten wir erst vor Kurzem hier. Da findest du auch 
gleich eine bessere Alternative für gets:
Beitrag "Wann Tastaturpuffer mit fflush(stdin); löschen?"

von Peter S. (ungoliant)


Lesenswert?

wow danke das ging ja schnell :)
klappt wenn ich ab und dann enter druecke statt a enter b enter

von W. M. (thematsche)


Lesenswert?

Ersetz mal
1
scanf("%1c",&a);

durch
1
scanf("%1c",&a); scanf("%*c");

von Peter S. (ungoliant)


Lesenswert?

danke, dass mit dem ersetzen klappt auch. habe aber in meinem code 
scanf("%c",&a); ohne %1c die '1' dazwischen gehabt.
kannst du mir bitte die '1' erklären und auch noch warum dein code noch 
funktioniert ? (also was '%*c' bedeutet?)

hab auch in dem anderen thread gesehen, dass eine leerstelle in der 
23ten zeile vor %c funktioniert ... und weiss nich warum :o

von W. M. (thematsche)


Lesenswert?

Schau mal da:

http://www.cplusplus.com/reference/cstdio/scanf/

unter "sub-specifier":

"An optional starting asterisk indicates that the data is to be read 
from the stream but ignored (i.e. it is not stored in the location 
pointed by an argument)."

und das mit der 1 :

"width"    "Specifies the maximum number of characters to be read in the 
current reading operation (optional)."


Das mit dem Leerzeichen ist hier erklaert:

Beitrag "Re: Wann Tastaturpuffer mit fflush(stdin); löschen?"

"Das Leerzeichen bedeutet: "Überlese alle Whitespace""

: Bearbeitet durch User
von Peter S. (ungoliant)


Lesenswert?

thx

von Dirk B. (dirkb2)


Lesenswert?

Du hast zwar eine Test-Ausgabe deiner Eingabe gemacht (das vergessen 
Viele), konntest aber nicht ergkennen, das da ein \n drin steckt.

Das kannst du besser sehen, wenn du die Ausgabe zwischen Sonderzeichen 
einbettest. Z.B <>
1
printf("\nAlso <%c> durch <%c> in <%s>\n", a, b, text);
Wenn du dann die Ausgabe
Also <a> durch <
> in <Hallo>
in zwei Zeilen hast, siehst du das Problem.

Auch wenn du mal fgets statt gets nimmst, ist da das \n mit drin.

von Peter S. (ungoliant)


Lesenswert?

danke euch allen für die loesung/tipps.
natuerlich habe ich nun ein weiteres problem :p
hab das program ein bisschen erweitert und bekomme nun bei der eingabe 
für 'text' ein richtiges ergebniss, wenn ich genau elf zeichen eingebe. 
bei einem zeichen gehts auch. aber bei z.B. zehn zeichen bekomme ich ein 
zeichen, dass wahrscheinlich grad im speicher war. und ich weiss nit 
warum Oo

#include <stdio.h>

const int MAX = 80;

void tausche(char *eingabe, char *ausgabe, char alt, char neu){
  while(*eingabe){
    if (*eingabe == alt)
      *ausgabe = neu;
    else
      *ausgabe = *eingabe;
    *eingabe++;
    *ausgabe++;
}
}


main(){
  char text[MAX];
  char text2[MAX];
  char a,b ;

  printf("\nGibt Text : ");
  gets(text);
  printf("\n\nWelcher Buchstabe soll ersetzt werden ? : ");
  scanf("%c",&a);
  printf("\n\nDurch welchen Buchstaben ersetzen ? : ");
  scanf(" %c",&b);
  printf("\n\nalso in <%s> soll <%c> durch <%c> ersetzt 
werden.",text,a,b);
  tausche(text,text2,a,b);
  printf("\n\n\n%s",text2);
}

von Walter (Gast)


Lesenswert?

Peter Schol schrieb:
> *eingabe++;
>     *ausgabe++;

ist zwar kein Fehler, aber verwirrend,
schreib bitte einfach

eingabe++;
ausgabe++;

denn du willst die Zeiger erhöhen, der Inhalt ist irrelevant

von DirkB (Gast)


Lesenswert?

Du musst auch noch den Stringterminator '\0' kopieren bzw. setzen

von tictactoe (Gast)


Lesenswert?

Peter Schol schrieb:
> void tausche(char *eingabe, char *ausgabe, char alt, char neu){
>   while(*eingabe){
>     if (*eingabe == alt)
>       *ausgabe = neu;
>     else
>       *ausgabe = *eingabe;
>     *eingabe++;
>     *ausgabe++;
> }
> }

Hier tust du zwar korrekt die Schleife abbrechen, wenn die 'eingabe' zu 
Ende ist, aber du vergisst, in der 'ausgabe' das Ende des Strings zu 
markieren. Daher zeigt dein printf den Ramsch, der halt grade da im 
Speicher liegt.

von Peter S. (ungoliant)


Lesenswert?

ja klar !
wenn ich das verstanden habe, bekommt 'eingabe' die '\o' durch die 
funktion 'gets()' already mit.
aber 'ausgabe' braucht ja auch noch an der richtigen stelle am speicher 
ein ende ..... hmm mal guggn wie ich das hinbekomme.

ihr hoert von mir :-)

von Dirk B. (dirkb2)


Lesenswert?

Peter Schol schrieb:
> hmm mal guggn wie ich das hinbekomme.

Überleg mal, auf welche Position der Zeiger ausgabe (am Ende der 
Schleife) zeigt, wenn eingabe auf die '\0' zeigt?

von Peter S. (ungoliant)


Lesenswert?

das ist es !!! vielleicht nicht grade sehr elegant ... aber klappt




#include <stdio.h>
#include <string.h>

const int MAX = 80;

void tausche(char *eingabe, char *ausgabe, char alt, char neu){
  int pos;
  while(*eingabe){
    if (*eingabe == alt)
      *ausgabe = neu;
    else
      *ausgabe = *eingabe;
    eingabe++;
    ausgabe++;
}
  pos = strlen(eingabe);
  ausgabe[pos] =  '\0';
}


main(){
  char text[MAX];
  char text2[MAX];
  char a,b ;
  int laenge;

  printf("\nGibt Text : ");
  gets(text);
  printf("\n\nWelcher Buchstabe soll ersetzt werden ? : ");
  scanf("%c",&a);
  printf("\n\nDurch welchen Buchstaben ersetzen ? : ");
  scanf(" %c",&b);
  printf("\n\nalso in <%s> soll <%c> durch <%c> ersetzt 
werden.",text,a,b);
  tausche(text,text2,a,b);
  printf("\n\n\n%s",text2);
  laenge = strlen(text2);
  printf("\nlaenge = %i",laenge);
}

von Dirk B. (dirkb2)


Lesenswert?

Gib doch mal den Wert von pos in tausche aus.
Auch mal bei verschiedenen Längen der Eingaben.

von W. M. (thematsche)


Lesenswert?

fueg mal vor

printf("\nGibt Text : ");


memset (text, 0, 80);
memset (text2, 0, 80);

ein.


http://www.cplusplus.com/reference/cstring/memset/

von Peter S. (ungoliant)


Lesenswert?

Dirk B. schrieb:
> Gib doch mal den Wert von pos in tausche aus.
> Auch mal bei verschiedenen Längen der Eingaben.

der wert von pos ist == 0. soll ja auch so sein um der funktion printf 
zu sagen, dass sie aufhoeren soll den speicher auszulesen. wenn ich das 
richtig verstanden habe ... :o
tests haben das auch bestaetigt, egal wie lang die eingabe ist pos == 0.

von Peter S. (ungoliant)


Lesenswert?

W. M. schrieb:
> fueg mal vor
>
> printf("\nGibt Text : ");
>
>
> memset (text, 0, 80);
> memset (text2, 0, 80);
>
> ein.
>
>
> http://www.cplusplus.com/reference/cstring/memset/

auch das funktioniert. bin mir aber leider nicht sicher warum Oo. wenn 
statt der 80 hinten eine variable mit dem inhalt von strlen(text) 
staende koennte ich mir denken wieso memset an der richtigen stelle ein 
'\0' setzt. aber so mit der 80 ....

von Peter S. (ungoliant)


Lesenswert?

hab da wieder ein neues problem -.- eine loesung habe ich schon im netz 
gefunden, werd sie gleich mal probieren.
nun aber zu meinem loesungsweg, der kein/ein falsches ergebnis bringt.
kann mir bitte jmd erklaeren, warum ich eine leere zeile als ergebnis 
bekomme ?

#include <stdio.h>
#include <string.h>

const int MAX = 80;

void reverse(char *eingabe, char *ausgabe){
  char hilf[MAX];
  char hilf2[MAX];
  int i=0;
  int x=0;
  int y;
  memset (hilf, 0, 80);
  memset (hilf2, 0, 80);
  while (*eingabe){
    hilf[i] = *eingabe;
    eingabe++;
    i++;
  }

  y = strlen(hilf);
  printf("\n%i",y);

  for (i = strlen(hilf); i<=0; i--){
    hilf2[x] = hilf[i];
    x++;
  }

  strcpy (ausgabe,hilf2);
}


main(){
  char text[MAX];
  char text2[MAX];
  puts("\ngib Text : \n");
  memset (text, 0, 80);
  memset (text2, 0, 80);
  gets(text);
  reverse(text,text2);
  printf("\n%s",text2);
}

von BattMan (Gast)


Lesenswert?

Versuch es mal damit:
1
#include <stdio.h>
2
#include <string.h>
3
4
const int MAX = 80;
5
6
void reverse(char *eingabe, char *ausgabe){
7
  char hilf[MAX];
8
  char hilf2[MAX];
9
  int i=0;
10
  int x=0;
11
  int y;
12
  memset (hilf, 0, 80);
13
  memset (hilf2, 0, 80);
14
  while (*eingabe){
15
    hilf[i] = *eingabe;
16
    eingabe++;
17
    i++;
18
  }
19
20
  y = strlen(hilf);
21
  printf("\n%i",y);
22
23
  for (y--; y >= 0 ; y--){
24
    hilf2[x] = hilf[y];
25
    x++;
26
  }
27
  
28
29
  strcpy (ausgabe,hilf2);
30
}
31
32
33
int main(){
34
  char text[MAX];
35
  char text2[MAX];
36
  puts("\ngib Text : \n");
37
  memset (text, 0, 80);
38
  memset (text2, 0, 80);
39
  gets(text);
40
  reverse(text,text2);
41
  printf("\n%s",text2);
42
}
Merke: strlen gibt zwar die Länge vom String aus, aber Du darfst das 
Ende des Strings nicht mit dem Wert von strlen indexen. Die Array fangen 
immer mit dem Index 0 an. Somit greifst Du beim ersten kopieren auf ein, 
in deinem Fall, NULL-Byte zu und daher ist Deine Ausgabe ein leeres 
Ergebnis!
Da ein NULL-Byte das Ende eines Strings definiert.

Beispiel: Eingabe von 1234. Strlen gibt Dir eine Länge von 4. Ok.
Aber, der String beginnt bei Index 0 und geht bis Index 3.

Ich hoffe, dass dies verständlich war. Den Fehler macht jeder einmal.

von Dirk B. (dirkb2)


Lesenswert?

Peter Schol schrieb:
> der wert von pos ist == 0. soll ja auch so sein um der funktion printf
> zu sagen, dass sie aufhoeren soll den speicher auszulesen. wenn ich das
> richtig verstanden habe ... :o

Leider falsch verstanden. pos ist ja die Länge vom String. Also der 
Abstand der '\0' vom Anfang. Und der ist bei dir immer 0, weil du 
eingabe solang weitergezählt hast (durch das ++), dass er jetzt auf 
die '\0' zeigt.
Da pos immer 0 ist, egal was du  eingibst, kannst du auf das strlen 
verzichten.

Da du ausgabe auch immer weiter gezählt hast, steht es am Ende der 
Schleife da, wo die '\0' hin gehört. Daher reicht ein
1
*ausgabe = '\0';
 hinter der Schleife aus.

von Dirk B. (dirkb2)


Lesenswert?

Peter Schol schrieb:
> der kein/ein falsches ergebnis bringt.
> kann mir bitte jmd erklaeren, warum ich eine leere zeile als ergebnis
> bekomme ?

Fast das gleiche Problem, aber in diesem Fall kopierst du die '\0' vom 
Ende ganz an den Anfang.
Daher sieht es so aus, dass der String leer ist.

Versuch mal auf hilf und hilf2 (als Arrays) zu verzichten.
Ist nicht schwer.

von Peter S. (ungoliant)


Lesenswert?

erstmal vielen Dank fuer eure vorschlaege und erklaerungen. denke ich 
habe einiges gelernt.
ich probiere mal die hilfs arrays weg zu lassen. bin leider vorbelastet, 
weil ich im netz schon ne loesung gefunden habe ohne die hilfs arrays.
da kommt allerdings eine for schleife :
 for ( c = 0 ; c < ( length - 1 ) ; c++ )
      end++;
vor, die ich nicht verstehe.
ich poste mal das ganze prog. vielleicht hat ja jmd lust mir auch noch 
die andere for schleife in der funktion zu erklaeren. da kapier ich das 
length/2 einfach nicht-.-


#include <stdio.h>
#include <string.h>

void reverse(char*);

main()
{
   char string[100];

   printf("Enter a string\n");
   gets(string);

   reverse(string);

   printf("Reverse of entered string is \"%s\".\n", string);

   return 0;
}

void reverse(char *string)
{
   int length, c;
   char *begin, *end, temp;

   length = strlen(string);

   begin = string;
   end = string;

   for ( c = 0 ; c < ( length - 1 ) ; c++ )
      end++;

   for ( c = 0 ; c < length/2 ; c++ )
   {
      temp = *end;
      *end = *begin;
      *begin = temp;

      begin++;
      end--;
   }
}

kanns in etwa nachvollziehen, aber verstehe halt nicht jeden schritt Oo

: Bearbeitet durch User
von Peter S. (ungoliant)


Lesenswert?

Dirk B. schrieb:

> Versuch mal auf hilf und hilf2 (als Arrays) zu verzichten.
> Ist nicht schwer.

habe aber absichtlich nicht den original text uebrschreiben wollen um 
ggfs spaeter noch mal drauf zu greifen zu koennen.
aber ich probier mal mehr mit zeigern zu arbeiten und die hilfs arrays 
weg zu lassen (darum gehts mir ja hier, die zeiger richtig zu verstehen) 
und trotzdem den original text un beruehrt zu lassen :)

von W. M. (thematsche)


Lesenswert?

Koenntest du bitte deine Code-Schnippsel in die c-tags einbetten?

Siehe "Formatierung".

von Dirk B. (dirkb2)


Lesenswert?

Die Scheife mit length-1 soll den Zeiger end solange hochzählen, bis er 
vor der '\0' steht.
Das ist doof gelöst, da ein
1
end += length-1
statt der Schleife das genauso macht.
Die Schleife ist da halt im strlen versteckt.

Man kann auch auf das strlen verzichten, dann muss man das Ende halt 
selber suchen.

Tja, und mit dem length/2 tauscht du nur bis zur Mitte.
Wenn du weiter machst, tauscht du wieder zurück.

0. 01234 // Anfang Länge ist 5
1. 41230 // tausche 0 mit 4
2. 43210 // tausche 1 mit 3 -> fertig
3. 43210 // tausche 2 mit 2
4. 41230 // tausche 3 mit 1
5. 01234 // tausche 4 mit 0

Die letzte Schleife kannst du auch so machen:
1
for ( ; begin < end ; begin++, end--)
2
   {
3
      temp = *end;
4
      *end = *begin;
5
      *begin = temp;
6
   }

von Peter S. (ungoliant)


Lesenswert?

dank dir.

glaub ich muss mir die for schleife nochmal genau angucken.
die kann ja viel mehr als ich bisher dachte :-)

von Dirk B. (dirkb2)


Lesenswert?

Ach, vergessen: Die '\0' fehlt wieder am Ende.
Die solltest du vor der Tausch-Schleife setzen, da du da ja den Zeiger 
auf das Ende schon hast (+/-1).

Deine Funktion tauscht den String in sich selbst.
Das geht nur gut, wenn der String nicht const ist.
Bei einem Array geht das, aber nicht bei einem Stringliteral (Text 
zwischen "")

Wenn du
1
reverse("Hallo Welt!");
kann es funktionieren, muss aber nicht.
Das ist abhängig vom System und Compiler.

Das nächste ist die Signatur der Funktion.
Wenn du dir mal die Standardfunktionen strcpy oder strcat ansiehst, 
wirst du sehen, dass das Ziel als erster Parameter angegeben wurde.
Das soll dann so wie bei Ziel = Quelle aussehen.
Zudem wird das Ziel auch noch als Rückgabewert der Funktion genutzt.
Dann kann man die Funktion gleich weiter benutzen.
1
printf("Reverse of entered string is \"%s\".\n", reverse(string));

von Dirk B. (dirkb2)


Lesenswert?

Peter Schol schrieb:
> glaub ich muss mir die for schleife nochmal genau angucken.
> die kann ja viel mehr als ich bisher dachte :-)
1
for(A;B;C) D;
Naja, die kann vor der Schleife etwas ausführen (A), hat eine 
Schleifenbedingung (B) und macht etwas nach dem Schleifendurchgang (D) 
und vor der nächsten Prüfung (C)

Es geht auch als while. Dann hast du
1
A;
2
while(B) {
3
  D;
4
  C;
5
}
Was bei A, B, C, D steht ist nicht festgelegt.
Du kannst A und C bei for auch weglassen (aber nicht die ; )

Meist nimmt man for für Schleifen, die eine feste Anzahl von Durchläufen 
haben und while, wo die Abbruchbedingung berechnet wird oder von Aussen 
(Benutzer, Datei) beeinflußt wird. Meist, muss aber nicht.

Der Unterschied zwischen while und for ist nur die Sichtbarkeit der 
Variablen, die evtl. bei A definiert wird.

von BattMan (Gast)


Lesenswert?

Ein kleine Idee, wie man es auch realisieren könnte.
1
#include <stdio.h>
2
#include <string.h>
3
#include <malloc.h>
4
5
const int MAX = 80;
6
7
char *reverse(char *eingabe){
8
9
10
  char *wp; /* Temporärer Zeiger */
11
  char *bp; /* Arbeitszeiger */
12
  int len;
13
  len = strlen(eingabe);
14
15
  if( (wp = (char *)malloc(len)) == (char *)0 ){
16
    printf("Malloc failed\n");
17
    return((char *)0);
18
  }
19
  memset((char*)wp,0,len);
20
21
  bp = wp;
22
  bp += len-1;
23
24
  while(*eingabe)
25
    *bp-- = *eingabe++;
26
27
  memcpy((char*)eingabe,(char*)wp,len);
28
  free(wp);
29
  return(eingabe);
30
}
31
32
33
int main(){
34
  char text[MAX];
35
  char text2[MAX];
36
  puts("\ngib Text : \n");
37
  memset (text, 0, 80);
38
  memset (text2, 0, 80);
39
  gets(text);
40
41
  printf("\n%s",reverse(text));
42
}

von Dirk B. (dirkb2)


Lesenswert?

BattMan schrieb:
> Ein kleine Idee, wie man es auch realisieren könnte.

Und welchen Vorteil hat das gegenüber dem direkten Tausch?
Da kann immerhin kein malloc fehlschlagen.

von Peter S. (ungoliant)


Lesenswert?

also wenn ich die original eingabe behalten will, ist mein loesungsweg 
mit hilf und hilf2 gut ? also effizient ?
oder kann man da noch was besser machen... ist immerhin ne menge text 
fuer so ein bisschen resultat :).

von Dirk B. (dirkb2)


Lesenswert?

Peter Schol schrieb:
> also wenn ich die original eingabe behalten will, ist mein loesungsweg
> mit hilf und hilf2 gut ? also effizient ?

Nein. Weder gut (zwei Hilfsfelder und du bist auf MAX Zeichen begrenzt) 
noch effizient (du gehst viermal (mit strlen und strcpy) über die 
Zeichen).

Erste Schleife: Ende finden (meinetwegen auch mit strlen)
Zweite Schleife: rückwärts kopieren (Quelle->Ziel) oder tauschen (in 
place)

Dann wird der Text auch kürzer. :-)

von Peter S. (ungoliant)


Lesenswert?

1
#include <stdio.h>
2
#include <string.h>
3
4
const int MAX = 80 ;
5
6
void tausche(char *eingabe, char *ausgabe){
7
  char hilf[MAX];
8
  int x,i,y;
9
10
  x = 0;
11
  i = 0;
12
  y = strlen(eingabe);
13
14
  printf("\nDie Eingabe besteht aus <%i> Zeichen.",y);
15
16
  while(*eingabe){
17
    hilf[x] = *eingabe;
18
    eingabe++;
19
    x++;
20
  }
21
22
  for (y--; y>=0; y--){
23
    *ausgabe = hilf[y];
24
    ausgabe++;
25
  }
26
  ausgabe[y+1] = '\0';
27
}
28
main(){
29
  char text[MAX];
30
  char text2[MAX];
31
  printf("\nText her fuer rueckwaerts : ");
32
  gets(text);
33
  tausche(text,text2);
34
  printf("\n\n%s",text2);
35
}

so MAX ist gewaehlt als const int damit fuer mehr variable der wert an 
einer stelle festgelegt werden kann. (nur fuer den fall...)
gibts denn da eine bessere(effizientere) loesung ?

hilf2 bin ich losgeworden da eh unsinn. hast recht :p

was waere denn eine alternative fuer strlen ?

was ich /*noch*/ nicht verstehe ist, wenn ich in der for schleife 'y >=0 
'eingebe gehts .... bei 'y=0' bekomme ich allderding gruetze.
und 'y>0' gibt mir halt einen zu wenig aus ... ok feld geht ja ab '0' 
los. aber bei = 0 ist mist aber bei >= 0 ist richtig ? weiss nich warum.

: Bearbeitet durch User
von Peter S. (ungoliant)


Lesenswert?

W. M. schrieb:
> Koenntest du bitte deine Code-Schnippsel in die c-tags einbetten?
>
> Siehe "Formatierung".

danke :)

von tictactoe (Gast)


Lesenswert?

Du kopierst ja noch immer in einen Hilfsarray. Machst du das, weil du 
einen Array-Index verwenden musst, also hilf[y] schreiben musst? Dann 
lass dir sagen, dass du das auch auf einen Pointer anwenden kannst: 
eingabe[y]. Das hat genau die gleiche Bedeutung wie bei einer als Array 
deklarierten Variablen: Nimm den y-ten Wert hinter dem, auf den eingabe 
zeigt. Damit wird eine Progrämmchen dann noch etwas kürzer.

Peter Schol schrieb:
> was ich /*noch*/ nicht verstehe ist, wenn ich in der for schleife 'y >=0
> 'eingebe gehts .... bei 'y=0' bekomme ich allderding gruetze.

Kein Wunder. 'y=0' ist ja auch eine Zuweisung. 'y==0' ist ein Vergleich. 
(Ob der hier richtig ist, habe ich mir aber nicht überlegt.) Eine 
Zuweisung ist auch ein Ausdruck (daher erlaubt der Compiler, dass du 
'for (...; y=0;...) schreibst) und hat ein Ergebnis, nämlich den 
zugewiesenen Wert, was in deinem Beispiel Null ist.

von Dirk B. (dirkb2)


Lesenswert?

Wozu brauchst du eigentlich noch hilf?
Du kopierst da ersmal nur eingabe rein um dann beim umdrehen daraus zu 
lesen.
Warum liest du nicht gleich aus eingabe?

Zudem vermischt du die Array und die Pointerschreibweise.
Das macht für die Funktion nichts, da der Compiler selber ein hilf[y] in 
ein *(hilf + y) umsetzt, aber es ist schwer zu lesen.

Die for-Schleife wird solange ausgeführt, solange die Bedingung wahr 
ist.
y=0 ist eine Zuweisung, deren Ergebnis 0 (unwahr bzw. falsch) ist. 
(Das liegt an der 0)
Der Vergleich auf Gleichheit wird in C mit == (zwei Gleichheitszeichen) 
ausgedrückt.
Der Compiler sollte dir da allerdings eine Warnung geben (wenn du den 
Warnlevel entsprechend gesetzt hast)

Du hattest bemerkt, dass das ja viel Text für so eine einfache Funktion 
ist.
1
char *my_strrev_a(char *out, const char *in)
2
{ // string von in nach out in umgekehrter Reihenfolge kopieren
3
  // Rückgabewert ist out
4
  // Arrayschreibweise
5
6
    size_t i, o;
7
    size_t len = strlen(in);
8
9
    out[len] = '\0';
10
    for(i=0, o=len-1;i<len;i++,o--)
11
        out[o] = in[i];
12
13
    return out;
14
}
15
16
char *my_strrev_p(char *out, const char *in)
17
{ // string von in nach out in umgekehrter Reihenfolge kopieren
18
  // Rückgabewert ist out
19
  // Pointerschreibweise
20
21
    char *o;  
22
    o = out + strlen(in);
23
24
    *(o--) = '\0';
25
    while(o >= out)
26
        *(o--) = *(in++);
27
28
    return out;
29
}
30
31
char *my_strrev_p3(char *out, const char *in)
32
{ // string von in nach out in umgekehrter Reihenfolge kopieren
33
  // Rückgabewert ist out
34
  // Dreizeiler
35
36
    char *o = out + strlen(in);
37
    
38
    for(*(o--) = '\0'; o >= out ; *(o--) = *(in++)) ;  // Leere Schleife
39
40
    return out;
41
}

Beim GCC (war bei Code::Blocks dabei) gibt es schon ein strev:
1
char* strrev (char*);
Das dreht den eigentlichen String um. So kann man sicher gehen, dass 
genug Speicher da ist.

von Peter S. (ungoliant)


Lesenswert?

erstmal vielen dank fuer eure vorschlaege.
zu tictactoe :
nein ich muss nicht irgendein array benutzen.
im moment jedenfals beschaeftige ich mich mit c aus privaten gruenden.
und ich merk grad, dass ich mich schlecht ausgedrueckt habe.
klar weiss ich (auch wenn ich erst vor zwei wochen mit c angefangen 
habe) das ein einfaches = daten zuweist. (hoff ich jedenfals ,dass es 
daten zuweist und nicht stellen im register oder so .... saeh sonst 
bloed aus zu behaupten, dass ich weiss das daten zugewiesen werden xD 
wobei ja daten, wenn ichs verstanden habe auch nur einsen und nullen in 
registern sind zur richtigen zeit am richtigen ort abgerufen ...also es 
quasi doch nur die stellen mit den einzelnen daten preisgibt also doch 
stellen in registern mit daten preisgibt was man dann gleichsetzen kann 
mit daten zuweisen ? kA erschlagt mich bitte nicht fuer den text in 
klammern. einfach ueberlesen... jetzt ist ja auch zu spaet das zu 
schreiben ... naja egal xD ich versuchs halt.)
meinte natuerlich == was ich getestet habe.
mich aergert einfach, dass ich nicht verstehe, warum ein == nur gruetze 
gibt aber ein >= das richtige ergenis.

und Dirk
sei bitte nich so streng mit mir :p
wie gesagt, ich habe nicht wirklich viel gelernt. ein buch von Helmut 
Erlenkoetter habe ich zur haelfte gelesen und bearbeitet wann immer ich 
ne minute zeit hatte.
deswegen ueb ich ja den zeiger kram, um zu verstehen was da wirklich 
passiert im rechner. und ich bin dir sehr dankbar fuer deine 
erklaerungen und loesungsvorschlaege. (ich versuch extra umlaute zu 
meiden um mich dran zu gewoehnen :))
leider hab ich imo keine zeit und kein kopp dafuer mir deine letzen 
vorschlaege genau an zu schaun.
evtl morgen oder so hab ich wieder zeit/luft.

also vielen dank euch allen nochmal :-)

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Peter Schol schrieb:
> meinte natuerlich == was ich getestet habe.
> mich aergert einfach, dass ich nicht verstehe, warum ein == nur gruetze
> gibt aber ein >= das richtige ergenis.

Die Schleifen in C laufen immer solange die Bedingung wahr ist.
Du fängst mit einem y ungleich 0 an.
Dann wird die Bedingung geprüft y == 0 und das ergibt unwahr.
Daher wird die Schleife nicht ausgeführt.


Und streng wollte ich nicht sein.
Als ich mit C angefangen habe, habe ich auch nichts verstanden.
Und wenn du nicht siehst wie es geht, dann kannst du es schlecht lernen.

Das Buch scheint schon ziemlich alt zu sein.
Du benutzt main() und gets.
Heutzutage schreibt man das int bei main() mit dazu (steht so im 
Standard) und gets nimmt man aus Sicherheitsgründen nicht mehr, daher 
solltest du es dir nicht angewöhnen.

C läßt den Entwicklern der Compiler einige Freiheiten in der Auslegung 
des Standards.
Daher kann es sein, dass Dinge auf deinem Rechner/Compiler laufen, auf 
anderen dann aber nicht mehr. Da kann schon eine neue Version vom 
Compiler reichen.
Darum muss man bei manchen Sachen sehr genau sein - und das hört sich 
dann streng an :-)

Aber das soll dir den Spaß nicht nehmen.

von foo (Gast)


Lesenswert?

Dirk B. schrieb:
> C läßt den Entwicklern der Compiler einige Freiheiten in der Auslegung
> des Standards.
> Daher kann es sein, dass Dinge auf deinem Rechner/Compiler laufen, auf
> anderen dann aber nicht mehr. Da kann schon eine neue Version vom
> Compiler reichen.

Aber bitte nicht bei so einfachen Sachen....
Die Grundkontrollstrukturen wie for while switch, operator precedence, 
variabelen scope etc. sind fix.
Wenn sich ein Compiler nicht an den Standard hält ist er kaputt.
Und implementation defined behaviour muss dokumentiert sein.

von Peter S. (ungoliant)


Lesenswert?

Dirk bitte,

erklaerst du mir noch deine loesungswege ?

array schreibweise ... klar habs verstanden und mehrfach reproduziert. 
:-)

aber bei beiden anderen funktionen definierst du eine variable mit der 
variablen "out", wobei "out" an dieser stelle doch noch leer ist. das 
verstehe ich einfach nicht.

"char *o = out + strlen(in);"

bevor out irgendwas zugewiesen wurde.
ich weiss garnicht, was in "out" steht in dem moment wo du den pointer 
"o" definierst.

dann weiss ich garnicht, ob die deklaration und definition nicht die 
gleiche ist in beiden beispielen.
einmal mit "*"  wie im letzen beispiel und davor einfach

"o = out + strlen(in);"

wenn das jetzt den rahmen sprengt dann sorry... muss ich wohl einfach 
noch mehr selber lernen/lesen...
aber wenn du so lieb waerst :-o

<edit> sorry fuer so ne spaete antwort -.- hatte echt wenig zeit die 
letzen wochen

: Bearbeitet durch User
von DirkB (Gast)


Lesenswert?

out ist leer, weil da das Ergebnis rein kommt.
Der Aufruf ist so wie bei strcpy.

out ist die Adresse vom dem Zielarray.
o ist ein Hilfszeiger, der erstmal auf das Ende vom Ziel gesetzt wird.
Dieser wird dann durch das Postdekrement (--) runtergezählt, während die 
Eingabe (in) mit dem Postinkrement  (++) hochgezählt wird.

Bei dem letzten Beispiel habe ich o gleich initialisiert. Spart eine 
Zeile.
Und die for-Schleife ist fast aus dem gleichen Grund da. Spart zwei 
Zeilen.
Ansonsten machen die beiden Pointer-Funktionen dasselbe. Der Compiler 
wird auch denselben (Maschinen-)Code dafür ausgeben.

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.