commit 481eeccdc7b21d185e35505bb44c416cd4eb2764 Author: Leonetienne Date: Sat Mar 19 14:15:03 2022 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc84959 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f7c451d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.16) +project(wdate) + +set(CMAKE_CXX_STANDARD 17) + +add_executable(wdate + main.cpp +) + diff --git a/StringTools.cpp b/StringTools.cpp new file mode 100644 index 0000000..1a51417 --- /dev/null +++ b/StringTools.cpp @@ -0,0 +1,156 @@ +#include "StringTools.h" +#include + +std::string StringTools::Replace(const std::string& str, const char find, const std::string& subst) { + std::stringstream ss; + + for (std::size_t i = 0; i < str.length(); i++) + { + if (str[i] != find) + ss << str[i]; + else + ss << subst; + } + + return ss.str(); +} + +std::string StringTools::Replace(const std::string& str, const std::string& find, const std::string& subst) { + if (find.length() == 0) + return str; + + std::stringstream ss; + + std::size_t posFound = 0; + std::size_t lastFound = 0; + + while (posFound != std::string::npos) + { + lastFound = posFound; + posFound = str.find(find, posFound); + + if (posFound != std::string::npos) + { + ss << str.substr(lastFound, posFound - lastFound) << subst; + posFound += find.length(); + } + else + { + ss << str.substr(lastFound, (str.length()) - lastFound); + } + } + + return ss.str(); +} + +std::string StringTools::Replace(const std::string& str, const char find, const char subst) { + std::stringstream ss; + ss << subst; + + return Replace(str, find, ss.str()); +} + +std::string StringTools::Replace(const std::string& str, const std::string& find, const char subst) { + std::stringstream ss; + ss << subst; + + return Replace(str, find, ss.str()); +} + +std::string StringTools::Lower(const std::string& str) { + std::stringstream ss; + + for (std::size_t i = 0; i < str.size(); i++) + { + const char c = str[i]; + + // Quick-accept: regular letters + if ((c >= 'A') && (c <= 'Z')) + ss << (char)(c | 32); + + // Else: keep the character as is + else ss << c; + } + + return ss.str(); +} + +std::string StringTools::Upper(const std::string& str) { + std::stringstream ss; + + for (std::size_t i = 0; i < str.size(); i++) + { + const char c = str[i]; + + // Quick-accept: regular letters + if ((c >= 'a') && (c <= 'z')) + ss << (char)(c & ~32); + + // Else: keep the character as is + else ss << c; + } + + return ss.str(); +} + +std::vector StringTools::Split(const std::string& str, const std::string& seperator) { + std::vector toRet; + // Quick-accept: str length is 0 + if (str.length() == 0) + toRet.push_back(""); + + // Quick-accept: seperator length is 0 + else if (seperator.length() == 0) { + for (const char c : str) + toRet.push_back(std::string(&c, (&c) + 1)); + } + + else { + std::size_t idx = 0; + while (idx != std::string::npos) { + std::size_t lastIdx = idx; + idx = str.find(seperator, idx); + + // Grab our substring until the next finding of sep + if (idx != std::string::npos) { + toRet.push_back(str.substr( + lastIdx, + idx - lastIdx + )); + + idx += seperator.length(); + } + // No more seperator found. Grab the rest until the end of the string + else { + toRet.push_back(str.substr( + lastIdx + )); + } + } + } + + return toRet; +} + +std::string StringTools::PadLeft(const std::string& str, const char pad, const std::size_t len) { + std::stringstream ss; + + for (std::size_t i = str.length(); i < len; i++) + ss << pad; + + ss << str; + + return ss.str(); +} + +std::string StringTools::PadRight(const std::string& str, const char pad, const std::size_t len) { + std::stringstream ss; + + ss << str; + + for (std::size_t i = str.length(); i < len; i++) + ss << pad; + + return ss.str(); +} + diff --git a/StringTools.h b/StringTools.h new file mode 100644 index 0000000..51bf79b --- /dev/null +++ b/StringTools.h @@ -0,0 +1,44 @@ +#ifndef STRINGTOOLS_STRINGTOOLS_H +#define STRINGTOOLS_STRINGTOOLS_H + +#include +#include + +/* Handy utensils to manipulate strings */ +class StringTools +{ + public: + //! Will replace every occurence of `find` in `str` by `subst`. + static std::string Replace(const std::string& str, const char find, const std::string& subst); + + //! Will replace every occurence of `find` in `str` by `subst`. + static std::string Replace(const std::string& str, const std::string& find, const std::string& subst); + + //! Will replace every occurence of `find` in `str` by `subst`. + static std::string Replace(const std::string& str, const char find, const char subst); + + //! Will replace every occurence of `find` in `str` by `subst`. + static std::string Replace(const std::string& str, const std::string& find, const char subst); + + //! Will make a string all-lowercase. + static std::string Lower(const std::string& str); + + //! Will make a string all-uppercase. + static std::string Upper(const std::string& str); + + //! Will split a string by a string seperator + static std::vector Split(const std::string& str, const std::string& seperator); + + //! Will pad a string to the left to length l + static std::string PadLeft(const std::string& str, const char pad, const std::size_t len); + + //! Will pad a string to the right to length l + static std::string PadRight(const std::string& str, const char pad, const std::size_t len); + + private: + // No instanciation! >:( + StringTools(); +}; + +#endif //STRINGTOOLS_STRINGTOOLS_H + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..7552e9b --- /dev/null +++ b/main.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include "spell.h" +#include "StringTools.h" + +std::string Eval(const std::string& cmd) { + FILE *p; + char ch; + + p = popen(cmd.c_str(), "r"); + if (p == NULL) { + std::cerr << "Unable to open a process. Make sure the requested program is installed! Tried to call:" << std::endl + << "'" << cmd << "'" << std::endl; + exit(-1); + } + + std::stringstream ss; + while ((ch=fgetc(p)) != EOF ) + ss << ch; + + // Remove terminating linebreak, if present + std::string out = ss.str(); + if ((out.length() > 0) && (out[out.length() - 1] == '\n')) + out = out.substr(0, out.length() - 1); + + return out; +} + +static const std::vector daynths = { + "first", + "second", + "third", + "fourth", + "fifth", + "sixth", + "seventh", + "eighth", + "ninth", + "tenth", + "eleventh", + "twelfth", + "thirteenth", + "fourteenth", + "fifteenth", + "sixteenth", + "seventeenth", + "eighteenth", + "nineteenth", + "twentieth", + "twentyfirst", + "twentysecond", + "twentythird", + "twentyfourth", + "twentyfifth", + "twentysixth", + "twentyseventh", + "twentyeighth", + "twentyninth", + "thirtieth", + "thirtyfirst" +}; + +int main() { + const std::string weekday = Eval("date +'\%A'"); + const std::string month = Eval("date +'\%B'"); + const std::string year = spell(std::stoi(Eval("date +'\%Y'"))); + const std::string day = daynths[std::stoi(Eval("date +'\%d'"))]; + const std::string hour = spell(std::stoi(Eval("date +'\%H'"))); + const std::string minute = spell(std::stoi(Eval("date +'\%M'"))); + const std::string seconds = spell(std::stoi(Eval("date +'\%S'"))); + + std::stringstream ss; + ss << "It is " + << weekday << ", the " + << day << " of " + << month << ", " << year << ". " + << "It is " + << hour << " " << minute + << " and " + << seconds << " seconds."; + + std::cout << ss.str() << std::endl; + + return 0; +} + diff --git a/spell.h b/spell.h new file mode 100644 index 0000000..daf6ea1 --- /dev/null +++ b/spell.h @@ -0,0 +1,56 @@ +#include +#include +using std::string; + +const char* smallNumbers[] = { + "zero", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", + "eleven", "twelve", "thirteen", "fourteen", "fifteen", + "sixteen", "seventeen", "eighteen", "nineteen" +}; + +string spellHundreds(unsigned n) { + string res; + if (n > 99) { + res = smallNumbers[n/100]; + res += " hundred"; + n %= 100; + if (n) res += " and "; + } + if (n >= 20) { + static const char* Decades[] = { + "", "", "twenty", "thirty", "forty", + "fifty", "sixty", "seventy", "eighty", "ninety" + }; + res += Decades[n/10]; + n %= 10; + if (n) res += "-"; + } + if (n < 20 && n > 0) + res += smallNumbers[n]; + return res; +} + +const char* thousandPowers[] = { + " billion", " million", " thousand", "" }; + +typedef unsigned long Spellable; + +string spell(Spellable n) { + if (n < 20) return smallNumbers[n]; + string res; + const char** pScaleName = thousandPowers; + Spellable scaleFactor = 1000000000;// 1 billion + while (scaleFactor > 0) { + if (n >= scaleFactor) { + Spellable h = n / scaleFactor; + res += spellHundreds(h) + *pScaleName; + n %= scaleFactor; + if (n) res += " "; + } + scaleFactor /= 1000; + ++pScaleName; + } + return res; +} +