C++ cannot name txt file after current sytem time and date - c++

Hi im having issue with this code i have made. It will compile but once i hit enter in the program it says this:
Unhandled exception at 0x008E8641 in Log Test.exe: 0xC0000005: Access violation reading location 0x566D846A.
Here is the code:
#include <iostream>
#include <time.h>
#include <fstream>
using namespace std;
int main() {
cin.get();
time_t Time;
Time = time(0);
string Date = __DATE__;
string LOG = Time + "_" + Date;
ofstream TEST;
TEST.open(LOG);
TEST << "This Text Should Appear Inside Of File.";
TEST.close();
cout << "Log has been Made.";
cin.get();
return 0;
}
I beleive that the problem is the time and how i tried putting it into a string but i dont see what i did doesn't work.

I would think that Time is an integer type so this:
Time + "_"
results in pointer addition so that what gets added to the string is a bad pointer to some location beyond the beginning of "_".
You see string literals like "_" actually resolve to an address (pointer). Adding an integer like Time to it simple makes it point elsewhere in memory.
First you need to convert your Time to a string.
I happen to have this code laying around that may work for you:
std::string get_stamp()
{
time_t t = std::time(0);
char buf[sizeof("YYYY-MM-DD HH-MM-SS")];
return {buf, std::strftime(buf, sizeof(buf), "%F %H-%M-%S", std::localtime(&t))};
}
Note: Using std::localtime is not threas-safe.

If you enabled compiler warnings, it should have screamed at you about this line:
string LOG = Time + "_" + Date;
Here, Time is being converted to a pointer, and you're getting undefined behaviour. For a not completely C++ solution, I recommend this simple approach:
time_t t = time(0);
struct tm ttm;
localtime_r( &t, &ttm );
char timestamp[20]; // actually only need 17 chars plus terminator.
sprintf_s( timestamp, sizeof(timestamp), "%04d-%02d-%02d_%02d%02d%02d",
ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_day, ttm.tm_hour, ttm.tm_min, ttm.tm_sec );
string logfilename = string(timestamp) + ".log";
ofstream logfile( logfilename.c_str() );
Note that localtime_r is not completely portable. On windows, use localtime_s, which unfortunately also reverses the order of the arguments.

Related

Combine strings in C++ to rename a file to present date

I'm new to C++. I'm trying to write a small program that will take a .txt file from my desktop, sort it in a folder and rename it to current date.
My idea is in combining three strings, first string is a direction to the main directory where I want to move the file, second string is the name of the month in my native language and the third string is the string that represents the date in dd-mm.txt format.
#include <iostream>
#include <filesystem>
#include <ctime>
using namespace std;
int main() {
int result;
std::time_t t = std::time(0);
std::tm* now = std::localtime(&t);
char date_string[100];
strftime(date_string, 50, "\\%e-%m.txt", now);
string mnths[12] = { "Januar", "Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar" };
char strt[] = "C:\\Users\\B\\Desktop\\New.txt";
char fnsh[] = "C:\\Users\\B\\Desktop\\Journal\\2020\\"+ mnths[date_string[month]]+ date_string;
result = rename(strt, fnsh);
if (result == 0)
puts("File successfully renamed");
else
perror("Error renaming file");
return 0;
};
For the second string, in case of April for example, I want to get the fourth value in the mnths array. I've tried a mishmash of solutions looking up online but now I'm lost and need help. Most notable error is "Expression must have integral or unscoped enum type" and I've googled it but I still can't understand completely how it relates to my problem and how I can fix it. Thank you.

Unexpected results when using std::stringstream

I am a beginner in C++, started last week. I am trying to make a simple program converting a number of inches to foot inch notation: E.g. 62 turns into 5'2". However when I try to compile I have some error in line 8. I don't know what it is. Thanks in advance.
#include <iostream>
#include <sstream>
using namespace std;
string ConvertToFootInchMeasure (int totalInches){
string feet = ""+totalInches/12;
string inches = "" + totalInches%12;
stringstream converted;
conveted<<feet;
converted<<"'";
converted<<inches;
converted<<"\"";
return converted.str();
}
That code can be easily fixed like this:
string ConvertToFootInchMeasure (int totalInches){
stringstream converted;
// Do inline calculations and use formatted text output for the results
converted << (totalInches/12) << "'" << (totalInches%12) << "\"";
return converted.str();
}
To explain further: You tried to concatenate the numeric results of the totalInches/12 and totalInches%12 operations to a std::string variable, but the right side of the statement doesn't do that.
Note:
std::string operator+(std::string, char c) doesn't do conversion of numerics to string and concatenation as you tried to use with:
string feet = ""+totalInches/12;
also it seems to be even worse in your case because the term
""+totalInches/12
does pointer arithmetics for a const char* pointer, and the string variable is initialized from e.g. a pointer address "" + (62/12).

C++ - How to check if today's date is an a string?

I have a C++ application I'm developing where I just need to check if the current day's date is in a char array, specifically in the format "2015-05-10". I'm pretty new to C++ coming over from PHP where it is very easy to do, but I'm struggling trying to find a good method in C++. This needs to be automated as the script runs daily on a cron job. So the process is:
If (today's date is in char array) {
do this }
else {
do nothing
}
Edit: I am obviously useless at expressing my problems, sorry!
My main issues are:
How do I get the current day's date in a nice simple string in this format - 2015-05-10
How do I then check if a char array I have stored (which I know contains a date amongst some other text) contains the current day's date (which I will, when I know how, have stored as a string).
If I understood correctly, your first want to convert the current date to the format yyyy-mm-dd and then search for the string in another string.
For the first question, you may refer to How to get current time and date in C++? where there are multiple solutions given.
For the second part of the question, if you are using strings, you should use the find (http://www.cplusplus.com/reference/string/string/find/) method and if you are using char arrays, you could use the C strstr (http://www.cplusplus.com/reference/cstring/strstr/) method.
Here's what I tried:
#include <iostream>
#include <string>
#include <cstdio>
#include <ctime>
#include <cstring>
time_t now = time(0);
struct tm tstruct;
char buf[100];
tstruct = *localtime(&now);
strftime(buf, sizeof(buf), "%Y-%m-%d", &tstruct);
//char arrays used
char ch_array[] = "This is the received string 2015-05-10 from server";
char * pch;
pch = strstr(ch_array, buf);
if (pch != nullptr)
std::cout << "Found";
//string used
std::string str("This is the received string 2015-05-10 from server");
std::size_t found = str.find(buf);
if (found != std::string::npos)
std::cout << "date found at: " << found << '\n';

Generating a short string containing the time with strange results

I have a function which creates a std::string with the time in it in cpp as follows:
#include "msattime.h"
#include <QTime>
#include <stdio.h>
#include <iostream>
std::string msattime::getTime(){
QTime t = QTime::currentTime();
std::string s;
char hours[5];
char minutes[5];
int min = t.minute();
itoa(t.hour(), hours, 10);
itoa(min, minutes, 10);
if(min < 10){
minutes[1] = minutes[0];
minutes[0] = '0';
minutes[2] = '\0';
}
s.clear();
s = s.append(hours).append(":").append(minutes);
return s;
}
This works just fine is the time in the minutes field does not contain a zero in the tens position. I changed my system time to many different values and used cout to print the string that resulted from this function. This table shows the input on the left and the output on the right.
9:19 AM || 9:19
11:20 AM || 11:20
10:20 PM || 22:20
5:24 PM || 17:24
5:00 PM || 17:00[
7:03 PM || 19:03┐
11:04 PM || 23:04!! (This is supposed to be a single character double bang)
12:09 AM || 0:09┌
The values for the hour are all correct. At some point there will be an option for the user to change the display format to 12h but for now there are no errors in those results. The only error is in the minutes place where there is an extra character added after the string. I don't get any errors when I print the string to the terminal so that suggests that it is null terminated at some point.
I have a display routine for a low resolution black and white lcd display that will print a value with center alignment. If I print this string with that alignment it gets forced to left alignment. The center printing function calculates a starting position based off of string length and then begins printing from that position. Because this string is forced to left alignment when printing using this method there is reason to believe that it is very very long.
Does anyone have any ideas about why this might be happening to me or have a suggestion for another get time function that with the same or similar output?
Environment:
Window 7 Pro w/ SP1 64bit
QT Creator IDE
QT 5.1.1
MinGW 32bit compiler with C++11 compliance turned on
I'd use strftime to do the formatting. Code would be something like this:
std::string getTime(){
time_t now = time(NULL);
struct tm *t = localtime(&now);
char buffer[16];
strftime(buffer, sizeof(buffer), "%H:%M", t);
return std::string(buffer);
}
If you're using multiple threads, you may want switch to from localtime to localtime_r instead.
The QTime class provides toString. This should be enough:
return QTime::currentTime().toString("h:mm").toStdString();
I also would recommend to use QString until you really need std::string.

Boost: How to locate the position of the iterator inside a huge text file?

I'm working in a program that uses boost::regex to match some patterns inside a huge text file (greater than 200 MB). The matches are working fine, but to build the output file I need to order the matches (just 2, but over all the text) in the sequence they are found in the text.
Well, when in debug mode, during the cout procedure I can see inside the iterator it1 an m_base attribute that shows an address that is increased each step of the loop and I think this m_base address is the address of the matched pattern in the text, but I could not certify it and I could not find a way to access this attribute to store the address.
I don't know if there is any way to retrieve the address of each matched pattern in the text, but I really need to get this information.
#define FILENAME "File.txt"
int main() {
int length;
char * cMainBuf;
ifstream is;
is.open (FILENAME, ios::binary );
is.seekg(0, ios::end);
length = is.tellg();
is.seekg (0, ios::beg);
cMainBuf = new char[length+1];
memset(cMainBuf, '\0',length+1);
is.read(cMainBuf,length);
is.close();
string str=cMainBuf;
regex reg("^(\\d{1,3}\\s[A-F]{99})");
regex rReg(reg);
int const sub_matches[] = { 1 };
boost::sregex_token_iterator it1(str.begin() ,str.end() ,rReg ,sub_matches ), it2;
while(it1!=it2)
{
cout<<"#"<<sz++<<"- "<< *(it1++) << endl;
}
return 0;
}
#sln
Hi sln,
I'll answer your questions:
1. I removed all code that is not part of this issue, so some libraries remaining there;
2. Same as 1;
3. Because the file is not a simple text file in fact, it can have any symbol and it may affect the reading procedure, as I could realize in the past;
4. Zero buffer was necessary during the tests period, since I could not store more than 1MB in the buffer;
5. the iterator doesn't allo to use char* to set the beggining and the end of the file, so was necessary to change it to string;
6. The incoming RegEx will not be declared static, this is just a draft to show the problem and the anchor act to find the line start, not only the string start;
7. sub_matches was part of the test to see where the iterator was for regex with 2 or more groups inside it;
8. sz is just a counter;
9. There is no cast possible from const std::_String_const_iterator<_Elem,_Traits,_Alloc> to long.
In fact all the code works fine, I can identify any pattern inside the text, but what I really need to know is the memory address of each matched pattern (in this case, the address of the iterator for each iteration). I could realize that m_base has this address, but I could not retrieve this address until this moment.
Ill continue the analysis, if I find any solution for this problem I post it here.
Edit #Tchesko, I am deleting my original answer. I've loaded the boost::regex and tried it out with a regex_search(). Its not the itr1 method like you are doing but, I think it comes down to just getting the results from the boost::smatch class, which is really boost::match_results().
It has member functions to get the position and length of the match and sub-matches. So, its really all you need to find the offset into your big string. The reason you can't get to m_base is that it is a private member variable.
Use the methods position() and length(). See the sample below... which I ran, debugged and tested. I'm getting back up to speed with VS-2005 again. But, boost does seem a little quirky. If I am going to use it, I want it to do Unicode, and than means I have to compile ICU. The boost binarys I'm using is downloaded 1.44. The latest is 1.46.1 so I might build it with vc++ 8 after I asess it viability with ICU.
Hey, let me know how it turns out. Good luck!
#include <boost/regex.hpp>
#include <locale>
#include <iostream>
using namespace std;
int main()
{
std::locale::global(std::locale("German"));
std::string s = " Boris Schäling ";
boost::regex expr("(\\w+)\\s*(\\w+)");
boost::smatch what;
if (boost::regex_search(s, what, expr))
{
// These are from boost::match_results() class ..
int Smpos0 = what.position();
int Smlen0 = what.length();
int Smpos1 = what.position(1);
int Smlen1 = what.length(1);
int Smpos2 = what.position(2);
int Smlen2 = what.length(2);
printf ("Match Results\n--------------\n");
printf ("match start/end = %d - %d, length = %d\n", Smpos0, Smpos0 + Smlen0, Smlen0);
std::cout << " '" << what[0] << "'\n" << std::endl;
printf ("group1 start/end = %d - %d, length = %d\n", Smpos1, Smpos1 + Smlen1, Smlen1);
std::cout << " '" << what[1] << "'\n" << std::endl;
printf ("group2 start/end = %d - %d, length = %d\n", Smpos2, Smpos2 + Smlen2, Smlen2);
std::cout << " '" << what[2] << "'\n" << std::endl;
/*
This is the hard way, still m_base is a private member variable.
Without m_base, you can't get the root address of the buffer.
long Match_start = (long)(what[0].first._Myptr);
long Match_end = (long)(what[0].second._Myptr);
long Grp1_start = (long)(what[1].first._Myptr);
long Grp1_end = (long)(what[1].second._Myptr);
*/
}
}
/* Output:
Match Results
--------------
match start/end = 2 - 17, length = 15
'Boris Schäling'
group1 start/end = 2 - 7, length = 5
'Boris'
group2 start/end = 9 - 17, length = 8
'Schäling'
*/