with.do bei C/c++?

Gast #7923104
Lesenswert?

In Pascal/Freepascal/Delphi/Lazaurs gibt es with...do gibt es vergleichbares in C/C++?

1
type 
2
  name_rec = record 
3
             first  : string; 
4
             middle : string; 
5
             last   : string; 
6
  end; 
7
 
8
(* ... *) 
9
 
10
var  
11
  name : name_rec; 
12
 
13
(* ... *) 
14
 
15
with name do 
16
  begin 
17
    writeln(first); 
18
    writeln(middle); 
19
    writeln(last) 
20
  end
Gast #7923160
Lesenswert?

hmm, nicht ganz – dein C++-Beispiel und das Pascal-Snippet tun vom Prinzip her etwas anderes.

Dein C++-Code geht einfach die Liste durch und gibt jeden Eintrag aus. Keine Bedingung, keine Fallunterscheidung – nur Iteration.

Der Pascal Code prüft nur einen Wert (today) gegen eine Menge von Werten und entscheidet dann zwischen zwei Ausgaben. Oder sehe ich das falsch? Ich habe con C++ so absolut keine Ahnung, bin da eher auf Krabbelkind Niveau, bewege mich da eher bei Pascal oder sogar Basic als C/C++

Müsste es nicht eher so sein

1
{
2
    std::string today = "Dienstag";
3

4
    std::vector<std::string> workdays = {
5
        "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"
6
    };
7

8
    if (std::find(workdays.begin(), workdays.end(), today) != workdays.end())
9
        std::cout << "Oh great—work.\n";
10
    else
11
        std::cout << "Happy weekend!\n";
12
}
Gast #7923176
Lesenswert?

hm, aber in Pascal ist [monday..friday] ist eine echte Bereichsprüfung. Der Compiler versteht automatisch: monday <= today <= friday.

Switch in C kennt nur einzelne Werte in case, keine Bereiche. In C++ müsste man sich dann doch so behelfen

[code] switch (today) { case monday: case tuesday: case wednesday: case thursday: case friday: std::cout << "Oh great—work" << std::endl; break; default: std::cout << "Happy weekend!" << std::endl; break; } {/code]

(Firma: LAPD) #7923177
Lesenswert?

with ist evil: https://ideasawakened.com/post/why-you-should-not-use-WITH-in-your-Delphi-code ... macht mehr potenziellen Ärger als es nutzt. Wirth hat es in seinen Nachfolgesprachen nicht mehr drinn. In den meisten Codingstyles steht drinn dass man es nicht nutzen soll.

Thomas W. schrieb:

std:vectorstd::string list = {"Montag", "Dienstag", "Mittwoch"};

for (const auto& day: list) { std::cout << day << std::endl; }

Wohl eher was mit set::find. if x in [ a .. b ] in Pascal nutzt hier Mengen, das ist kein Array oder Liste auch wenn es so aussieht, afaik.

Gast #7923186
Lesenswert?

Mairian schrieb:

Switch in C kennt nur einzelne Werte in case, keine Bereiche. In C++ müsste man sich dann doch so behelfen

Doch, das geht inzwischen. Wobei die Pascal Syntax einfach und lesbar ist im Vergleich zu C++. Ohne Autocompletion kann heute keiner mehr C++ schreiben, und ohne Syntax Highlighting ist C++ unlesbar.

#7923254
Lesenswert?

Mairian schrieb:

ah ok., Jepp, in C bekomme ich Augenkrebs:-( und brauche immer etliche Versuche bis es mal so klappt, wie ich er versuche, programmiere dafür aber auch viel zu selten

Wenn du zum Augekkrebs auch nocht einen Konten im Kopf haben willst, probier es mal mit python. SCNR

Mairian schrieb:

if today in [monday..friday] then writeln ‘Oh great—work.’ else writeln ‘Happy weekend!’;

1
#include <stdio.h>
2

3
 typedef enum weekday {
4
  sunday,
5
  monday,
6
  tuesday,
7
  wednesday,
8
  thursday,
9
  friday,
10
  saturday
11
 } tWeekday;
12
int main()
13
{
14
 tWeekday today = thursday;
15

16
 if ((today >= monday) && (today <= friday))
17
 {
18
  printf("Oh great—work.\n");
19
 }
20
 else 
21
 {
22
  printf("Happy weekend!\n");
23
 }
24
}

ließ sich unter https://www.onlinegdb.com/online_c_compiler testen.

(Firma: 1984now) #7923277
Lesenswert?

Mairian schrieb:

with...do gibt es vergleichbares in C/C++?

Nö, gibt's nicht. Und ich halte das für eher gut. Dieses with-Konstrukt ist zwar manchmal scheinbar eine Erleichterung (wie etwa in gezeigtem Beispiel), aber kann auch sehr schnell in die Hölle führen.

Die Crux ist nämlich: with-Blöcke können sowohl geschachtelt werden als auch für mehrere Bezeichner gleichzeitig gelten.

Und dann noch ein paar Zeilen Code und kein Schwein kann mehr auf die Schnelle nachvollziehen, zu welchem der with-Bezeichner nun der im Block verwendete Feld-, Methoden oder Eingenschaftsname gehört. Inbesondere dann nicht, wenn es den in mehreren der in with-Klausel aufgeführten Bezeichner gibt. Die Sprachdefinition regelt zwar klar, was dann passiert, aber es ist trotzdem große Scheiße.

Sprich: with ist vor allem dazu geeignet, den Code maximal unlesbar zu machen. Eine der wenigen Sachen, die ich an Pascal Scheiße finde.

Das nutzen vor allem Leute, die ihren Code obfuskieren wollen, was in Pascal ja viel schwieriger ist als in C/C++.

#7923326
Lesenswert?

Rahul D. schrieb:

if ((today >= monday) && (today <= friday))

eine der ganz wenigen "reinen" Funktionen in unseren Sourcen ist "inrange(int, int, int), die praktisch überall genau solche Konstrukte ersetzt durch

1
if(inrange(today, monday, friday)) ...

egal ob der größere Wert als 2.ter oder 3.ter Parameter kommt oder ob überhaupt einer größer ist.

Damit offenbart sich auch die Schwäche der ganzen Konstruktion: Sunday...Monday überrascht die Hälfte der Nutzer.

#7923352
Lesenswert?

Ob S. schrieb:

Und dann noch ein paar Zeilen Code und kein Schwein kann mehr auf die Schnelle nachvollziehen, zu welchem der with-Bezeichner nun der im Block verwendete Feld-, Methoden oder Eingenschaftsname gehört

Sorry, das hat man in C++ auf jeden Schritt und Tritt, also wenn DAS ein Argument ist, dann müsste man C++ komplett verbieten.

Da weisst du nicht mal ob + addiert, ob ein 'Variablenname' nicht doch ein getter-Funktionsaufruf ist, und welche Kaskade von Funktionen dabei durchlaufen wird dank Klassenhierarchie.

#7923375
Lesenswert?

Bruno V. schrieb:

egal ob der größere Wert als 2.ter oder 3.ter Parameter kommt oder ob überhaupt einer größer ist.

Wo der größere oder kleinere Wert wo steht, ist nur eine Abfrage und ein Swap mehr. Was deine "Funktion" wohl im Hintergrund macht? Mir sind offensichtliche Lösungen lieber.

Damit offenbart sich auch die Schwäche der ganzen Konstruktion: Sunday...Monday überrascht die Hälfte der Nutzer.

Welche Schwäche? Würdest du mir bitte erklären, wo du da eine siehst? Ich hätte auch die Fernsehzeitschrift-Reihenfolge (Samstag -> Freitag) verwenden können. Selbst mit Montag als erstem und Sonntag als letztem Tag der Woche funktioniert die Abfrage. Wie sind die Wochentage denn in Pascal definiert?

#7923381
Lesenswert?

Rahul D. schrieb:

Damit offenbart sich auch die Schwäche der ganzen Konstruktion: Sunday...Monday überrascht die Hälfte der Nutzer.

Welche Schwäche? Würdest du mir bitte erklären, wo du da eine siehst?

Es funktioniert damit so nicht:

1
if ((today >= sunday) && (today <= monday))

Du müsstet dann darauf achten, in allen Fällen (und nur denen), in denen der Bereich die Grenze Sonntag -> Montag überschreitet, das && durch ein || zu ersetzen. Falls hier nicht direkte Werte sondern z.B. Variablen stehen, muss diese Unterscheidung zur Laufzeit über ein zweites if erfolgen. Solche Dinge verstecke ich dann auch lieber hinter einer Funktion. Und um das ganze dann wieder zu Pascal zurückzubringen: Was passiert eignetlich, wenn man

1
if today in [sunday..monday] then

schreibt?

#7923384
Lesenswert?

Rolf M. schrieb:

Falls hier nicht direkte Werte sondern z.B. Variablen stehen, muss diese Unterscheidung zur Laufzeit über ein zweites if erfolgen.

Sagen wir es so: Mein Beispiel erfüllt die Frage, ob das so geht. Deswegen definiere ich ja auch die enum mit den Wochentagsnamen. Es ist kein Ersatz für die "in"-Funktion, sondern nur eine Lösung für das angefragte Beispiel.

Solche Dinge verstecke ich dann auch lieber hinter einer Funktion. Das würde ich auch so machen. Aber dann müsste ich auch wissen, was die Funktion alles können soll. Weiß ich nicht, interessiert mich auch gerade nicht.

Rolf M. schrieb:

Es funktioniert damit so nicht:if ((today >= sunday) && (today <= monday))

Was soll dabei rauskommen? Meine Abfrage bezieht sich auf die von mir genannte enum. Will man was anderes haben, muss man auch die enum anpassen. Man sollte schon wissen, was man tut (sonst klemmt man sich die Finger).

#7923391
Lesenswert?

Rahul D. schrieb:

Sagen wir es so: Mein Beispiel erfüllt die Frage, ob das so geht. Deswegen definiere ich ja auch die enum mit den Wochentagsnamen. Es ist kein Ersatz für die "in"-Funktion, sondern nur eine Lösung für das angefragte Beispiel.

Meistens sucht man aber nicht eine Lösung, die speziell für ein ganz konkretes Beispiel funktioniert, sondern eine allgemeingültige.

Rolf M. schrieb:

Es funktioniert damit so nicht: if ((today >= sunday) && (today <= monday))

Was soll dabei rauskommen?

Na true, wenn heute Sonntag oder Montag ist, sonst false. Eben ein Test auf einen Bereich von Wochentagen.

Meine Abfrage bezieht sich auf die von mir genannte enum.

Und genau das ist der Punkt: Es funktioniert nur, wenn die Definition des Enums und die Abfrage genau auf einander abgestimmt sind und nicht allgemein. Und ich denke, das ist, was Bruno mit

Schwäche der ganzen Konstruktion

meinte. Du hattest ja gefragt, wo da die Schwäche ist.

Will man was anderes haben, muss man auch die enum anpassen.

Das heißt für die Abfrage, die ich gezeigt habe, würdest du dann die Tage im Enum verschieben, damit sie funktioniert? Das wird spannend, wenn du hier nicht mehr zwei feste Werte hast, sondern Variablen, in denen die Grenzen stehen.

#7923409
Lesenswert?

Rolf M. schrieb:

Meistens sucht man aber nicht eine Lösung, die speziell für ein ganz konkretes Beispiel funktioniert, sondern eine allgemeingültige.

Für DIESES Problem funktioniert die Lösung. Wenn man was allgemeingültiges haben will, sollte man die Randbedingungen definieren. Auch die Pascal-Funktion wird irgendwo ihre Grenzen haben.

Rolf M. schrieb:

Das heißt für die Abfrage, die ich gezeigt habe, würdest du dann die Tage im Enum verschieben, damit sie funktioniert? Das wird spannend, wenn du hier nicht mehr zwei feste Werte hast, sondern Variablen, in denen die Grenzen stehen.

Nö. Ich würde die Abfrage so schreiben, dass sie das Ergebnis produziert, was ich haben will, und nicht irgendwas, was sich jemand aus den Fingern gesogen hat.

Rolf M. schrieb:

Na true, wenn heute Sonntag oder Montag ist, sonst false. Eben ein Test auf einen Bereich von Wochentagen.

Ich nenne das jetzt mal "Philosophisches Geplapper", da es nichts mit der eigentlich Fragestellung (ob es das folgende Konstrukt auch in C/C++ gibt) zutun hat:

Mairian schrieb:

und sowas? if today in [monday..friday] then writeln ‘Oh great—work.’ else writeln ‘Happy weekend!’;

Antwort: Ja, kann man ähnlich realiseren.

Wie sind denn monday, friday und die anderen Wochentage definiert?

(Firma: LAPD) #7923431
Lesenswert?

Rahul D. schrieb:

Wie sind denn monday, friday und die anderen Wochentage definiert?

Üblicherweise als Aufzählungstyp (enum): type Wochentage = (monday, tuesday, usw );

Davon kann man dann Bereiche angeben eben wie in dem if [monday .. friday] oder auch über Bereiche neue Typen ableiten:

type Wochenendtage = [saturday..sunday];

Intern haben die einen Wert den man mit ord() ermitteln kann. inc(), decr() gibts auch noch zum hoch/runterzaehlen.

#7923472
Lesenswert?

Rahul D. schrieb:

Rolf M. schrieb:

Meistens sucht man aber nicht eine Lösung, die speziell für ein ganz konkretes Beispiel funktioniert, sondern eine allgemeingültige.

Für DIESES Problem funktioniert die Lösung.

Oben hast du es noch ein Beispiel genannt, und mehr als das ist es auch nicht.

Wenn man was allgemeingültiges haben will, sollte man die Randbedingungen definieren. Auch die Pascal-Funktion wird irgendwo ihre Grenzen haben.

Hab ich ja geschrieben. Ich habe mit meinen Ausführungen diese Frage beantwortet:

Rahul D. schrieb:

Damit offenbart sich auch die Schwäche der ganzen Konstruktion: Sunday...Monday überrascht die Hälfte der Nutzer.

Welche Schwäche?

und das bezieht sich nicht ausdrücklich auf C oder C++, sondern auf den Konstrukt an sich, da er in Pascal offenbar genau die gleiche Schwäche hat.

Ich nenne das jetzt mal "Philosophisches Geplapper", da es nichts mit der eigentlich Fragestellung (ob es das folgende Konstrukt auch in C/C++ gibt) zutun hat:

Es hat mit der Frage zu tun, die du gestellt hast:

Rahul D. schrieb:

Welche Schwäche? Würdest du mir bitte erklären, wo du da eine siehst?

Ich kann jetzt nicht für Bruno sprechen, aber das ist die Schwäche, die ich sehe.

Mairian schrieb:

und sowas? if today in [monday..friday] then writeln ‘Oh great—work.’ else writeln ‘Happy weekend!’;

Antwort: Ja, kann man ähnlich realiseren.

Klar kann man das. Es ist aber finde ich kein Fehler, darauf hinzuweisen, dass so ein Konstrukt generell gewisse Fallstricke mit sich bringen kann. Du hast gefragt, welche das sind, ich hab dir diese Frage beantwortet.

Rahul D. schrieb:

Frank D. schrieb:

Üblicherweise als Aufzählungstyp (enum):

Also wie in C. "Meine" enum könnte man auch problemlos von Montag bis Sonntag definieren. Und "meine" Abfrage würde immer noch funktioneren.

Wozu was "allgemeingültiges" schreiben, wenn man das Problem mit einer "popeligen" Abfrage lösen kann?

Gut, wenn du dir absoulut sicher bist, dass du in deinem Programm so einen Test nicht mit einem Bereich über die Grenze Sonntag->Montag brauchst und auch nie brauchen wirst, dann kannst du es natürlich so machen. Es kann aber (vor allem bei der Pascal-Variante, weil da die Vergleiche nicht explizit ausgeschrieben sind) durchaus überraschen, dass es evtl. nicht mehr funktioniert, wenn man eine andere Kombination an Wochentagen nimmt. Was ist jetzt so schlimm daran, darauf hinzuweisen?

#7923482
Lesenswert?

Rolf M. schrieb:

Oben hast du es noch ein Beispiel genannt, und mehr als das ist es auch nicht.

Mairian schrieb:

und sowas?

Nope. Mein Programm ist eine Beispiellösung für das von Mairian genannte "Problem". Man kann es auch auf andere Art und Weise lösen. Es ist eine erste, einfache, nachvollziehbare Lösung als Beispiel. Die muss nicht perfekt auf alle möglichen Worstcases reagieren.

Rolf M. schrieb:

Es ist aber - finde ich - kein Fehler, darauf hinzuweisen, dass so ein Konstrukt generell gewisse Fallstricke mit sich bringen kann.

Die selben Fallstricke wird es auch bei anderen Programmiersprachen geben. Deswegen nannte ich deinen Post "philosophisches Geplapper" - es trägt nicht zur Lösung der Frage bei. Es könnte sein, dass ein Fehler auftritt; muss aber nicht unter den vorgegeben Bedingungen. Dein Verhalten würden einige "übergriffig" nennen.

#7923515
Lesenswert?

Rahul D. schrieb:

Die selben Fallstricke wird es auch bei anderen Programmiersprachen geben.

Nochmal: Es bezog sich nicht auf die Programmiersprache, sondern darauf, dass der Konstrukt an sich zu Problemen führen kann.

Deswegen nannte ich deinen Post "philosophisches Geplapper" - es trägt nicht zur Lösung der Frage bei.

Nun, wenn mich jemand fragt, wie er sich am besten in den Fuß schießen kann, aber mit einem Gewehr statt einer Pistole, dann werde ich zumindest dazuschreiben, dass es generell keine gute Idee ist, sich in den Fuß zu schießen. Ob er diesen Hinweis zu Herzen nimmt oder nicht, ist kann er ja dann immer noch selbst entscheiden. Wenn mich dann noch jemand fragt, warum das keine gute Idee ist, erkläre ich es ihm eben.

Es könnte sein, dass ein Fehler auftritt; muss aber nicht unter den vorgegeben Bedingungen. Dein Verhalten würden einige "übergriffig" nennen.

Warum? Ich habe lediglich eine Frage beantwortet, die DU gestellt hast.

Da würde ich dein Verhalten eher so beschreiben. Bruno hat nebenbei erwähnt, dass der Konstrukt problematisch sein kann, du hast gefragt, warum, und ich hab dir das beantwortet. Damit hätte es eigentlich zu Ende sein können, aber du hast da inzwischen eine riesen Diskussion draus gemacht.

(Firma: 1984now) #7923595
Lesenswert?

Rahul D. schrieb:

Frank D. schrieb:

Üblicherweise als Aufzählungstyp (enum):

Also wie in C.

Nein. Diese Dinger in Pascal sind keine Aufzählungstypen, sondern Mengentypen.

Der Unterschied ist: Es ist von vorherein sichergestellt, dass die Elemente sich als Flags verwenden lassen, denn intern sind diese Dinger eher sowas wie Bitfields in C.

Bloß halt mit wesentlich besserer Unterstützung durch die Sprache, die viele Operatoren und Funktionen bereitstellt, um mit diesen Mengentypen sinnvoll zu arbeiten.

#7923609
Lesenswert?

Ob S. schrieb:

Der Unterschied ist: Es ist von vorherein sichergestellt, dass die Elemente sich als Flags verwenden lassen, denn intern sind diese Dinger eher sowas wie Bitfields in C.

Ich zitiere mal den ersten Satz von: https://learnxbyexample.com/pascal/enums/

"Our enum type ServerState has an underlying int type. Enumerated types (enums) are data structures that allow us to define a set of named values for a variable. While some languages have built-in support for enums, many can simulate them using other features." Die gleiche Definition wie in C...

Laut Wikipedia (https://de.wikipedia.org/wiki/Aufz%C3%A4hlungstyp) unterscheiden sich die enum von Pascal, Java etc von denen von C durch die Typsicherheit. Ich bin mir nicht ganz sicher, aber arm-gcc (Keil) spuckt AFAIR eine Warning aus, wenn man zwei unterschiedliche enum-Typen mischen will - gehen tut es, aber es wird gemeckert.

(Firma: LAPD) #7923616
Lesenswert?

Laut Delphisprachspec lassen sich mit Aufzaehlungstypen (das sind keine Mengen wie oben jemand behauptete, die spielen da auch rein aber sind nicht das selbe, "set" ist ein eigener Typ und kann auch andere typen aufnehmen, aufzaehlungstypen können nur ordinaltypen aufnehmen) alle Ordinaltypen möglich. Ordinaltypen sind einfach alle ganzzahligen Typen. Mann kann aufzaehlungswerten auch vordefinierte Werte zuweise wie in C bei den enums. Also der erste Wert 100 und nicht wie default eben 0,...

Beitrag #7923779 wurde von einem Moderator gelöscht.
#7923789
Lesenswert?

Im Prinzip gibt es viele gute alternativen, wieso muss es ausgerechnet eine ähnliche Lösung sein?

Das gleich ist ja name.first,name.middle und name.last .. wieso ist das schwerer als es wegzulassen?

Man könnte den Struct erweitern (Nur eine Idee):

struct MyStruct { String first; String middle; String last;

1
void printmystruct() {
2
    std::cout << first << std::endl;
3
    std::cout << middle << std::endl;
4
    std::cout << last << std::endl;
5
}

};

#7924303
Lesenswert?

Rahul D. schrieb:

Welche Schwäche?

Sorry, da habe ich Dich auf dem falschen Fuß erwischt. Ich fand Deine Zeile genau richtig, habe unsre "inrange" angebracht und wollte unabhängig davon darauf hinweisen, dass Wochentage für Ranges ungeeignet sind.

Wenn inrange als "ist in range [von ... bis]" verstanden wird, dann sollte [3 ... 5] das gleiche bedeuten wie [5 ... 3]. Bei Wochentagen ist Montag-Freitag offensichtlich was anderes wie Freitag-Montag. Und da der erste Tag unterschiedlich festgelegt ist, ist Deine Lösung für diese Aufgabe perfekt, die Aufgabe aber dumm. Für Wochentage führt es zwangsläufig früher oder später in Missverständnisse.

#7924470
Lesenswert?

Bruno V. schrieb:

Bei Wochentagen ist Montag-Freitag offensichtlich was anderes als Freitag-Montag. Und da der erste Tag unterschiedlich festgelegt ist, ist Deine Lösung für diese Aufgabe perfekt, die Aufgabe aber dumm. Für Wochentage führt es zwangsläufig früher oder später in Missverständnisse.

Danke für die Rückmeldung. Meine Fuinktion arbeitet halt nach dem Motto: "Keep it simple!" ;) Die Aufgabe ist erfüllt. Es geht ja nicht um die "in"-Funktion, sondern um das, was bei der Funktion rauskommen soll. Wenn ich ein anderes Ergebnis haben will, muss ich die Abfrage halt ändern / erweitern - ist hier aber nicht gefragt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren