Separating a single string into separate variables - c++

In my program I receive a string: "09:07:38,50,100"
(the numbers will be changing, only commas are consistent)
My desired output would be separating the string into 3 different variables for use in other things.
like so:
a = 09:07:38
b = 50
c = 100
Currently I tried splitting the string by separating it at commas, but I still lack the ability to put the data into different variables, or at least the knowledge on how to.
Here is my current code:
#include<iostream>
#include<vector>
#include<sstream>
int main() {
std::string my_str = "09:07:38,50,100";
std::vector<std::string> result;
std::stringstream s_stream(my_str); //create stringstream from the string
while(s_stream.good()){
std::string substr;
getline(s_stream, substr, ','); //get first string delimited by comma
result.push_back(substr);
}
for(int i = 0; i<result.size(); i++){ //print all splitted strings
std::cout << result.at(i) << std::endl;
}
}

I think is a good idea to approach this kind of problem using regular expressions:
#include <string>
#include <boost\regex.hpp>
int main()
{
std::string my_str = "09:07:38,50,100";
std::string a,b,c;
boost::regex regEx("(\\d{2}:\\d{2}:\\d{2}),(\\d*),(\\d*)");
if(boost::regex_match(my_str, regEx, boost::match_extra))
{
boost::smatch what;
boost::regex_search(my_str, what, regEx);
a = what[1];
b = what[2];
c = what[3];
}
std::cout<< "a = " << a << "\n";
std::cout<< "b = " << b << "\n";
std::cout<< "c = " << c;
}

The stoi function is what you require.
a = stoi(result.at(i));
std::cout << a;

Related

Why is my string extraction function using back referencing in regex not working as intended?

Extraction Function
string extractStr(string str, string regExpStr) {
regex regexp(regExpStr);
smatch m;
regex_search(str, m, regexp);
string result = "";
for (string x : m)
result = result + x;
return result;
}
The Main Code
#include <iostream>
#include <regex>
using namespace std;
string extractStr(string, string);
int main(void) {
string test = "(1+1)*(n+n)";
cout << extractStr(test, "n\\+n") << endl;
cout << extractStr(test, "(\\d)\\+\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]([a-zA-Z])") << endl;
return 0;
}
The Output
String = (1+1)*(n+n)
n\+n = n+n
(\d)\+\1 = 1+11
([a-zA-Z])[+-/*]\1 = n+nn
([a-zA-Z])[+-/*]([a-zA-Z]) = n+nnn
If anyone could kindly point the error I've done or point me to a similar question in SO that I've missed while searching, it would be greatly appreciated.
Regexes in C++ don't work quite like "normal" regexes. Specialy when you are looking for multiple groups later. I also have some C++ tips in here (constness and references).
#include <cassert>
#include <iostream>
#include <sstream>
#include <regex>
#include <string>
// using namespace std; don't do this!
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
// pass strings by const reference
// 1. const, you promise not to change them in this function
// 2. by reference, you avoid making copies
std::string extractStr(const std::string& str, const std::string& regExpStr)
{
std::regex regexp(regExpStr);
std::smatch m;
std::ostringstream os; // streams are more efficient for building up strings
auto begin = str.cbegin();
bool comma = false;
// C++ matches regexes in parts so work you need to loop
while (std::regex_search(begin, str.end(), m, regexp))
{
if (comma) os << ", ";
os << m[0];
comma = true;
begin = m.suffix().first;
}
return os.str();
}
// small helper function to produce nicer output for your tests.
void test(const std::string& input, const std::string& regex, const std::string& expected)
{
auto output = extractStr(input, regex);
if (output == expected)
{
std::cout << "test succeeded : output = " << output << "\n";
}
else
{
std::cout << "test failed : output = " << output << ", expected : " << expected << "\n";
}
}
int main(void)
{
std::string input = "(1+1)*(n+n)";
test(input, "n\\+n", "n+n");
test(input, "(\\d)\\+\\1", "1+1");
test(input, "([a-zA-Z])[+-/*]\\1", "n+n");
return 0;
}

How to create a 0x appended hex string from a hex string for each byte of hex characters in C++?

Trying to convert my following go code question
How to create a 0x appended hex string from a hex string for each byte of hex characters in golang?
to C++ - but completely lost.
#include <iostream>
#include <string>
using namespace std;
// Function to append 0x
void appendX(string str)
{
// Appends 1 occurrences of "X" to str
str.append(1, 'X');
cout << "Modified append() : ";
cout << str;
}
int main()
{
string str("01234567891011121314151617181920");
cout << "String : " << str << endl;
appendX(str);
return 0;
}
Your function appendX() is going to append only one 'X' at the end of your input string, as your comment also says.
But if you are trying to append "0x" after every hex byte within your string, (as asked in the GO language question you mentioned), you should be appending "0x" after every 2 characters in your input string. Try below:
void appendX(String str)
{
String outstr;
for(int i=0;i<str.size();i=i+2)
{
outstr.append("0x");
outstr.append(str,i,2);
}
cout << "Modified append() : ";
cout << outstr;
}
Simplest/Understandable way is to iterate over a string and add the desirable amount of characters to a result string.
std::string insertStringInto(const std::string& s, const int interval, const std::string& sep_str)
{
std::string result_str;
auto chars_count_until_sep = interval;
for (auto ch: s)
{
if (chars_count_until_sep == 0)
{
result_str += sep_str;
chars_count_until_sep = interval;
}
result_str += ch;
--chars_count_until_sep;
}
return result_str;
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str,2,", 0x") << std::endl;
return 0;
}
Using the Ranges V3 library (in the future all these functions should be available in the C++ standard library):
std::string insertStringInto(const std::string& in_string, const int interval, const std::string& sep_str)
{
using namespace ranges::views;
auto concat_to_str = [](auto grp) { // auxilllary function to concat single characters into a string
return ranges::accumulate(grp, std::string {});
};
auto r = in_string // Use the characters from the input string parameter
| chunk(interval) // Split string up into interval count of characters
| transform(concat_to_str) // combine characters from chunks into strings
| intersperse(sep_str); // intersperse between the chunks the separator text
return concat_to_str(r); // concat all the strings into 1 string
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str, 2, ", 0x") << std::endl;
return 0;
}

how to remove spaces from a string in C++

I used "using namespace std;" in my entire study in C++,so basically I don't understand something like std::out,please help me out.Let's say I have a code shown below,i want the two string to be the same when I compare them.
int main(void)
{
using namespace std;
char a[10] = "123 ";
char b[10] = "123";
if(strcmp(a,b)==0)
{cout << "same";}
return 0;
}
If you use std::string instead of char you could use the truncate functions from boost.
Use std::string to do it
std::string a("123 ");
std::string b("123");
a.erase(std::remove_if(a.begin(), a.end(), ::isspace), a.end());
if (a == b)
std::cout << "Same";
The difference made by using will be
using namespace std;
string a("123 ");
string b("123");
a.erase(remove_if(a.begin(), a.end(), ::isspace), a.end());
if (a == b)
cout << "Same";
It is generally advised not to use the using namespace std. Don't forget to include <string> and <algorithm>.
EDIT If you still want to do it the C way, use the function from this post
https://stackoverflow.com/a/1726321/2425366
void RemoveSpaces(char * source) {
char * i = source, * j = source;
while (*j != 0) {
*i = *j++;
if (*i != ' ') i++;
}
*i = 0;
}
use regex \\s+ to match all space characters and use regex_replace to remove it
#include <iostream>
#include <regex>
#include <string>
int main()
{
std::string text = "Quick brown fox";
std::regex spaces("\\s+");
// construct a string holding the results
std::string result = std::regex_replace(text, spaces, "");
std::cout << '\n' << text << '\n';
std::cout << '\n' << result << '\n';
}
reference: http://en.cppreference.com/w/cpp/regex/regex_replace

Declaring an array of type String containing numbers with padding

I am trying to create an array of String that contain numbers. These numbers are the names of folders that I need to access. Currently I am declaring it as shown below:
String str1[] = { "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", "020", };
I have 124 folders and naming them in such fashion is tedious. Is there a better way to do this? I am working with C++.
You can use stringstreams and set the format options to fill the integer to a certain number of characters and set the filling character.
Edit: Ok my code doesn't begin with 1 but 0, but I'm sure you can figure that out :)
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
std::vector<std::string> strs;
for (int i = 0; i < 124; i++)
{
std::ostringstream os;
os << std::setfill('0') << std::setw(3) << i;
strs.push_back(os.str());
}
for (const auto& s : strs)
{
std::cout << s << "\n";
}
}
Live example: http://ideone.com/TEV2iq
use a stringstream and for loop.
Example:
uint32_t t150()
{
std::vector<std::string> strVec; // i.e. String str1[]
for (int i=1; i<125; ++i)
{
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << i;
strVec.push_back(ss.str());
}
for (int i=0; i<124; ++i)
std::cout << strVec[i] << std::endl;
return(0);
}
An alternative is something like:
std::string t150b(int i) {
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << i;
return (ss.str());
}
// not tested, and no range check
which returns the formatted string for the value i ... I imagine you have the loop at some higher level code.
Another alternative is to skip the vector, just build the string with white spaces between ... then fetch them like you fetch any file item ...
void t150c(std::stringstream& ss)
{
for (int i=1; i<125; ++i) {
ss << std::setw(3) << std::setfill('0') << i << " ";
// white space between values -------------------^^
}
}
Usage example:
{
std::stringstream ss;
t150c(ss); // 'fill' stream with desired strings
do {
if(ss.eof()) break;
std::string s;
ss >> s; // extract string one at a time
std::cout << s << std::endl; // and use
}while(1);
}
std::string str1[124];
for(int i = 1; i <= 124; i++){
str1[i-1] = convertTo3Digit(i);
}
Then just write the convertTo3Digit function to take the numerical value and format it into a 3-digit string.
Another less elegant way would be to format a column in excel to be three-digit numbers and generate 001-124 and then copy-paste into your static initializer. You can use regex to add the quotes and commas.

Make a backward string its own string?

I am brand new to programming so none of this may be right. I was just messing around trying to get the effect that I (finally) achieved. More for practice than anything else, but I wondered if there was another way to do it.
#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1="Don't even think about it!";
string str2;
string str3;
string str4 = "";
for (int i = 0; i < str1.length(); i++){
str2 = str1.substr (0, str1.length()-i);
cout << str2 << str4;
for (int x = str2.length() - 1; x >= 0; x--){
str3 = str1[x];
cout << str3;
}
str4 = str4 + " ";
cout << "\n";
}
getch();
main();
return 0;
}
The question I have is this: Is there a way to make the str3, after it is backwards, its own string that I could then justify right instead of adding spaces with str4?
In order to get a reversed string, just pass the reverse-iterators to the constructor of a new string:
#include <iostream>
#include <string>
int main() {
std::string s = "this is a test";
std::string s_reversed(s.rbegin(), s.rend());
std::cout << s << "\n" << s_reversed << "\n";
}
The output is:
$ g++ test.cc && ./a.out
this is a test
tset a si siht
Applied to your problem:
#include <iostream>
#include <string>
int main() {
std::string s = "this is a test";
for (auto i = s.length(); i > 0; i--) {
std::cout << s;
std::cout << std::string(s.rbegin(), s.rend());
std::cout << '\n';
s[i-1] = ' ';
}
}
Note that there also is an algorithm in the standard library to reverse a container, e.g., a string: std::reverse().
For reference:
http://en.cppreference.com/w/cpp/string/basic_string/basic_string
http://en.cppreference.com/w/cpp/string/basic_string/rbegin
http://en.cppreference.com/w/cpp/string/basic_string/rend
http://en.cppreference.com/w/cpp/algorithm/reverse
You could try this:
replacing letters for whitespace and then reversing the string.
Concat the modified string with the reverse of it and print it.
std::string reverse(std::string str)
{
std::reverse(str.begin(), str.end());
return str;
}
int main()
{
std::string str = "Don't even think about it!";
size_t N = str.length();
for (size_t i = 1; i < N; i++)
{
std::cout << str << reverse(str) << std::endl;
str.replace(N-i,1, " ");
}
return 0;
}
First I would rename the variables so it is more clear what you are trying to achieve. Believe me, in two months you will not have a clue what this code actually does. Suggestion:
str1 -> baseString
str2 -> forwardsClippedString
str3 -> backwardsClippedString
str4 -> gapString
Maybe these names are not even good but I think they are better than str1, ..., str4.
Then I would make a separate method of the inner loop. After that make a separate method of the outer for loop - yes, main() shouldn't be complicated at all.
Finally instead of recursively calling main I suggest to do a while-loop. An infinite one if you please (but it would be nice if one key quits the loop then).