• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

C++ kleinste Zahl ausgeben

Kugelfisch

Nerd

Registriert
12 Juli 2013
Beiträge
2.342
Ort
Im Ozean
Der Code ist meines Erachtens eine sehr unschöne Mischung aus C und C++. Man muss ja nicht zwingend meine zuvor vorgeschlagene, puristische Einzeiler-Lösung nutzen (die erfüllt den Wortlaut der Aufgabe auch nicht und sollte bloss dazu dienen, den Nutzen der Standardbibliothek aufzuzeigen), doch `math.h` ist kein C++-Header (das passende Äquivalent wäre `cmath`), den kompletten Math-Header zu inkludieren, wenn man bloss die numerischen Limits benötigt scheint mir unschön (INT_MAX wird in limits.h bzw. climits definiert), und den Grund für das Einlesen als String und die explizite Konvertierung in eine Zahl kann ich nicht erkennen. Eher im Gegenteil, die <<- und >>-Operatoren der IO-Streams sind durchaus aus gutem Grund polymorph überladen.

Eine alternative C++-Lösung mit expliziter Schleife wäre:
[src=cpp]#include <iostream>
#include <limits>

int main() {
int res(std::numeric_limits<int>::max());

while(std::cin.good()) {
int x;
std::cin >> x;
if(x <= 0) break;
res = std::min(res,x);
}
std::cout << "Minimum: " << res << std::endl;
}[/src]
Man beachte die while-Bedingung std::cin.good(). Schlägt das Einlesen des nächsten Tokens im Stream in eine int-Zahl fehl, wird das failbit gesetzt, tritt ein Lesefehler auf das badbit, ist der Stream zu Ende, das eofbit. Wenn eines dieser Bits gesetzt ist, gibt die good()-Methode false zurück und die Schleife bricht ab. Exception-Handling ist an dieser Stelle nicht nötig.

Alternative unter Verwendung eines std::istream_iterator<int>, jedoch ohne std::min_element:
[src=cpp]#include <iostream>
#include <limits>
#include <iterator>

int main() {
int res(std::numeric_limits<int>::max());

for(std::istream_iterator<int> it(std::cin); *it>0&&std::cin.good(); ++it) {
res = std::min(res,*it);
}
std::cout << "Minimum: " << res << std::endl;
}[/src]

Zu beachten ist bei beiden Beispielen, dass das Resultat ungültig ist, wenn nicht mindestens eine gültige Zahl eingegeben wird. Das könnte man verhindern, indem man res mit -1 initialisiert und dies sowohl in der Schleife als auch vor der Ausgabe überprüft. Alternativ könnte man vor der Ausgabe überprüfen, ob res noch std::numeric_limits<int>::max() enthält.
 
Zuletzt bearbeitet:

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.507
Jedenfalls hat er hier im Thread jetzt noch gelernt was man unter "Programmierstil" versteht und wie viele mehr oder weniger gute Möglichkeiten es gibt schon eine eher einfache Aufgabe zu lösen :).

Wo wir grad dabei sind: In C++11 müsste man in Zeile 8 auch folgendes schreiben können:
[src=cpp]for(auto it(std::cin); *it>0&&std::cin.good(); ++it)[/src]
 

Sp1xx

NGBler

Registriert
9 Okt. 2013
Beiträge
643
Ort
Bavaria
  • Thread Starter Thread Starter
  • #23
Die ganzen Antworten zeigen mir, dass es viele Möglichkeiten gibt ein Problem zu lösen.

Ich habe mir jetzt noch diverses Lesematerial besorgt und versuche mich Stück für Stück in C++ zurecht zu finden.
 

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.507
ImHo gehts eh erstmal nur teilweise darum C++ an sich zu lernen. Zum großen Teil gehts auch darum sich das entsprechende Denken und die Themen die in fast allen Programmiersprachen vorkommen anzueignen, von Schleifen bis Speicherverwaltung.

Noch was. Wir haben alle deine Vorlage verwendet, aber in der Aufgabenstellung heißt es:
Schreibe eine Funktion, in der beliebig viele positive Zahlen eingelesen werden und die kleinste an die aufrufende Funktion zurückgegeben wird.
Du sollst gewiss eine Funktion schreiben und die innerhalb von main() dann aufrufen.
 

Sp1xx

NGBler

Registriert
9 Okt. 2013
Beiträge
643
Ort
Bavaria
  • Thread Starter Thread Starter
  • #25
Das hast du richtig gelesen.

Ich habe es mal versucht und bin auf folgendes Ergebnis gekommen:

[src=cpp]#include <iostream>
#include <iomanip>

using namespace std;


int kleiner()
{
double input;
int min=INT_MAX;

while(true)
{

cout<<"Geben sie eine Zahl ein:";
cin>>input;
if(input==0) break;

if(input<min) min=input;

}

return min;
}

int main()
{

int ergebnis;

ergebnis=kleiner();

cout<<"Die kleinste Zahl ist:"<<ergebnis;

cin.get();

}[/src]


Unschön ist noch der Abbruch bei einer Minus Zahl. Sobald eine Minus Zahl ausgegeben wird bricht das Programm ab und gibt die entsprechende Zahl aus...
 

accC

gesperrt

Registriert
14 Juli 2013
Beiträge
5.250
Das finde ich unnötig kompliziert, eine einfache Abfrage, ob der Wert kleiner ist und eine davon abhängige Zuweisung wäre besser. Anderenfalls wird res immer ein neuer Wert zugewiesen, der eben teilweise der alte res-Wert ist. Der Compiler würde das vermutlich ohnehin weg-optimieren, aber die Lesbarkeit vom Code wird dadurch unnötigerweise erschwert.

Du findest also, dass
[src=cpp]if(x < res)
res = x;[/src]

einfacher ist, als

[src=cpp]res = x < res ? x : res;[/src]

Der Compiler wird beides gleich übersetzen, wenn er nicht ganz schrottig ist. Davon abgesehen finde ich syntaktischen Zucker eigentlich immer ganz hilfreich, wenn man nicht unnötig tippseln möchte. Die Lesbarkeit wird mMn in keiner der beiden Möglichkeiten eingeschränkt.



Außerdem enthält Dein Code eine falsche Abbruchbedingung. Das Programm soll ja nicht beendet werden, wenn eine nicht-numerische Eingabe erfolgt, sondern wenn die Eingabe 0 ist. Da in der Aufgabe ausnahmslos genannt wird, dass Zahlen eingegeben werden, könnte man sich die Abfrage nach dem String ohnehin sparen.
Das habe ich wohl überlesen, allerdings sollte man zumindest beachten, was bei nicht nummerischen Eingaben passiert. Die verwendete Funktion wird dann nämlich eine Exception werfen und das sollte man durchaus beachten. Ob wie man darauf reagiert, bleibt dann jedem selbst überlassen.



Der Code ist meines Erachtens eine sehr unschöne Mischung aus C und C++. [...] doch `math.h` ist kein C++-Header (das passende Äquivalent wäre `cmath`), den kompletten Math-Header zu inkludieren, wenn man bloss die numerischen Limits benötigt scheint mir unschön (INT_MAX wird in limits.h bzw. climits definiert)
Ich habe schon seit Jahren nichts mehr mit C / C++ zu tun gehabt, zumal ich es immer nur stiefmütterlich behandelt habe. Ich hoffe man möge mir verzeihen.. ;)



und den Grund für das Einlesen als String und die explizite Konvertierung in eine Zahl kann ich nicht erkennen. Eher im Gegenteil, die <<- und >>-Operatoren der IO-Streams sind durchaus aus gutem Grund polymorph überladen.
Nun, was passiert denn, wenn im Zweifelsfall ein "a" und 4 verglichen werden bzw wenn man versucht ein int res = "a" zu setzen?
Zumindest aus der Java-Welt kommend würde ich daher zumindest eine Konvertierung durchführen, um sicher zu gehen, dass ich keinen Mist mache.




Wenn ich das noch richtig in Erinnerung habe, dann sollte int i = std::stoi(x); versuchen x in int umzuwandeln, schlägt das fehl, wird eine Exception geworfen.
Damit das Programm dann aber nicht komplett auseinander fliegt, fängst du mit catch (Exception e) die Exception wieder auf. Die Idee war, dass der Loop (der ja theoretisch unbegrenzt läuft) eben bei der Eingabe eines Nicht-Int-Wertes aufgebrochen wird und das Programm terminiert.
Sprich: Solange der Anwender Zahlen eingibt, speichert dein Algorithmus immer die kleinste Zahl, sobald eine Nicht-Zahl [genauer: ein nicht Integer] eingegeben wird, gibt der Algorithmus das Minimum aus.


Warum bei Negativzahlen eine positive Zahl ausgegeben wird, kann ich dir erklären, das hängt mit signed und unsigned Werten ab.

Wenn du unsigned 3 bit hast, dann kannst du darstellen:
(dual = dezimal)
000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7

bei signed 3 bit, kannst du darstellen:
(dual = dezimal)
000 = 0
001 = 1
010 = 2
011 = 3
100 = -1
101 = -2
110 = -3
111 = -4

Die führende 1 (also auf dem high bit) zeigt in dieser Darstellung an, dass es sich um eine negative Zahl handelt.

Wenn du an einer Stelle ein signed int verwendest, der eine führende 1 trägt, also eigentlich negativ ist und du an einer anderen Stelle mit unsigned int arbeitest, dann glaubst du eben an der zweiten Stelle du hättest eine riesige positive Zahl, während du an der anderen eben eine negative Zahl gespeichert hast.
 

Kugelfisch

Nerd

Registriert
12 Juli 2013
Beiträge
2.342
Ort
Im Ozean
Nun, was passiert denn, wenn im Zweifelsfall ein "a" und 4 verglichen werden bzw wenn man versucht ein int res = "a" zu setzen?
Zumindest aus der Java-Welt kommend würde ich daher zumindest eine Konvertierung durchführen, um sicher zu gehen, dass ich keinen Mist mache.
Das wird nicht geschehen, weil ein String in einer statisch und strikt typisierten Sprache wie C++ nicht in einer Variablen des Typs int abgelegt werden kann. Der >>-Operator ist polymorph überladen, die konkrete Operation hängt also vom Operand auf der rechten Seite ab - >> (int) liest eine Ganzzahl in eine int-Variable, >> (std::string) ein Wort ein einen std::string.
Wird ein Token eingegeben, der sich nicht in eine Ganzzahl umwandeln lässt, wird in
[src=cpp]int x;
std::cin >> x;[/src]
die Operation >> (int) fehlschlagen. In diesem Fall wird gemäss http://www.cplusplus.com/reference/istream/istream/operator>>/ das failbit des Streams gesetzt. Konnte aus dem Stream aus anderen Gründen kein Token gelesen werden, wird das badbit gesetzt. Diese Bits sollte man spätestens abfragen (etwa über std::cin.good()), bevor man einen weiteren Wert aus dem Stream zu lesen versucht (denn das wird erneut fehlschlagen).
 

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.507
Das wäre doch eine schöne Übung, dass der TE das noch in sein Programm einbaut ;-).
Hier noch ein Link der in dem Kontext interessant ist.
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
@Sp1xx: Abbruch bei Minus Zahl? Das kann ich nicht wirklich nachvollziehen. Oder versuchst du sowas wie -0.55 einzugeben? Dann ist es sogar logisch. -1 müsste er auf jeden Fall richtig erkennen.
 

Sp1xx

NGBler

Registriert
9 Okt. 2013
Beiträge
643
Ort
Bavaria
  • Thread Starter Thread Starter
  • #30
Hey,

habe das ganze noch einmal geprüft:

bild.png

Scheint jetzt zu klappen, er rundet bei Komma Zahlen nur ab.
Negative Zahlen erkennt er aber auch als kleiner, da hast du recht!
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
Die Abrundung ist aber logisch, du hast schließlich min als Integer deklariert welches nur ganze Zahlen beinhaltet. Wenn du das Ganze auf Double abänderst hast du dann auch wieder die korrekten Nachkommastellen dabei stehen. Man muss nur aufpassen ob das Initilaisieren mit MAX_INT dann noch richtig hinhaut bzw. es nicht sowas wie MAX_DOUBLE gibt.
 

Sp1xx

NGBler

Registriert
9 Okt. 2013
Beiträge
643
Ort
Bavaria
  • Thread Starter Thread Starter
  • #32
Ja der Fehler leuchtet mir auch ein und den unterschied zwischen integer und double wurde mir durch dieses Beispiel auch deutlich gemacht :)

Danke an alle für die Tipps!
 
Oben