Combining common code in functions as individual function in C++? - c++

I'm currently working on an application in C++, and a small part of that involves appending the date and time in array values, so I've created a couple of functions that get these values and make them look more user-friendly. There's a common chunk of code between the two functions, and I can't remember for the life of me how to stick it in it's own function and have it work as it does currently. The full code is below:
// GetDateAndTime.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <sstream>
using namespace std;
string getTime();
string getDate();
int main()
{
string theTime = getTime();
string theDate = getDate();
cout << "It is " << theTime << " on " << theDate << endl;
return 0;
}
string getTime()
{
// define variables
string strHour;
string strMin;
// get local time
time_t now;
struct tm nowLocal;
now = time(NULL);
nowLocal = *localtime(&now);
int hour = nowLocal.tm_hour;
int min = nowLocal.tm_min;
// send hour value to string
stringstream ssHour;
ssHour << hour;
if (hour >= 0 && hour <= 9)
{
strHour = "0" + ssHour.str();
}
else
{
strHour = ssHour.str();
}
// send min value to string
stringstream ssMin;
ssMin << min;
if (min >= 0 && min <= 9)
{
strMin = "0" + ssMin.str();
}
else
{
strMin = ssMin.str();
}
string curTime = strHour + ":" + strMin;
return curTime;
}
string getDate()
{
// define variables
string strDay;
string strMonth;
string strYear;
// get local time
time_t now;
struct tm nowLocal;
now = time(NULL);
nowLocal = *localtime(&now);
int day = nowLocal.tm_mday;
int month = nowLocal.tm_mon + 1;
int year = nowLocal.tm_year + 1900;
// send day value to string
stringstream ssDay;
ssDay << day;
if (day >= 1 && day <= 9)
{
strDay = "0" + ssDay.str();
}
else
{
strDay = ssDay.str();
}
// send month value to string
stringstream ssMonth;
ssMonth << month;
if (month >= 1 && month <= 9)
{
strMonth = "0" + ssMonth.str();
}
else
{
strMonth = ssMonth.str();
}
// send year value to string
stringstream ssYear;
ssYear << year;
strYear = ssYear.str();
string curDate = strDay + "/" + strMonth + "/" + strYear;
return curDate;
}
The code block in question is the one commented as "get local time". I'd appreciate any help at all! Thank you!

You can define a function called getLocalTime. This function will do what these 4 lines contains. In both getTime and getDate you'll call it.

I removed the include of stdafx.h because I couldn't compile with it, and it worked fine without it.
using namespace std;
string getTime();
string getDate();
string prepareValueForAddingToString(int dateThing) {
string str;
stringstream ssDateThing;
ssDateThing *2 left arrows* dateThing;
if (dateThing >= 1 && dateThing <= 9)
{
str = "0" + ssDateThing.str();
}
else {
str = ssDateThing.str();
}
return str;
}
int main()
{
string theTime = getTime();
string theDate = getDate();
cout << "It is " << theTime << " on " << theDate << endl;
return 0;
}
string getTime()
{
// define variables
string strHour;
string strMin;
// get local time
time_t now;
struct tm nowLocal;
now = time(NULL);
nowLocal = *localtime(&now);
int hour = nowLocal.tm_hour;
int min = nowLocal.tm_min;
// send hour value to string
string curTime;
curTime += prepareValueForAddingToString(hour);
curTime += ":";
curTime += prepareValueForAddingToString(min);
return curTime;
}
string getDate()
{
// define variables
string strDay;
string strMonth;
string strYear;
// get local time
time_t now;
struct tm nowLocal;
now = time(NULL);
nowLocal = *localtime(&now);
int day = nowLocal.tm_mday;
int month = nowLocal.tm_mon + 1;
int year = nowLocal.tm_year + 1900;
// send day value to string
string curDate;
curDate += prepareValueForAddingToString(day);
curDate += "/";
curDate += prepareValueForAddingToString(month);
curDate += "/";
curDate += prepareValueForAddingToString(year);
return curDate;
}
An example output: It is 15:26 on 07/04/2017

Related

C++: 'char*' vs 'char', getting an error when trying to assign variables

I'm working on an assignment for my programming I class. I'm brand new to C++. What we're trying to do is take year, month, and day arguments provided by the user at the time of execution and calculate the difference between them and the current date.
In my main function, I have the following code to grab those arguments from the user:
int main(int argc, char** argv)
My understanding is that this creates a character array and stores the user's arguments in it. Next, I am assigning the arguments stored in this array to new char variables so that I can pass them to a function, like so:
int main(int argc, char** argv)
{
int year, month, day;
char arg1 = argv[1];
string arg2 = argv[2];
char arg3 = argv[3];
argumentChange(argc, arg1, arg2, arg3, year, month, day);
blablabla other code
}
Where argumentChange is the function I'm sending them to. The issue is when I try to compile this, I receive the following errors:
Error: invalid conversion from 'char*' to 'char' [-fpermissive]
charArg1 = argv[1];
Error: invalid conversion from 'char*' to 'char' [-fpermissive]
charArg3 = argv[3];
I've tried searching this issue, and I can't really make heads or tails of the explanations given elsewhere. I've seen a lot of people mention "pointers", which we haven't yet covered in class and which I know nothing about. What have I done wrong? How do I make this work?
Here is the complete code for my entire program:
#include <iostream>
#include <ctime>
#include <string>
using namespace std;
void argumentChange(int numArg, char chArg1, string sArg2, char chArg3, int year, int month, int day)
{
cout << "Starting birth date: " << chArg1 << " " << sArg2 << " " << chArg3
<< endl;
if (numArg < 4 || numArg > 4)
{
cout << "Correct Usage: ./cl <birth_year><birth_month><birth_day>" << endl;
cout << "Try again, dude." << endl;
}
else if (numArg == 4)
{
year = chArg1 - '0';
day = chArg3 - '0';
if ((sArg2 == "january") || (sArg2 == "January"))
{
month = 0;
}
else if ((sArg2 == "february") || (sArg2 == "February"))
{
month = 1;
}
else if ((sArg2 == "march") || (sArg2 == "March"))
{
month = 2;
}
else if ((sArg2 == "april") || (sArg2 == "April"))
{
month = 3;
}
else if ((sArg2 == "may") || (sArg2 == "May"))
{
month = 4;
}
else if ((sArg2 == "june") || (sArg2 == "June"))
{
month = 5;
}
else if ((sArg2 == "july") || (sArg2 == "July"))
{
month = 6;
}
else if ((sArg2 == "august") || (sArg2 == "August"))
{
month = 7;
}
else if ((sArg2 == "september") || (sArg2 == "September"))
{
month = 8;
}
else if ((sArg2 == "october") || (sArg2 == "October"))
{
month = 9;
}
else if ((sArg2 == "november") || (sArg2 == "November"))
{
month = 10;
}
else if ((sArg2 == "december") || (sArg2 == "December"))
{
month = 11;
}
else
{
cout << "Error: You have entered an invalid term for month. Please type ";
cout << "the complete name of a valid month." << endl;
}
}
}
struct tm bday(int year, int month, int day)
{
struct tm r {0};
r.tm_year = year - 1900;
r.tm_mon = month;
r.tm_mday = day;
return r;
}
int main(int argc, char** argv)
{
int year, month, day;
char arg1 = argv[1];
string arg2 = argv[2];
char arg3 = argv[3];
argumentChange(argc, arg1, arg2, arg3, year, month, day);
struct tm a = bday(year, month, day);
time_t x = mktime(&a);
time_t y = time(0);
if ( x != (time_t)(-1) && y != (time_t)(-1) )
{
double difference = difftime(y, x) / (60 * 60 * 24);
cout << ctime(&x);
cout << ctime(&y);
cout << "difference = " << difference << " days" << endl;
}
return 0;
}
As pointed out, the type of argv[x] is a char*, which is a pointer to an array of chars. So char** is a pointer to an array of arrays. (Really * doesn't automatically mean it's a pointer to an array, it just does in this case)
// argv is an array of char*'s
int main(int argc, char** argv)
// firstParam is an array of char's
char* firstParam = argv[1];
// firstLetter is the first char of the array
char firstLetter = firstParam[0]
Really, you should skip all the char arrays and just use std::string's. eg
int main(int argc, char** argv) {
std::string param = argv[1];
if (param == "january") {
// Something ...
}
}
You should also really check how many arguments are being passed in, so you don't access outside the range of the array. That's what argc is for.
When storing an bunch of variables in type T, we may have a dynamic array to store it. Usually we use the pointer to the array, its type will be T*
For int as example:
int* ary1 = new int[3];
ary1[0] = 10; // ary1 + 0 store 10, a int
ary1[1] = 11; // ary1 + 1 store 11, a int
ary1[2] = 12; // ary1 + 2 store i2, a int
Same as char* string
char** argv= new char*[4];
argv[0] = "cl.exe" // ary2 + 0 stores "cl.exe", a `char*` string
argv[1] = "2018"" // ary2 + 1 stores "2018" , a `char*` string
argv[2] = "3" // ary2 + 2 stores "3" , a `char*` string
argv[3] = "16" // ary2 + 3 stores "16" , a `char*` string
So this is why you cannot assign the argv[1], (a char* string), to arg1, (a char character).

C++ Compare 2 dates and check the minutes difference

Here's the thing:
A datetime access is created with C# using DateTime.Now. This datetime is passed through JSON to a C++ method. I'm using JsonCpp to handle the Json data, but I'm not sure how to handle when the data is a datetime.
I want to compare this datetime that I received with the actual datetime and check the minutes difference between this two (if the difference is on a interval that was defined).
If I convert the Json datetime to a string using JsonCpp I have this format:
2015-06-08T11:17:23.746389-03:00
So what I'm trying to do is something like this:
var d1 = oldAccess["Date"].ToString(); //Json datetime converted to a string
var d2 = actualAccess["Date"].ToString()
if((d2 - d1) < 20) { //Difference between the two dates needs to be less than 20 minutes
return true;
} else return false;
I'm new in C++, even looking for I don't discovered how to do this.
Well, I got it. Not the best way neither the pretty one, but it works since I know that the two dates were set on the same server and always comes in the same format \"2015-01-01T23:40:00.000000-03:00\"
Here's what I did:
int convertToInt(std::string number_str){
int number;
std::istringstream ss(number_str);
ss.imbue(std::locale::classic());
ss >> number;
return number;
}
time_t convertDatetime(std::string date_str) {
time_t rawtime;
struct tm date;
int year, month, day, hour, min, sec;
date_str.erase(std::remove_if(date_str.begin(), date_str.end(), isspace), date_str.end());
year = convertToInt(date_str.substr(1, 4));
month = convertToInt(date_str.substr(6, 2));
day = convertToInt(date_str.substr(9, 2));
hour = convertToInt(date_str.substr(12, 2));
min = convertToInt(date_str.substr(15, 2));
sec = convertToInt(date_str.substr(18, 2));
time(&rawtime);
localtime_s(&date, &rawtime);
date.tm_year = year - 1900;
date.tm_mon = month - 1;
date.tm_mday = day;
date.tm_hour = hour;
date.tm_min = min;
date.tm_sec = sec;
return mktime(&date);
}
bool isValidIntervalDatetime(std::string actualDatetime_str, std::string oldDatetime_str, int maxMinutesInterval) {
double maxSecondsInterval = 60 * maxMinutesInterval;
time_t actualDatetime = convertDatetime(actualDatetime_str);
time_t oldDatetime = convertDatetime(oldDatetime_str);
double secondsDiff = difftime(actualDatetime, oldDatetime);
return secondsDiff <= maxSecondsInterval;
}
int main(int argc, char* argv[])
{
auto maxMinutesInterval = 20;
auto actuaDatetime = JsonConverter::toString(actualAccess["Date"]); // \"2015-01-02T00:00:00.000000-03:00\"
auto oldDatetime = JsonConverter::toString(oldAccess["Date"]); // \"2015-01-01T23:40:00.000000-03:00\"
if (isValidIntervalDatetime(actuaDatetime, oldDatetime, maxMinutesInterval){
//do something
}
}

C++ - compare two dates

I am writing a application which needs the possibility to compare two dates. This is what I have so far:
struct entry {
string text;
string date; // format: dd.mm.yyyy
bool finished;
};
string addNulls(int number, int cols) {
string num = to_string(number);
if (num.size() < cols) {
int count = cols - num.size();
for (int i = 0; i < count; i++) {
num = "0" + num;
}
}
return num;
}
// [...]
entry e = {"here is some text", "21.03.2019", false};
int day2 = atoi(e.date.substr(0, 2).c_str());
int month2 = atoi(e.date.substr(3, 2).c_str());
int year2 = atoi(e.date.substr(6, 4).c_str());
time_t t = time(0);
struct tm * now = localtime(&t);
string date1 = e.date.substr(6, 4) + "-" + e.date.substr(3, 2) + "-" + e.date.substr(0, 2) + " 00:00:00";
string date2 = addNulls(now->tm_year, 4) + "-" + addNulls(now->tm_mon, 2) + "-" + addNulls(now->tm_mday, 2) + " 00:00:00";
if(date2 > date1) {
// do something
}
the code gets an "entry" struct which contains a date. Than the code compares the date with the actual time. The problem is, it does not work! I run some tests with some example content, but the result (date2 > date1) returns false.
Why?
I read this: C++ compare to string dates
I'm not actually answering your question. However I am offering you a solution. Have you considered a date/time library? Boost datetime is very popular.
If you are compiling in C++11 or later, I recommend this date time library, as it is header-only (eliminating the need to link to a library such as boost), and in my opinion, it has cleaner syntax (that is a very subjective and biased viewpoint).
This latter library builds on the C++11 <chrono> library. Here is your example code using this library:
#include "date.h"
#include <iostream>
#include <string>
struct entry {
std::string text;
date::year_month_day date;
bool finished;
};
int
main()
{
entry e = {"here is some text", date::day(21)/3/2019, false};
auto day2 = e.date.day();
auto month2 = e.date.month();
auto year2 = e.date.year();
auto t = std::chrono::system_clock::now();
auto date1 = date::sys_days{e.date};
auto date2 = t;
if (date2 > date1)
std::cout << "It is past " << e.date << '\n';
else
std::cout << "It is not past " << e.date << '\n';
}
Which currently outputs:
It is not past 2019-03-21
In C++14, the chrono literals make specifying literal times very compact:
using namespace std::literals;
auto date1 = date::sys_days{e.date} + 0h + 0min + 0s;
Also on the subject of literals, you can make the construction of entry slightly more compact if you drop in a using namespace date;:
entry e = {"here is some text", 21_d/3/2019, false};
Reusing a date or datetime class, or even creating your own, is easier than trying to use a string to hold a date. Additionally you get the type-safety of not accidentally adding a string to a date, when you meant to add a time duration to a time point.
Why don't you use strptime to parse your date strings, convert them to epoch times and then compare?
#include <time.h>
char *
strptime(const char *restrict buf, const char *restrict format,
struct tm *restrict tm);

How to convert formatted string HH:MM:SS to seconds in C++

I want to convert a string time stamp formatted in HH:MM:SS to seconds only, and then compare it with a number. I have written a prime version of my code in Java, however I separately ask from Scanner as opposed to having a string time. I'm not much familiar with C++ libraries, as I'm a Java guy. Wondering how I can do it in C++?
Make it brief, String s = "1:01:01"; and String s2= "3600"; I need to know if (s>s2)
import java.util.*;
public class Test {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
int hours;
int mins;
int secs;
System.out.println("Enter Hours: ");
hours = console.nextInt();
System.out.println("Enter Minutes: ");
mins = console.nextInt();
System.out.println("Enter Seconds: ");
secs = console.nextInt();
int showSecs = (hours * 3600) + (mins * 60) + secs;
System.out.println(hours + ":" + mins + ":" + secs + " in secs are "
+ showSecs);
}
}
I'll risk the downvotes and remind you that we still have sscanf in our toolbox.
int h, m, s= 0;
std::string time ="10:40:03"
if (sscanf(time.c_str(), "%d:%d:%d", &h, &m, &s) >= 2)
{
int secs = h *3600 + m*60 + s;
}
As #ghostofstandardspast suggested you can use the std::get_time() I/O manipulator to read a specific time format from a std::istream
#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
#include <ctime>
int main() {
std::tm t;
std::istringstream ss("1:01:01");
ss >> std::get_time(&t, "%H:%M:%S");
std::cout << "Total seconds: "
<< t.tm_hour * 3600 + t.tm_min * 60 + t.tm_sec
<< std::endl;
}
Here's a fully working sample using clang. Unfortunately I couldn't get this sample running using GCC 4.8.x, I'd guess it's not complete in this implementation. May be GCC 4.9.x supports this correctly.
As looking for an alternative (if you can't use a compiler supporting the complete current c++11 standard actually), you may either consider to use std::sscanf() as #Roddy suggested, or split the string using ':' as delimiter character, and simply convert the split out parts to integer values, using the e.g. the atoi() method.
Here's the alternative
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
std::vector<std::string> &split
( const std::string &s
, char delim
, std::vector<std::string> &elems)
{
std::istringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
int main() {
std::vector<std::string> parts;
split("1:01:01",':',parts);
if(parts.size() == 3) {
int hour = std::atoi(parts[0].c_str());
int min = std::atoi(parts[1].c_str());
int sec = std::atoi(parts[2].c_str());
std::cout << "Total seconds: "
<< hour * 3600 + min * 60 + sec
<< std::endl;
}
return 0;
}
Let's do a simple automaton that parse your string:
#include <string>
int string2sec(const std::string& str) {
int i = 0;
int res = -1;
int tmp = 0;
int state = 0;
while(str[i] != '\0') {
// If we got a digit
if(str[i] >= '0' && str[i] <= '9') {
tmp = tmp * 10 + (str[i] - '0');
}
// Or if we got a colon
else if(str[i] == ':') {
// If we were reading the hours
if(state == 0) {
res = 3600 * tmp;
}
// Or if we were reading the minutes
else if(state == 1) {
if(tmp > 60) {
return -1;
}
res += 60 * tmp;
}
// Or we got an extra colon
else {
return -1;
}
state++;
tmp = 0;
}
// Or we got something wrong
else {
return -1;
}
i++;
}
// If we were reading the seconds when we reached the end
if(state == 2 && tmp < 60) {
return res + tmp;
}
// Or if we were not, something is wrong in the given string
else {
return -1;
}
}
This has not been tested so there is no warranties.
EDIT: I still can not promise anything but I ran quick tests and it seems to work properly as expected.
#include <iostream>
int main(int argc, char** argv) {
(void) argc;
(void) argv;
std::cout << string2sec("0:2:0") << std::endl;
std::cout << string2sec("1:0:0") << std::endl;
std::cout << string2sec("1:2:0") << std::endl;
std::cout << string2sec("10:10:10") << std::endl;
return 0;
}
Output:
120
3600
3720
36610

mbed application board lcd screen button control

#include "mbed.h"
#include "C12832_lcd.h"
#include<cstring>
#include<string>
#include<sstream>
C12832_LCD lcd;//creating LCD object
Serial s_comms(USBTX, USBRX);//creating a serial comms object
DigitalIn Button(p14);//using button to change pages
int main()
{
char str[100] = "$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A";
char*point;
point = strtok(str, ",");
int page_state = 0;
for (int i = 0; point != NULL; i++){
//time
if (i == 1 and page_state == 0){
//using substrings to extract time elements
string time = point;
string hrs = time.substr(0, 2);
string mins = time.substr(2, 2);
string sec = time.substr(4, 2);
//using string streams to reformat time string
ostringstream tim;
tim << hrs << ":" << mins << ":" << sec;
time = tim.str();
lcd.cls();
lcd.locate(0, 1);
lcd.printf("%s\n", time.c_str());
}
//date
if (i == 9 and page_state == 0){
string date = point;
string day = date.substr(0, 2);
string month = date.substr(2, 2);
string year = date.substr(4, 2);
//Converting the numerical month into abbreviation ect.
if (month == "03"){
month = "Mar";
}
if (month == "04"){
month = "Apr";
}
ostringstream dat;
dat << day << "-" << month << "-20" << year;
date = dat.str();
lcd.locate(0, 9);
lcd.printf("%s\n", date.c_str());
}
//latitude
if (i == 3 and page_state == 0){
string lati = point;
string lati_deg = lati.substr(0, 2);
string sml_latideg = lati.substr(2, 6);
ostringstream lat;
lat << "Lat: " << lati_deg << " deg " << sml_latideg << "'";
lati = lat.str();
lcd.locate(0, 18);
lcd.printf("%s", lati.c_str());
}
//latitude direction (N or S)
if (i == 4 and page_state == 0){
string lat_dir = point;
lcd.printf("%s\n", lat_dir.c_str());
}
point = strtok(NULL, ",");
}
//Change page
if (Button == 1){
page_state = !page_state;//toggle page state
wait(0.2);//debounce timer
lcd.cls();
}
//second page
for (int j = 0; point != NULL; j++){
char str[100] ="$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A";
char*point;
point = strtok(str, ",");
//longitude
if (j == 5 and page_state == 1){
string lngi = point;
string lngi_deg = lngi.substr(0, 2);
string sml_lngideg = lngi.substr(2, 6);
ostringstream lng;
lng << "Lng: " << lngi_deg << " deg " << sml_lngideg << "'";
lngi = lng.str();
lcd.locate(0, 1);
lcd.printf("%s", lngi.c_str());
}
//longitude direction (E or W)
if (j == 6 and page_state == 1){
string lng_dir = point;
lcd.printf("%s\n", lng_dir.c_str());
}
//speed
if (j == 7 and page_state == 1){
string speed = point;
ostringstream spd;
spd << "Speed: " << speed;
speed = spd.str();
lcd.locate(0, 9);
lcd.printf("%s\n", speed.c_str());
}
point = strtok(NULL, ",");
}
return 0;
}
hello, trying to get the onboard button on an mbed application board to allow me to clear the screen and put new info, the button currently does nothing, i am getting the first 4 parts of info on the screen however this does not change when the button is pressed, i need help to try to make this work
This does not directly answer OP's question, but this should be more helpful in the long run. Rather than trying to debug the program logic in a limited environment it is often helpful to replace the platform-specific functionality with functions and classes that allow simulation of of the platform on general purpose computing hardware without having to change the code.
By adding
#include <cstdarg>
#include <iostream>
and a fake C12832_lcd.h
#pragma once
#include <cstdarg>
#include <iostream>
// Sim LCD class. Just writes LCD commands to console
class C12832_LCD
{
public:
void cls()
{
std::cout << "LCD: Cleared" << std::endl;
}
void locate(int row, int col)
{
std::cout << "LCD: positioned " << row << "," << col << std::endl;
}
void printf(const char * fmt, ...)
{
char buffer[4096];
va_list args;
va_start(args, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, args);
std::cout << buffer << std::endl;
va_end(args);
}
};
And a bogus mbed.h
#pragma once
// Sim DigitalIn class. Toggles true and false on the button. First call will be true
class DigitalIn
{
private:
bool mVal;
public:
DigitalIn(int): mVal(false)
{
}
bool operator==(int)
{
mVal = !mVal;
return mVal;
}
};
//Sim serial Does nothing yet.
class Serial
{
public:
Serial(int, int)
{
}
};
//sim wait. We don't need to wait in simulation, so does nothing.
void wait(double)
{
}
const int p14 = 14;
const int USBTX = 0;
const int USBRX = 0;
to OP's code, I can now compile and run on the desktop in the Visual Studio IDE and throw the awesome might of the debugger at the problem. Stepping through the code quickly reveals the first of two logic errors. The second one is a bit more subtle. Watch your scope.
A quick recommendation:
Rather than using strtok, consider using the std::getline overload that takes a character delimiter. This allows
std::stringstream stream(str);
std::string token;
while (std::getline(stream, token, ','))
{
// do stuff
}
to read through a comma separated stream of input like a NMEA string.