Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
C++ fgets, sscanf ersetzbar durch cin?!
- Ersteller _mclaren_
- Erstellt am
1
1668mib
Gast
cout ist ja nur eine Instanz einer ostream-Klasse, cin ist eine Instanz einer istream-Klasse...
Wenn du von der Tastatur einlesen willst, klar dann nimm cin (eventuell mit der Methode geline)
Wenn von Datei dann erstelle ein Objekt der ifilestream-Klasse... (so müsste sie heißen)
Edit: ne, ifstream heißt sie
Wenn du von der Tastatur einlesen willst, klar dann nimm cin (eventuell mit der Methode geline)
Wenn von Datei dann erstelle ein Objekt der ifilestream-Klasse... (so müsste sie heißen)
Edit: ne, ifstream heißt sie
- Registriert
- Dez. 2006
- Beiträge
- 909
hi
es geht um das hier
ob man das von der Überprüfung her in c++ genauso machen kann wenn ja wie.
es geht um das hier
printf("Datum im Format tt.mm.jjjj --> ");
char in[201];
fgets(in, 201, stdin);
int t, m, j;
char ch;
int test;
test = sscanf(in, "%d.%d.%d%c", &t, &m, &j, &ch);
if(test != 4 || ch != '\n') { // Eingabs syntaktisch falsch
return 0;
}
ob man das von der Überprüfung her in c++ genauso machen kann wenn ja wie.
Wenn du nur die Funktionen ersetzt, wird das trotzdem kein echtes C++. Ich würde empfehlen, eine Klasse "Datum" zu definieren mit Ein- und Ausgabeoperatoren. In diesen holst du dir dann die Benutzereingabe mit der globalen Funktion getline (-> <string> includen) und überprüfst mit einem regulären Ausdruck, ob die Eingabe passt.
- Registriert
- Dez. 2006
- Beiträge
- 909
hi - also die genaue Aufgabe ist
und wir rätsln halt grad, wie man nun auf eine gültige Eingabe prüfen kann ( weil nun die Kontrolle auf '\n' wegfallt)
Ersetzen Sie die Konsole-IO durch die objektorientierte Variante mit Hilfe von
cout und cin.
und wir rätsln halt grad, wie man nun auf eine gültige Eingabe prüfen kann ( weil nun die Kontrolle auf '\n' wegfallt)
Mir war etwas langweilig und da hab ich mal nen objektorientierten Vorschlag formuliert. Zum Kompilieren brauchst du dann noch die Boost.Regex-Bibliothek (www.boost.org).
Sieht vllt. etwas langatmig aus für die kleine Anwendung, hat aber den Vorteil, dass hier Objektorientierung auftaucht wie sie leibt und lebt. Getter- und Setter-Methoden, überladene Ein- und Ausgabestreams etc. Insbesondere die verwendete Regex ist einen Blick wert. Meine Regex ist aber noch nicht ideal, weil nur geprüft wird, ob die Eingabe mit dem Datumsformat übereinstimmt und nicht, ob es überhaupt ein gültiges Datum ist. Dein Teil überlass ich dir mal
Ansonsten hab ich aber extra ausführlich kommentiert, in der Hoffnung, dass du dir vllt. ein paar Dinge merkst.
datum.h
datum.cpp
main.cpp
HTH,
moagnus
Sieht vllt. etwas langatmig aus für die kleine Anwendung, hat aber den Vorteil, dass hier Objektorientierung auftaucht wie sie leibt und lebt. Getter- und Setter-Methoden, überladene Ein- und Ausgabestreams etc. Insbesondere die verwendete Regex ist einen Blick wert. Meine Regex ist aber noch nicht ideal, weil nur geprüft wird, ob die Eingabe mit dem Datumsformat übereinstimmt und nicht, ob es überhaupt ein gültiges Datum ist. Dein Teil überlass ich dir mal
Ansonsten hab ich aber extra ausführlich kommentiert, in der Hoffnung, dass du dir vllt. ein paar Dinge merkst.
datum.h
PHP:
#include <iostream>
#include <sstream> // für Konvertierung
#include <boost/regex.hpp> // für reguläre Ausdrücke -> siehe Wikipedia
#include <string> // für getline -> Datum einlesen
typedef enum monat {JANUAR=1, FEBRUAR, MAERZ, APRIL, MAI, JUNI, JULI, AUGUST, SEPTEMBER, OKTOBER, NOVEMBER, DEZEMBER}
MONAT; // eigener Datentyp für Monate. bei Eingabe von 1 wird Januar ausgewählt usw.
class Datum { // Datumsklasse
public: // öffentlich zugreifbar
Datum(int=1, MONAT=JANUAR, int=2000); // Konstruktor zur Erstellung eines Datums mit Standardwerten, falls keine Angabe
Datum(const Datum &); // Kopierkonstruktor zum Kopieren eines bereits vorhandenen Datumsobjekts
// getter-Methoden: Rückgabe von Eigenschaftswerten
int getTag() const;
MONAT getMonat() const;
int getJahr() const;
// setter-Methoden: Setzen dieser Werte
void setTag(int);
void setMonat(MONAT);
void setJahr(int);
private: // Eigenschaften eines Datums: nur innerhalb der oben genannten Methoden bearbeitbar
int tag;
MONAT monat;
int jahr;
};
// globale Funktionen
std::ostream & operator<<(std::ostream &, const Datum &); // Ausgabeoperator für komfortable Datumsausgabe
std::istream & operator>>(std::istream &, Datum &); // dasselbe für die Eingabe -> Datumsobjekt kann komfortabel erstellt werden
int convert_to_int(const std::string &, std::stringstream &); // eine Hilfsfunktion zur Umwandlung von eingegebenen Werte in int
// (alle private-Attribute der Klasse sind ints)
PHP:
#include "datum.h"
using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
Datum::Datum(int tag, MONAT monat, int jahr) {
this->tag = tag; // Setzen der Klassenattribute. wegen Namensgleichheit this-Zeiger benutzen (ansonsten wäre es eine Selbstzuweisung)
this->monat = monat;
this->jahr = jahr;
}
Datum::Datum(const Datum& datum) {
Datum(datum.getTag(), datum.getMonat(), datum.getJahr()); // Attributwerte über getter-Methoden ermitteln und Standardkonstruktor aufrufen
}
// einfach nur zurückgeben
int Datum::getTag() const {return tag;}
MONAT Datum::getMonat() const {return monat;}
int Datum::getJahr() const {return jahr;}
// einfach nur setzen
void Datum::setTag(int tag) {this->tag=tag;}
void Datum::setMonat(MONAT monat) {this->monat=monat;}
void Datum::setJahr(int jahr) {this->jahr=jahr;}
// Ende der Klassenmethoden und Beginn der globalen Funktionen, die von der Klasse losgelöst sind
istream & operator>>(istream & inputStream, Datum & datum) {
string eingabeString;
cout<<"Bitte um Format tt.mm.jjjj eingeben: ";
getline(std::cin, eingabeString); // Eingabe in string speichern
boost::regex pattern("^(\\d{1,2})\\.(\\d{1,2}).(\\d{4})$"); // \d: Ziffer, Zahlen in geschweiften Klammern geben
// Anzahl bzw. Anzahlsintervall an, Backslashes zum sog. "Escapen"
// {1,2
boost::smatch substrings; // Sammelbecken für Teilstrings (Tag, Monat, Jahr)
if(boost::regex_match(eingabeString, substrings, pattern)) { // Prüfen, ob Pattern auf String passt (ob richtige Eingabe erfolgt ist)
std::stringstream converter_stream; // Hilfsobjekt für die Konvertierung von string nach int
datum.setTag( convert_to_int(substrings[1].str(), converter_stream) ); // substrings[1] enthält Tag
datum.setMonat( static_cast<MONAT> ( convert_to_int( substrings[2].str(), converter_stream) ) ); // substrings[2] enthält Monat;
// Hier muss das Funktionsergebnis noch nach MONAT gecastet werden. Da enum aber intern
// ein int ist, ist das kein Problem.
datum.setJahr( convert_to_int(substrings[3].str(), converter_stream) ); // substrings[3] enthält Jahr
}
return inputStream; // Stream zurückgeben für mögliche Verkettungen, bspw. cin>>datum1>>datum2;
}
int convert_to_int(const std::string & substring, std::stringstream & converter_stream) {
converter_stream << substring;
int attribut; // kann Tag, Monat oder Jahr sein
converter_stream >> attribut;
// Stream leeren
converter_stream.clear();
converter_stream.str("");
return attribut; // umgewandelten Wert zurückgeben
}
std::ostream & operator<<(std::ostream & output_stream, const Datum & datum) {
std::cout<< datum.getTag() << "."<< static_cast<int>(datum.getMonat()) <<"."<< datum.getJahr();
return output_stream;
}
PHP:
#include "datum.h"
int main() {
Datum datum1, datum2;
std::cin>> datum1>> datum2;
std::cout<< "Datum1: "<<datum1 <<"\nDatum2: "<< datum2 <<std::endl;
}
moagnus
Zuletzt bearbeitet von einem Moderator:
(Link korrigiert)
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Also alleine das attestiert dem Aufgabensteller schon eine gewisse Inkompetenz._mclaren_ schrieb:Ersetzen Sie die Konsole-IO durch die objektorientierte Variante mit Hilfe von
cout und cin.
Um mal rudimentär zu verdeutlichen, was ich meine; wir haben das hier in C++:
Code:
class A {
int m
void f( int x) { m = x; }
};
Was ist denn hierdran anders in C?
Code:
struct A {
int m;
};
void f( A* this, int x) {
this->m = x;
}
Wenn man sich nun überlegt, dass printf( ...) nix anderes ist als ein fprintf( STDOUT, ...) und der erste Parameter von fprintf im Endeffekt immer das "Objekt" ist, steht irgendwo die Überlegung an, was an C I/O weniger objektorientiert sein soll als an C++ I/O... nur weil eine Sprache nicht direkt Objektorientierung unterstützt, heißt das noch lange nicht, dass man nicht trotzdem objektorientierten Code schreiben kann... genauso wenig wie ein C++ Programm objektorientiert ist, nur weil mal irgendwo "class" drin steht.
Folgendes sollte es wohl auch rudimentär tun:
Code:
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
char c1, c2; // könnte man auch alles noch initialisieren
int dd, mm, yyyy;
if( cin >> dd >> c1 >> mm >> c2 >> yyyy) {
char c3 = char_traits<char>().to_char_type( cin.get());
if( c1 == '.' && c2 == '.' && c3 == '\n') {
cout << "ok" << endl;
}
}
return 0;
}
Naja, vllt. ists etwas übertrieben. Aber...
Meiner Meinung weist das eindeutig auf überladene Operatoren hin, was dann so ungefähr das ergibt, was ich oben gepostet habe. Und wirklich kompliziert sind die Regechsen auch nicht...objektorientierte Variante mit Hilfe von
cout und cin