Forum: PC-Programmierung while-Schleife


von Tobias Mehrl (Gast)


Lesenswert?

Hi Leute!

Ist mein Code syntaktische korrekt?
1
while((str_komplett[i] != '+') | (str_komplett[i] != '-'))
2
{
3
 Schleifenrumpf
4
}

von (prx) A. K. (prx)


Lesenswert?

Syntaktisch schon...

von grrr (Gast)


Lesenswert?

Nein. LOGISCHES Oder verwenden, außerdem ist die Bedingung immer wahr.

von (prx) A. K. (prx)


Lesenswert?

grrr schrieb:

> Nein. LOGISCHES Oder verwenden, außerdem ist die Bedingung immer wahr.

Beides hat nichts mit der Syntax zu tun, und nur das war gefragt.

von grrr (Gast)


Lesenswert?

Ok, A. K. hat Recht...

von Klaus W. (mfgkw)


Lesenswert?

naja, eigentlich fehlt hinter Schleifenrumpf noch ein Semikolon...

von Tobias Mehrl (Gast)


Lesenswert?

Gut Syntaktische ist es korrekt. Warum aber kommt immer wahr raus? Das 
verstehe ich nicht... Das Problem hab ich nämlich jetzt grad!

von (prx) A. K. (prx)


Lesenswert?

Tobias Mehrl schrieb:

> Gut Syntaktische ist es korrekt. Warum aber kommt immer wahr raus? Das
> verstehe ich nicht... Das Problem hab ich nämlich jetzt grad!

Die Bedingung wird nur falsch, wenn das Zeichen sowohl + als auch - ist.
Gleichzeitig.

von Tobias Mehrl (Gast)


Lesenswert?

Wie bekomm ich dann das entweder oder als Bedingung in den Schleifenkopf 
rein? Mit dem | oder || geht's ja anscheinend nicht...

von cproger (Gast)


Lesenswert?

Ich würde sagen:


while((str_komplett[i] != '+') || (str_komplett[i] != '-'))
{
 Schleifenrumpf
}

von cproger (Gast)


Lesenswert?

if((str_komplett[i] != '+') || (str_komplett[i] != '-'))
{
 Schleifenrumpf
}Beitrag melden | Bearbeiten | Löschen |

von (prx) A. K. (prx)


Lesenswert?

@cproper: Diese while() Variante ist zwar gebräuchlicher,
aber genauso falsch.

von Tobias Mehrl (Gast)


Lesenswert?

|| so geht's auch nicht. Hab ich vorher schon ausprobiert.
Was is mit isalpha()? Hab's grad ausprobiert, aber geht auch nicht. Gut, 
ich hab's so geschrieben:

while(!isalpha(x[i])
{
};

von (prx) A. K. (prx)


Lesenswert?

Tobias Mehrl schrieb:

> Wie bekomm ich dann das entweder oder als Bedingung in den Schleifenkopf
> rein? Mit dem | oder || geht's ja anscheinend nicht...

Ein "entweder oder" wäre
  while((str_komplett[i] != '+') != (str_komplett[i] != '-'))
aber ich bezweifle, dass du das wirklich meinst.

Ich biete ein "und" an Stelle des "oder".

von Klaus W. (mfgkw)


Lesenswert?

A. K. schrieb:
> @cproper: Diese while() Variante ist zwar gebräuchlicher,
> aber genauso falsch.

Das kannst du so nicht sagen.
Vielleicht will er ja den Rumpf immer ausgeführt haben?
Dann wäre es absolut korrekt :-)

von ... (Gast)


Lesenswert?

Tobias Mehrl schrieb:
> Wie bekomm ich dann das entweder oder als Bedingung in den Schleifenkopf
> rein? Mit dem | oder || geht's ja anscheinend nicht...

Och Mensch, denken!

while( (var!='+') && (var!='-') )
{
   tu_was_sinnvolles();
}

Etwas boolsche Algebra macht daraus

while( ! ( (var=='+') || (var=='-') ) )
{
   tu_was_sinnvolles();
}

von Tobias Mehrl (Gast)


Lesenswert?

while(!isalpha(x[i])
{
};

das hier ist schwachsinn... ich will ja auf ziffern prüfen

von ... (Gast)


Lesenswert?

@Klaus Wachtler

#define Schleifenrumpf gueltige_Funktion();

SCNR ;-)

von (prx) A. K. (prx)


Lesenswert?

Tobias Mehrl schrieb:

> ich will ja auf ziffern prüfen

Das wäre isdigit().

von Tobias Mehrl (Gast)


Lesenswert?

Was meint ihr? Geht's so?

while(isdigit(x))
{
};

von Klaus W. (mfgkw)


Lesenswert?

@... (Gast) :
Gut, aber mit passendem #define davor bekommst du ziemlich
alles syntaktisch korrekt hin, und sei es nur indem man alles
wegdefiniert zu nichts :-)

von Klaus W. (mfgkw)


Lesenswert?

Tobias Mehrl schrieb:
> Was meint ihr? Geht's so?
>
> while(isdigit(x))
> {
> };

Wenn es das ist, was du willst, dann natürlich ja.

von Klaus W. (mfgkw)


Lesenswert?

Soll das C++ sein wie in deinem anderen Thread (wenn ich mich
recht entsinne)?

Dann wäre es besser:
1
#include <cctype>
2
...
3
while( std::isdigit(x) )
4
{
5
  ...
6
}

Aber sonst ok.

von Tobias Mehrl (Gast)


Lesenswert?

Wenn ich nun das hier

while(isdigit(x))
{
};

schreibe, dann bekomm ich wenn x erfüllt ist einen von 0 verschiedenen 
Wert. D.h. entweder -1 oder 1. Wie bekomm ich das nun hin, dass ich 
immer einen fest definierten Zustand von einer glatten +1 krieg?

Nein es soll kein c++ sein...

von Klaus W. (mfgkw)


Lesenswert?

Das Semikolon hinter dem Block ist übrigens für die Katz.

von Klaus W. (mfgkw)


Lesenswert?

> Wie bekomm ich das nun hin, dass ich
> immer einen fest definierten Zustand von einer glatten +1 krieg?
1
while( isdigit(x)!=0 )
2
{
3
}

Wobei -1 an dieser Stelle die gleiche Wirkung hat wie +1

von grrr (Gast)


Lesenswert?

>ich will ja auf ziffern prüfen
In deinem ersten Post stand etwas ganz anderes, falsche Syntax hin oder 
her. Ich kommt mir gerade leicht verar### vor.

von Klaus W. (mfgkw)


Lesenswert?

Kann es sein, daß du Strings hast mit Zahlen und diese entweder mit +
oder - beginnen und du darauf prüfen willst?
Dann geht das eh nicht so!

von Tobias Mehrl (Gast)


Lesenswert?

Ich möchte eigentlich einen String auf korrekt Eingabe prüfen. An erster 
Stelle muss einzelne Zahl stehen an zweiter stelle mus ein D stehen an 
dritter Stelle muss wieder eine einzelne Zahl stehen an vierter Stelle 
entweder ein + oder ein - und an fünfter Stelle muss wieder ein einzelne 
Zahl stehen.

Wenn bei der Eingabe davon abgewichen wird, muss eine Fehlermeldung 
ausgegeben werden.

Das soll ich machen

von Klaus W. (mfgkw)


Lesenswert?

Tobias Mehrl schrieb:
> Zahl ... Zahl

Ziffer meinst du wohl.

Eigentlich kannst du diesen ganzen Test mit einem einzigen
Aufruf von sscanf() erschlagen.
Es übt natürlich auch, das alles Zeichen für Zeichen zu machen,
dem will ich nicht im Wege stehen.

von Klaus W. (mfgkw)


Lesenswert?

Etwa in der Art:
1
    if( isdigit( str[0] ) && str[1]=='D' &&  isdigit( str[2] ) && 
2
        ( str[3]=='+' || str[3]=='-' ) && isdigit( str[4] ) )
3
    { /* alles ok */
4
    }
5
    else
6
    { /* oioioi! */
7
    }

von Tobias Mehrl (Gast)


Lesenswert?

das hier ist ja schon mal ganz nett:
1
    if( isdigit( str[0] ) && str[1]=='D' &&  isdigit( str[2] ) && 
2
        ( str[3]=='+' || str[3]=='-' ) && isdigit( str[4] ) )
3
    { /* alles ok */
4
    }
5
    else
6
    { /* oioioi! */
7
    }


aber: wie mach ich es, wenn ich jeden Fehler einzeln erkannt haben will?

Ausgabe in der Art:

-Stelle 1 ist falsch
-Stelel 2 ist falsch
-Stelle 5 ist falsch

von Klaus W. (mfgkw)


Lesenswert?

1
  if( !isdigit( str[0] ) )
2
  {
3
     // erste Zeichen schon falsch
4
  }
5
  else if( str[1]!='D' )
6
  {
7
     // kein D an zweiter Stelle
8
  }
9
  else if( !isdigit( str[2] ) )
10
  {
11
     // wieder keine Ziffer
12
  }
13
  else if( str[3]!='+' && str[3]!='-' )
14
  {
15
     // kein Vorzeichen
16
  }
17
  else if( !isdigit( str[4] ) )
18
  {
19
     // wieder keine Ziffer
20
  }
21
  else
22
  {
23
     // alles quintmoppel
24
  }

von Torsten K. (ago)


Lesenswert?

Tobias Mehrl schrieb:
> Ich möchte eigentlich einen String auf korrekt Eingabe prüfen. An erster
> Stelle muss einzelne Zahl stehen an zweiter stelle mus ein D stehen an
> dritter Stelle muss wieder eine einzelne Zahl stehen an vierter Stelle
> entweder ein + oder ein - und an fünfter Stelle muss wieder ein einzelne
> Zahl stehen.

Also ein simpler Einzeiler ;-)

Vergiss' cctype und string.h und geh noch ein letztes mal mit Deinen 
Freunden aus und verabschiede Dich bevor Du das Deinem Lehrer 
vorlegst...

printf((x[0]>='0' && x[0]<='9' && x[1]=='D' && x[2]>='0' && x[2]<='9' && 
(x[3]=='+' || x[3]=='-') && x[4]>='0' && x[4]<='9' && !x[5]) ? "Alles 
ok" : "Eingabefehler");


Aber um auch ernstgemeinte Ratschläge zu geben: Eine Schleife brauchst 
du hier nicht wirklich, dafür aber cctype und string.h wenn du es 
vernünftig machen willst.

Überprüf die Länge der Eingabe als erstes (mit strlen)
Danach erst prüfe den Rest:
   - erst auf die Ziffern
   - dann auf das 'D'
   - dann auf + oder -

Du mußt auch nicht alles in eine Schleife setzen. Setze am Anfang eine 
Kontrollvariable auf 1 und bei einer fehlgeschlagenen Prüfung in den 
einzelnen Tests auf 0

Wenn eine Prüfung fehlschlägt (Länge des Strings, oder z.B. Ziffer an x. 
Stelle) dann brauchst (bzw. DARFST) Du die restlichen Tests NICHT mehr 
durchführen, z.B. wenn strlen==2 dann mach keinen Test an x[4] (hinter 
dem Stringende). Das macht bei fest dimensionierten Strings a la "char 
eingabe[20];" sicher nichts aus, dürfte aber Punktabzug geben.

von Klaus W. (mfgkw)


Lesenswert?

Torsten K. schrieb:
> Überprüf die Länge der Eingabe als erstes (mit strlen)

nicht nötig bei meinem Vorschlag, weil das Programm ein zu
frühes Stringende auch als Fehler erkennt (nebenbei).

Für die  erste Version schämst du dich hoffentlich etwas,
sowas macht man nicht in der Öffentlichkeit :-)

von Tobias Mehrl (Gast)


Lesenswert?

Also langsam:

Ich geb den String ein. Gut.

Jetzt stehen evtl. Fehler an den Stellen. Die möchte ich nun 
identifizieren und ALLE Eingabefehler der Reihe nach ausgeben. Wie mache 
ich das?

von Klaus W. (mfgkw)


Lesenswert?

Lohnt es sich nach dem ersten Fehler noch die restlichen auszugeben?

von Torsten K. (ago)


Lesenswert?

Klaus Wachtler schrieb:
> Für die  erste Version schämst du dich hoffentlich etwas,
> sowas macht man nicht in der Öffentlichkeit :-)

Man kann sowas sogar schachteln ;-)

von Tobias Mehrl (Gast)


Lesenswert?

"Lohnt es sich nach dem ersten Fehler noch die restlichen auszugeben?"

Eigentlich nicht; meiner Meinung nach. Aber ich weiß nicht recht was in 
meiner Aufgabe da genau verlangt ist. Das ist sehr schwammig formuliert. 
Hier der Auszug: "Quittieren Sie bitte Eingaben, die nicht dem obigen 
Format entsprechend, mit einer Fehlermeldung." Keine Ahnung ob man nun 
alle Fehler ausgeben soll, oder ob nur der erste reicht...

von Klaus W. (mfgkw)


Lesenswert?

Wenn die erste reicht, dann siehe hier 
Beitrag "Re: while-Schleife"
(statt der Kommentare halt noch eine Fehlermeldung ausgeben!)

Ansonsten:
1
  int nFehler = 0;
2
  if( !isdigit( str[0] ) )
3
  {
4
    puts( "erstes Zeichen schon falsch" );
5
    nFehler++;
6
  }
7
  if( str[1]!='D' )
8
  {
9
    puts( "kein D an zweiter Stelle" );
10
    nFehler++;
11
  }
12
  if( !isdigit( str[2] ) )
13
  {
14
    puts( "wieder keine Ziffer" );
15
    nFehler++;
16
  }
17
  if( str[3]!='+' && str[3]!='-' )
18
  {
19
    puts( "kein Vorzeichen" );
20
    nFehler++;
21
  }
22
  if( !isdigit( str[4] ) )
23
  {
24
    puts( "wieder keine Ziffer" );
25
    nFehler++;
26
  }
27
28
  if( nFehler )
29
  {
30
    printf( "%d Fehler erkannt\n", nFehler );
31
  }
32
  else
33
  {
34
    puts( "Glückwunsch!" );
35
  }

von Tobias Mehrl (Gast)


Lesenswert?

was macht na puts()?

von Klaus W. (mfgkw)


Lesenswert?

Doku lesen!

       puts() writes the string s and a trailing newline to stdout.

von Klaus W. (mfgkw)


Lesenswert?

Bzw. damit du es mal in voller Schönheit siehst:
1
klaus@i4a:~/video > man puts
2
3
PUTS(3)                                              Linux Programmer’s Manual                                              PUTS(3)
4
5
NAME
6
       fputc, fputs, putc, putchar, puts - output of characters and strings
7
8
SYNOPSIS
9
       #include <stdio.h>
10
11
       int fputc(int c, FILE *stream);
12
13
       int fputs(const char *s, FILE *stream);
14
15
       int putc(int c, FILE *stream);
16
17
       int putchar(int c);
18
19
       int puts(const char *s);
20
21
DESCRIPTION
22
       fputc() writes the character c, cast to an unsigned char, to stream.
23
24
       fputs() writes the string s to stream, without its trailing '\0'.
25
26
       putc() is equivalent to fputc() except that it may be implemented as a macro which evaluates stream more than once.
27
28
       putchar(c); is equivalent to putc(c,stdout).
29
30
       puts() writes the string s and a trailing newline to stdout.
31
32
       Calls  to  the functions described here can be mixed with each other and with calls to other output functions from the stdio
33
       library for the same output stream.
34
35
       For non-locking counterparts, see unlocked_stdio(3).
36
37
RETURN VALUE
38
       fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error.
39
40
       puts() and fputs() return a non-negative number on success, or EOF on error.
41
42
CONFORMING TO
43
       C89, C99.
44
45
BUGS
46
       It is not advisable to mix calls to output functions from the stdio library with low-level calls to write(2)  for  the  file
47
       descriptor associated with the same output stream; the results will be undefined and very probably not what you want.
48
49
SEE ALSO
50
       write(2), ferror(3), fopen(3), fputwc(3), fputws(3), fseek(3), fwrite(3), gets(3), putwchar(3), scanf(3), unlocked_stdio(3)
51
52
COLOPHON
53
       This  page  is  part  of  release  3.05 of the Linux man-pages project.  A description of the project, and information about
54
       reporting bugs, can be found at http://www.kernel.org/doc/man-pages/.
55
56
GNU                                                          1993-04-04                                                     PUTS(3)
57
 Manual page puts(3) line 1/58 (END)

von Tobias Mehrl (Gast)


Lesenswert?

Danke! Für eure Mühe! Woher hast du das manual? Wo gibts das im I-Net?

von Klaus W. (mfgkw)


Lesenswert?

Das ist eine Standard-man-Page von Unix bzw. Linux.

Die sind auch alle im Internet zu finden, falls du mit Windows
arbeitest.
Falls du Linux hast, sollten die alle da sein (notfalls das passende
Paket nachinstallieren).

Der Vorteil der man-Pages gegnüber z.B. der Onlinehilfe im
VisualStudio o.ä. ist, daß man klar sieht, was zu welchem Standard
gehört (hier: ISO-C89 und ISO-C99) und deshalb merkt, wann man
nicht mehr portabel programmiert.

von Torsten K. (ago)


Lesenswert?

Tobias Mehrl schrieb:
> Jetzt stehen evtl. Fehler an den Stellen. Die möchte ich nun
> identifizieren und ALLE Eingabefehler der Reihe nach ausgeben. Wie mache
> ich das?

Das steht doch alles schon im Beitrag von Klaus, siehe
Datum: 03.12.2010 21:36

Aber um Deine Frage "Die möchte ich nun identifizieren und ALLE 
Eingabefehler der Reihe nach ausgeben. Wie mache ich das?" doch noch zu 
beantworten:

Du prüfst auf Fehler und falls es falsch ist, dann gib eine 
entsprechende Meldung aus.

int errmask =  ((x[0]<'0'||x[0]>'9')?1:0) || ((x[1]!='D')?2:0) || 
((x[2]<'0'|| x[2]>'9')?4:0) || ((x[3]!='+'&&x[3]!='-')?8:0) || 
((x[4]<'0'||x[4]>'9')?16:0) || ((x[5])?32:0)

if (errmask & 1)
   printf("Erstes Zeichen keine Zahl.");
if (errmask & 2)
   printf("Zweites Zeichen kein 'D'.");
if (errmask & 4)
   printf("Drittes Zeichen keine Zahl.");
if (errmask & 8)
   printf("Viertes Zeichen kein + oder -.");
if (errmask & 16)
   printf("Fünftes Zeichen keine Zahl.");
if (errmask & 32)
   printf("Länge der Eingabe ungleich 5 Zeichen.");
if (!errmask)
   printf("Alles ok.");

von Klaus W. (mfgkw)


Lesenswert?

Statt der ?: hättest du es auch  mit << etwas kompakter schreiben können 
:-)

Richtig ist es, aber für einen Einsteiger vielleicht etwas hm, naja,
pädagogisch forsch?

von Torsten K. (ago)


Lesenswert?

Klaus Wachtler schrieb:
> Statt der ?: hättest du es auch  mit << etwas kompakter schreiben können
> :-)
Ich war mir da jetzt nicht sicher ob ein logisches TRUE immer als binäre 
"1" definiert ist. Ich meine früher mal gesehen (erlebt) zu haben, das 
TRUE "-1" war, also alle Bits gesetzt. Bin mir da aber nicht mehr 
sicher, ob das nun C war. Könnte der Inline-Assembler im BASIC vom 
damaligen Acorn RiscPC gewesen sein.

Klaus Wachtler schrieb:
> Richtig ist es, aber für einen Einsteiger vielleicht etwas hm, naja,
> pädagogisch forsch?

Das war schon absicht (ich weiß das es für Einsteiger unlesbar ist, 
selbst ich finde es grottig..). Irgendwie hatte ich das Gefühl das er 
sich alles vorkauen läßt, und da mache ich dann mal sowas aus frust. 
Tipps gab es hier und im Nachbarthread reichlich. Vielleicht bin ich 
auch einfach nur zu gestreßt und empfindlich....

von Karl H. (kbuchegg)


Lesenswert?

Um noch mal auf die Ausgangsfrage ganz oben zurück zu kommen.

Selbst wenn man den offensichtlichen Fehler korriegiert und schreibt
1
while((str_komplett[i] != '+') || (str_komplett[i] != '-'))
2
{
3
}

dann muss man hier etwas sagen:
Hüte dich davor, da mit Alltagswissen ranzugehen. Wir Menschen sind im 
Alltag unglaublich schlampig, wenn es um die Verwendung von UND und ODER 
geht.
In solchen Fällen empfiehlt es sich immer das ganze mit ein paar 
Beispielen durchzuspielen.

Annahme:
Das Zeichen sei 'A'
'A' ist nicht gleich '+'   die Bedingung ist also wahr
                           und die Schleife wird wiederholt

Das Zeichen sei '+'
Es ist nicht wahr, dass '+' nicht gleich '+' sei. Dieser Teil der 
Bedinung ist daher falsch. Aber
Es ist wahr, dass '+' nicht gleich '-' ist. Dieser Teil ist daher wahr.
Da sind daher 2 Teilbedingungen, die eine wahr die andere falsch. Und 
verodert ergibt das nun mal wahr.  -> die Schleife wird ausgeführt

Das Zeichen sei '-'
'-' ist nicht gleich '+'.   Diese Bedingung ist also wahr
                            und daher wird die Schleife wiederholt.


Seltsam. Egal welches Zeichen man zum Testen nimmt, die komplette 
Bedingung ist immer wahr. Völlig egal bei welchem Zeichen.

Das heist die umgangssprachliche saloppe Formulierung "Ich will die 
Schleife wiederholen, solange das Zeichen nicht '+' oder nicht '-' ist" 
ist logisch gesehen Unsinn. Das eigentlich interessante dabei ist, dass 
jeder dem du das erzählst unmittelbar versteht was du meinst und (wenn 
er selber Computer spielt) das richtige tut.

Daher Vorsicht! Bei Ausdrücken mit NICHT und UND und/oder ODER immer 
einfach ein paar Variablenwerte annehmen und den Ausdruck durchspielen! 
Und zwar so wie er dort stehen, völlig wertfrei, neutral und 
unvoreingenommen. Die Intuition ist da nämlich sehr trügerisch.

von Klaus W. (mfgkw)


Lesenswert?

Torsten K. schrieb:
> Ich war mir da jetzt nicht sicher ob ein logisches TRUE immer als binäre
> "1" definiert ist.

Alle logischen Operationen in C liefern 0 (wenn nicht erfüllt)
oder +1 (wenn erfüllt), nie etwas anderes.
Das war auch schon immer so.

Deshalb kann man so schön damit rechnen :-)

Torsten K. schrieb:
> Das war schon absicht (ich weiß das es für Einsteiger unlesbar ist,
> selbst ich finde es grottig..). Irgendwie hatte ich das Gefühl das er
> sich alles vorkauen läßt, und da mache ich dann mal sowas aus frust.
> Tipps gab es hier und im Nachbarthread reichlich. Vielleicht bin ich
> auch einfach nur zu gestreßt und empfindlich....

Naja, manchmal schwer zu sagen.
Aber bei Tobias Mehrl habe ich schon den Eindruck, daß er sich
damit beschäftigt.

Im Gegensatz zu dem hier: Beitrag "ATtiny2313 Programmieren"

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.