Zeit in C++: Parser formatierter Eingaben
In diesem Artikel geht es um den Formatspezifizierer zum Verarbeiten von Eingaben.
(Bild: Kwangmoozaa/Shutterstock.com)
- Rainer Grimm
Dieser Artikel ist der elfte in meiner ausfĂĽhrlichen Reise durch die Chrono-Erweiterung in C++20.
- Zeit in C++20: EinfĂĽhrung in die Chrono-Terminologie
- Zeit in C++20: EinfĂĽhrung in die Chrono-Terminologie mit Zeitdauer und Zeitpunkt
- Zeit in C++20: Neue Datentypen fĂĽr die Tageszeit und das Kalenderdatum
- Zeit in C++20: Kalendertermine erstellen
- Zeit in C++20: Kalendertermine darstellen und prĂĽfen
- Zeit in C++20: Kalenderdaten abfragen und Ordinaldaten
- Zeit in C++20: Details zu der Arbeit mit Zeitzonen
- Zeitzonen in C++20: Online-Klassen
- Zeit in C++20: Chrono I/O
- C++20: Chrono I/O: Unformatiert und formatiert
Die Chrono-Bibliothek unterstützt formatierte Eingaben auf zwei Arten. Man kann die Funktionen std::chrono::from_stream oder std::chrono::parse verwenden. Beide Funktionen benötigen einen Eingabestrom und parsen die Eingabe entsprechend der Formatspezifikation in einen Zeitpunkt. Alle Formatspezifikationen außer %q für die Einheit, die entsprechend den Literalen für Zeitdauern angehängt werden, können verwendet werden.
std::chrono::from_stream
std::chrono::from_stream hat Ăśberladungen fĂĽr die verschiedenen Uhrentypen.
Uhren
std::chrono::system_timestd::chrono::utc_timestd::chrono::tai_timestd::chrono::gps_timestd::chrono::file_timestd::chrono::local_time
Kalenderdaten
std::chrono::year_month_daystd::chrono::year_monthstd::chrono::month_daystd::chrono::weekdaystd::chrono::yearstd::chrono::monthstd::chrono::day
Die verschiedenen Überladungen benötigen in der elementaren Form einen Eingabestrom is, einen Formatstring fmt und einen Zeitpunkt oder ein Kalenderobjekt chro – std::chrono::from_stream(is, fmt, chro). Das Chrono-Objekt aus dem Eingabestrom wird dann entsprechend dem Formatstring geparst.
Man kannst auch eine AbkĂĽrzung abb fĂĽr eine Zeitzone und einen Offset der UTC-Zeit angeben: std::chrono::from_stream(is, fmt, chro, abb, off). Der Offset hat den Datentyp std::chrono::minutes.
Das Programm inputChrono.cpp verwendet eine formatierte Eingabe, um einen Zeitpunkt und ein Kalenderdatum aus einem Eingabestrom zu lesen.
// inputChrono.cpp
#include <chrono>
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::cout << '\n';
std::chrono::sys_seconds timePoint;
std::istringstream iStream1{"2021-08-11 21:49:35"}; //(1)
std::chrono::from_stream(iStream1, "%F %T", timePoint); //(2)
if (iStream1) std::cout << "timePoint: "
<< timePoint << '\n';
else std::cerr << "timepoint: Reading failed\n";
std::chrono::year_month_day date1;
std::istringstream iStream2{"11/08/21"}; //(3)
std::chrono::from_stream(iStream2, "%x", date1); //(4)
if (iStream2) std::cout << "date1: " << date1 << '\n';
else std::cerr << "date1: Reading failed\n";
std::chrono::year_month_day date2;
std::istringstream iStream3{"11/15/21"};
std::chrono::from_stream(iStream3, "%x", date2); //(5)
if (iStream3) std::cout << "date2: " << date2 << '\n';
else std::cerr << "date2: Reading failed\n";
std::cout << '\n';
}
In den (1 und 2) entsprechen die Daten im Eingabestrom (iStream1) dem Formatstring ("%F %T"). Das Gleiche gilt für den Eingabestrom iStream2 (3) und den entsprechenden Formatstring "%x" (4). Im Gegensatz dazu gibt es keinen fünfzehnten Monat, und der Parse-Schritt in (5) schlägt fehl. Infolgedessen wird das Failbit des iStream3 gesetzt. Die Verwendung von iStream3 in einem booleschen Ausdruck ergibt false.
std::chrono::parse
Analog zu std::chrono::from_stream kan man die Funktion std::chrono::parse zum Parsen von Eingaben verwenden. Der folgende Codeschnipsel zeigt ihre Gleichwertigkeit.
std::chrono::from_stream(is, fmt, chro)
is >> std::chrono::parse(fmt, chro)
Statt std::chrono::from_stream wird std::chrono::parse direkt auf dem Eingabestrom is aufgerufen. std::chrono::parse benötigt außerdem einen Format-String fmt und ein Chrono-Objekt chro.
Daher kann ich das vorherige Programm inputChrono.cpp mit std::chrono::from_stream direkt in das Programm inputChronoParse.cpp mit std::chrono::parse umschreiben.
// inputChronoParse.cpp
#include <chrono>
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::cout << '\n';
std::chrono::sys_seconds timePoint;
std::istringstream iStream1{"2021-08-11 21:49:35"};
iStream1 >> std::chrono::parse("%F %T", timePoint);
if (iStream1) std::cout << "timePoint: " << timePoint << '\n';
else std::cerr << "timepoint: Reading failed\n";
std::chrono::year_month_day date1;
std::istringstream iStream2{"11/08/21"};
iStream2 >> std::chrono::parse("%x", date1);
if (iStream2) std::cout << "date1: " << date1 << '\n';
else std::cerr << "date1: Reading failed\n";
std::chrono::year_month_day date2;
std::istringstream iStream3{"11/15/21"};
iStream3 >> std::chrono::parse("%x", date2);
if (iStream3) std::cout << "date2: " << date2 << '\n';
else std::cerr << "date2: Reading failed\n";
std::cout << '\n';
}
Wie geht es weiter?
Jetzt bin ich fertig mit meiner genauen Vorstellung der Chrono-Bibliothek. In meinem nächsten Artikel werde ich über Concurrency in C++20 schreiben. (rme)