How can I get several characters from a std::string - c++

I want to name a file according to the date and the time it was created. I'm using this code to get the date and time:
auto time = std::chrono::system_clock::now();
std::time_t end_time = chrono::system_clock::to_time_t(time);
std::string finaltime = std::ctime(&end_time);
I now want to eliminate all spaces and informations that I dont need from the finaltime-string . For this purpose I found out which characters I need. I need all except 11, 14, 17 (counter started at 0 for the first character).
In python there is a very simple way to do something like that, if you need all characters from 2 to 5 you can say mystring[2:5]. Is there somethig similar in c++ or is there another way to delete the chars I need

use the substr(a, b) function
std::string str2 = finaltime.substr (3,5); // 12:00

Related

C++ Substract the end of a string, not knowing length of the result

I have a string like this: 001,"John Marvin","doctor", "full time"
I want to delete everything after (001) with substr, but, the length of (001) is not always 3 so I can not put something like thie:
string chain = "001,\"John Marvin\",\"doctor\", \"full time\"";
std::string partial = chain.substr(0,3);
How can I proceed in this case?
You could find the index of the first comma and use that to determine where to cut off the string.
Something like:
string chain = "001,\"John Marvin\",\"doctor\", \"full time\"";
int cutoff = chain.find(',');
string newString = chain.substr(0, cutoff);
Tested here.

Decompose an ISO8601 format time stamp with regular expressions

I want to extract the minutes and seconds from an time stamp of ISO8601 format. I made some tries with regexp but I have no experience on that.
Could you please help me on this?
Examples:
PT1M46S --> 1 minute, 46 seconds
PT36S --> 36 seconds
Thanks!
getPart = #(str, c) str2double(['0' regexp(str, ['\d*(?=' c ')'], 'match', 'once')]);
str = 'PT36S';
seconds = getPart(str, 'S');
minutes = getPart(str, 'M');
hours = getPart(str, 'H');
This looks for character c, finds the digits behind it and converts them to a double. It adds character '0' in the beginning because if regexp can't find a match it returns an empty string. Adding this converts empty strings to zero while not affecting other numbers. If you want to restrict it to the parts after PT, you can remove that from original string using
str = regexprep(str, '^.*PT', '');
Use datevec to turn strings representing hours, minutes etc into corresponding numeric values. See "help datestr" to understand rules for symbols used in second input to datevec, ie. the format string. Here's how you can convert the two examples given, I leave it to you to extend it to cover the entire format.
str = 'PT36S';
str = strrep(str, 'PT', ''); % PT have to go.
if ~ismember('M', str)
% To use a single format string, we must write zero minutes if none are there already
str = ['00M', str];
end
% Date string cannot contain characters y,m,d,H,M or S, so remove these
str = strrep(str, 'S', ' ');
str = strrep(str, 'M', ' ');
% Call datevec with appropriate format string
[~, ~, ~, ~, min, sec] = datevec(str, 'MM SS')
You can extend this to manage hours, days etc by including additional if loops similar to that above. I am not familiar with this standard beyond the examples given so let me know if it's not as simple as that.

How to separate a line of input into multiple variables?

I have a file that contains rows and columns of information like:
104857 Big Screen TV 567.95
573823 Blender 45.25
I need to parse this information into three separate items, a string containing the identification number on the left, a string containing the item name, and a double variable containing the price. The information is always found in the same columns, i.e. in the same order.
I am having trouble accomplishing this. Even when not reading from the file and just using a sample string, my attempt just outputs a jumbled mess:
string input = "104857 Big Screen TV 567.95";
string tempone = "";
string temptwo = input.substr(0,1);
tempone += temptwo;
for(int i=1 ; temptwo != " " && i < input.length() ; i++)
{
temptwo = input.substr(j,j);
tempone += temp2;
}
cout << tempone;
I've tried tweaking the above code for quite some time, but no luck, and I can't think of any other way to do it at the moment.
You can find the first space and the last space using std::find_first_of and std::find_last_of . You can use this to better split the string into 3 - first space comes after the first variable and the last space comes before the third variable, everything in between is the second variable.
How about following pseudocode:
string input = "104857 Big Screen TV 567.95";
string[] parsed_output = input.split(" "); // split input string with 'space' as delimiter
// parsed_output[0] = 104857
// parsed_output[1] = Big
// parsed_output[2] = Screen
// parsed_output[3] = TV
// parsed_output[4] = 567.95
int id = stringToInt(parsed_output[0]);
string product = concat(parsed_output[1], parsed_output[2], ... ,parsed_output[length-2]);
double price = stringToDouble(parsed_output[length-1]);
I hope, that's clear.
Well try breaking down the files components:
you know a number always comes first, and we also know a number has no white spaces.
The string following the number CAN have whitespaces, but won't contain any numbers(i would assume)
After this title, you're going to have more numbers(with no whitespaces)
from these components, you can deduce:
grabbing the first number is as simple as reading in using the filestream <<.
getting the string requires you to check until you reach a number, grabbing one character at a time and inserting that into a string. the last number is just like the first, using the filestream <<
This seems like homework so i'll let you put the rest together.
I would try a regular expression, something along these lines:
^([0-9]+)\s+(.+)\s+([0-9]+\.[0-9]+)$
I am not very good at regex syntax, but ([0-9]+) corresponds to a sequence of digits (this is the id), ([0-9]+\.[0-9]+) is the floating point number (price) and (.+) is the string that is separated from the two number by sequences of "space" characters: \s+.
The next step would be to check if you need this to work with prices like ".50" or "10".

Matching algorithm or regular expression?

I have a huge log file with different types of string rows, and I need to extract data in a "smart" way from these.
Sample snippet:
2011-03-05 node32_three INFO stack trace, at empty string asfa 11120023
--- - MON 23 02 2011 ERROR stack trace NONE      
For instance, what is the best way to extract the date from each row, independent of date format?
You could make a regex for different formats like so:
(fmt1)|(fmt2)|....
Where fmt1, fmt2 etc are the individual regexes, for yor example
(20\d\d-[01]\d-[0123]\d)|((?MON|TUE|WED|THU|FRI|SAT|SUN) [0123]\d [01]\d 20\d\d)
Note that to prevent the chance to match arbitrary numbers I restricted year, month and day numbers accordingly. For example, a day number cannot start with 4, neither can a month number start with 2.
This gives the following pseudo code:
// remember that you need to double each backslash when writing the
// pattern in string form
Pattern p = Pattern.compile("..."); // compile once and for all
String s;
for each line
s = current input line;
Matcher m = p.matcher(s);
if (m.find()) {
String d = m.group(); // d is the string that matched
....
}
Each individual date pattern is written in () to make it possible to find out what format we had, like so:
int fmt = 0;
// each (fmt) is a group, numbered starting with 1 from left to right
for (int i = 1; fmt == 0 && i <= total number of different formats; i++)
if (m.group(i) != null) fmt = i;
For this to work, inner (regex) groups must be written (?regex) so that they do not count as capture-groups, look at updated example.
If you use Java, you may want to have a look at Joda time. Also, read this question and related answers. I think Joda DateTimeFormat should give you all the flexibility that you need to parse the various date/time format of your log file.
A quick example:
String dateString = "2011-04-18 10:41:33";
DateTimeFormatter formatter =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dateTime = formatter.parseDateTime(dateString);
Just define a String[] for the formats of you date/time, and pass each element to DateTimeFormat to get the corresponding DateTimeFormatter. You can use regex just separate date strings from other stuff in the log lines, and then you can use the various DateTimeFormatters to try and parse them.

How to achieve this specific datetime format using boost?

I want to format a datetime like this:
YYYYMMDD_HHMMSS
eg, 4 digit year, followed by 2 digit months, followed by 2 digit day, underscore, 24-hour hour, 2 digit minutes, 2 digit seconds.
e.g.: 16th of February 2011, 8:05 am and 2 seconds would be:
20110216_080502
What format string should I use in the following code to achieve this? (And, if necessary, what code changes are needed):
//...#includes, namespace usings...
ptime now = second_clock::universal_time();
wstringstream ss;
time_facet *facet = new time_facet("???"); //what goes here?
ss.imbue(locale(cout.getloc(), facet));
ss << now;
wstring datetimestring = ss.str();
Here are some strings I've tried so far:
%Y%m%d_%H%M%S : "2011-Feb-16 16:51:16"
%Y%m%d : "2011-Feb-16"
%H%M%S : "16:51:16"
Here's another one:
%Y : "2011-Feb-16 16:51:16" huh??
I believe you need to use wtime_facet, not time_facet. See the working program I posted on your other question.
From date/time facet format flags:
"%Y%m%d_%H%M%S"
time_facet *facet = new time_facet("%Y%m%d_%H%M%S");