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_time
std::chrono::utc_time
std::chrono::tai_time
std::chrono::gps_time
std::chrono::file_time
std::chrono::local_time
Kalenderdaten
std::chrono::year_month_day
std::chrono::year_month
std::chrono::month_day
std::chrono::weekday
std::chrono::year
std::chrono::month
std::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)