İlk başta sscanf()
yoluna giderken, IDE'yi CLion'a geçirdikten sonra, sscanf()
'u değiştirmek için std::strtol()
işlevinin kullanılmasını önerdi.
Bunun, yalnızca sscanf()
sürümü ile aynı sonucu elde etmenin bir örneği olduğunu unutmayın. Her şekilde daha kısa, evrensel ve doğru olmak değil, herkesi "saf C++ çözümü" yönüne işaret etmek. Bir API'dan aldığım ve henüz evrensel olmayan zaman damgası dizgilerine dayanıyor (benim durumumun YYYY-MM-DDTHH:mm:ss.sssZ
biçimini kullanma ihtiyacı var), farklı olanları işlemek için kolayca değiştirilebilir.
Kodu göndermeden önce, std::strtol()
kullanmadan önce yapılması gereken bir şey var: dizginin kendisini temizleme, böylece basamaklı olmayan tüm işaretleri kaldırma ("-", ":", "T", "Z") , "."), çünkü std::strtol()
olmadan rakamları yanlış yoldan ayrıştırırsınız (negatif ay veya gün değerleri olmadan bitebilirsiniz).
Bu küçük snippet, bir ISO-8601 dizesini (yukarıda belirtildiği gibi, yukarıda belirtildiği gibi) alır ve bunu milisaniye cinsinden epoch süresini temsil eden std::time_t
sonucuna dönüştürür. Buradan std::chrono-type
nesnesine gitmek oldukça kolaydır.
std::time_t parseISO8601(const std::string &input)
{
// prepare the data output placeholders
struct std::tm time = {0};
int millis;
// string cleaning for strtol() - this could be made cleaner, but for the sake of the example itself...
std::string cleanInput = input
.replace(4, 1, 1, ' ')
.replace(7, 1, 1, ' ')
.replace(10, 1, 1, ' ')
.replace(13, 1, 1, ' ')
.replace(16, 1, 1, ' ')
.replace(19, 1, 1, ' ');
// pointers for std::strtol()
const char* timestamp = cleanInput.c_str();
// last parsing end position - it's where strtol finished parsing the last number found
char* endPointer;
// the casts aren't necessary, but I just wanted CLion to be quiet ;)
// first parse - start with the timestamp string, give endPointer the position after the found number
time.tm_year = (int) std::strtol(timestamp, &endPointer, 10) - 1900;
// next parses - use endPointer instead of timestamp (skip the part, that's already parsed)
time.tm_mon = (int) std::strtol(endPointer, &endPointer, 10) - 1;
time.tm_mday = (int) std::strtol(endPointer, &endPointer, 10);
time.tm_hour = (int) std::strtol(endPointer, &endPointer, 10);
time.tm_min = (int) std::strtol(endPointer, &endPointer, 10);
time.tm_sec = (int) std::strtol(endPointer, &endPointer, 10);
millis = (int) std::strtol(endPointer, &endPointer, 10);
// convert the tm struct into time_t and then from seconds to milliseconds
return std::mktime(&time) * 1000 + millis;
}
Değil temiz ve en evrensel, ama iş sscanf()
gibi C tarzı fonksiyonları başvurmadan bitmiş olur.
Öneriler sunmak için o tarih biçiminin nasıl göründüğüne bakmak zorunda mıyız? –
C++ 11'i kullanabilir misiniz? [std :: get_time] (http://en.cppreference.com/w/cpp/io/manip/get_time) – Barry
Ne hakkında ['strptime()'] (http://linux.die.net/man/ 3/strptime)? – cdhowie