I'm a C++ newbie who came from Java, so I need some guidance on some really basic issues I'm stumbling upon as I go.
I'm reading lines from a file, and each line consists of 6 strings/ints, which will be sent as parameters to a temporary variable.
Example:
Local1,Local2,ABC,200,300,asphalt
However, there are two subtypes of variable. One has a string as the last parameter (like 'asphalt' in the example above). The other one has an int instead. I have a method that reads each parameter and sends it to a variable, but how do I detect if the last bit of string is an integer or a string beforehand, so I know if I should send it to a Type1 variable or a Type2 one?
Many thanks!
Since you want to determine the type of the last column, then this ought to work:
#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <sstream>
#include <cctype>
#include <algorithm>
enum Types {
NONE,
STRING,
INTEGER,
DOUBLE
};
struct Found {
std::string string_val;
int integer_val;
double double_val;
enum Types type;
};
//copied verbatim from:
//http://stackoverflow.com/a/2845275/866930
inline bool isInteger(const std::string &s) {
if(s.empty() || ((!std::isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
char * p ;
std::strtol(s.c_str(), &p, 10);
return (*p == 0);
}
//modified slightly for decimals:
inline bool isDouble(const std::string &s) {
if(s.empty() || ((!std::isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ;
char * p ;
std::strtod(s.c_str(), &p) ;
return (*p == 0);
}
bool isNotAlpha(char c) {
return !(std::isalpha(c));
}
//note: this searches for strings containing only characters from the alphabet
//however, you can modify that behavior yourself.
bool isString (const std::string &s) {
std::string::const_iterator it = std::find_if(s.begin(), s.end(), isNotAlpha);
return (it == s.end()) ? true : false;
}
void determine_last_column (const std::string& str, Found& found) {
//reset found:
found.integer_val = 0;
found.double_val = 0;
found.string_val = "";
found.type = NONE;
std::string temp;
std::istringstream iss(str);
int column = 0;
char *p;
while(std::getline(iss, temp, ',')) {
if (column == 5) {
//now check to see if the column is an integer or not:
if (isInteger(temp)) {
found.integer_val = static_cast<int>(std::strtol(temp.c_str(), &p, 10));
found.type = INTEGER;
}
else if (isDouble(temp)) {
found.double_val = static_cast<double>(std::strtod(temp.c_str(), &p));
found.type = DOUBLE;
}
else if (isString(temp)) {
found.string_val = temp;
found.type = STRING;
}
}
++column;
}
if (found.type == INTEGER) {
std::cout << "An integer was found: " << found.integer_val << std::endl;
}
else if(found.type == DOUBLE) {
std::cout << "A double was found: " << found.double_val << std::endl;
}
else if(found.type == STRING) {
std::cout << "A string was found: " << found.string_val << std::endl;
}
else {
std::cout << "A valid type was not found! Something went wrong..." << std::endl;
}
}
int main() {
std::string line_t1 = "Local1,Local2,ABC,200,300,asphalt";
std::string line_t2 = "Local1,Local2,ABC,200,300,-7000.3";
Found found;
determine_last_column(line_t1, found);
determine_last_column(line_t2, found);
return 0;
}
This outputs and correctly assigns the appropriate value:
A string was found: asphalt
An integer was found: -7000.3
This version works on int, double, string; does not require boost; and, is plain vanilla C++98.
REFERENCES:
UPDATE:
This version now supports both positive and negative numbers that are integers or doubles, in addition to strings.
First, create an array that can store both strings and integers:
std::vector<boost::variant<std::string, int>> items;
Second, split the input string on commas:
std::vector<std::string> strings;
boost::split(strings, input, boost::is_any_of(","));
Last, parse each token and insert it into the array:
for (auto&& string : strings) {
try {
items.push_back(boost::lexical_cast<int>(string));
} catch(boost::bad_lexical_cast const&) {
items.push_back(std::move(string));
}
}
Related
I want to implement a simple is_number function that checks if it's an integer, float or an unsigned long int using this method:
bool isNumber(const std::string& str)
{
size_t idx = 0;
//Check if it's an integer
std::stoi(str,&idx);
if (idx == str.size())
return true;
//Check if it's a float
std::stof(str,&idx);
if (idx == str.size() || str[str.size()-1] == 'f' && idx == str.size()) //Cause I do have some float numbers ending with 'f' in the database
return true;
//Check if it's an unsigned long int
std::stoul(str,&idx);
if (idx == str.size())
return true;
return false;
}
But if I test it with a pure string like "test" or "nan", it will throw an error because I'm trying to change a pure string to an integer.
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoi
However if I test it with "0nan" for example, stoi or the others will retrieve the first number and assign the index position of the first found number to the idx variable.
Is it possible to find a workaround for pure strings like "nan" or any other?
Or is there a better method to implement this without regex or try-catch?
std::stoi throws when it fails. Instead of using C i/o you can use C++ streams, try to read from the stream and check if there is something left in the stream:
#include <string>
#include <sstream>
#include <iostream>
enum Number {Float,Signed,Unsigned,NotANumber};
template <typename T>
bool is_only_a(const std::string& str){
std::stringstream ss(str);
T x;
return (ss >> x && ss.rdbuf()->in_avail() ==0);
}
Number isNumber(const std::string& str)
{
size_t idx = 0;
if (is_only_a<unsigned long>(str)) return Unsigned;
else if (is_only_a<int>(str)) return Signed;
else if (is_only_a<float>(str)) return Float;
return NotANumber;
}
int main() {
std::cout << isNumber("1.2") << "\n";
std::cout << isNumber("12") << "\n";
std::cout << isNumber("-12") << "\n";
std::cout << isNumber("asd") << "\n";
std::cout << isNumber("nan") << "\n";
}
Order is important, because 12 could be a float as well.
The link I posted in the comments is most probably what you need.
The only slight modification needed from the answers there is adding a +/- sign, and an optional (at most one) decimal point:
bool isNumber(const std::string &s) {
bool first_char = true;
bool saw_decpt = false;
for (const auto &it: s) {
if (std::isdigit(it)) { first_char = false; }
else if (it == '+' && first_char) { first_char = false; }
else if (it == '-' && first_char) { first_char = false; }
else if (it == '.' && !saw_decpt) { first_char = false; saw_decpt = true; }
else return false;
}
return true;
}
My asssignmet is:
Input three strings into an array of strings. First, use a function to find the length for the end comparisons, then again compare the last two characters separately.
Second, use a string function to take a sub-string of the first three characters for the beginning comparison all at once.
{
string stringarray[3] = {"yankee", "yes", "word"};
for (int x = 0; x < 3; x++)
string substringend1 = stringarray.substr(stringarray.length(stringarray[x]) - 2, stringarray.length(stringarray[x]));
string substringend2 = stringarray.substr(stringarray.length(stringarray[x]) - 1, stringarray.length(stringarray[x]));
string substringstart = stringarray.substr(0, 3);
if (substringend1 == "e" && substringend2 == "s" || substringstart == "yan") {
for (int y = 0; y < 3; y++)
cout << stringarray[y];
}
}
I know Im an idiot and this is a bad question format and whatever but I need help
C++20 makes this very easy:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
std::vector<std::string> in{"yankee", "yes", "word"};
for(const auto& s : in)
{
if(s.starts_with("yan") || s.ends_with("es"))
std::cout << s << '\n';
}
return 0;
}
Live Example: https://godbolt.org/z/6Eq3nnKrf
The hardest part is finding C++20 support in your compiler. Later versions of gcc have it, latest versions of MSVC have it.
Without C++20, you need to find replacements for starts_with() and ends_with(). Starts with is easy and has a good answer here: How do I check if a C++ std::string starts with a certain string, and convert a substring to an int?
Using that answer we can write a pretty simple starts_with() function:
bool starts_with(const std::string& in, const std::string& prefix)
{
return in.rfind(prefix, 0) == 0;
}
We can use that as an example on how to create an ends_with() function too!
bool ends_with(const std::string& in, const std::string& prefix)
{
return in.rfind(prefix) == (in.size() - prefix.size());
}
Then our main code changes only slightly:
int main()
{
std::vector<std::string> in{"yankee", "yes", "word"};
for(const auto& s : in)
{
if(starts_with(s, "yan") || ends_with(s, "es"))
std::cout << s << '\n';
}
return 0;
}
You can use std::compare to compare the start of a string with yan or its end with es:
#include <iostream>
#include <string>
using namespace std;
bool startWithString(string a, string mod)
{
if (a.length() < mod.length()) {return false;}
return 0 == a.compare(0, mod.length(), mod);
}
bool endWithString(string a, string mod)
{
if (a.length() < mod.length()) {return false;}
return 0 == a.compare(a.length()-mod.length(), mod.length(), mod);
}
int main()
{
string str[4] = {"yankee", "yes", "word", "yankes"};
for (int i = 0; i < 4; i++)
{
string cur = str[i];
if (startWithString(cur, "yan") || endWithString(cur, "es")) {cout << cur << endl;}
}
}
Result :
yankee
yes
yankes
Using rfind() also yields similar result:
bool startWithString(string a, string mod)
{
return a.rfind(mod, 0) == 0;
}
bool endWithString(string a, string mod)
{
return a.rfind(mod) == (a.length() - mod.length());
}
As #Chad mentioned, C++20 also support starts_with() and ends_with(), which makes stuff easier.
Task : Create a function that returns true if two strings share the same letter pattern, and false otherwise.
I found a way to solve this task but I think it could be more simple and short. I converted all same letters to a specific char character for 2 strings. Then end of the process checked whether they are same or not. Any ideas for simpler solutions ?
#include <iostream>
#include <string>
using namespace std;
bool LetterPattern(string str1, string str2) {
// Controlling whether they have same size or not
if (str1.length() != str2.length()) {
return false;
}
else {
// Checking for ABC XYZ format type
int counter = 0;
for (int i = 0; i < str1.length()-1; i++) {
for (int k = i+1; k < str1.length(); k++) {
if (str1[i] == str1[k]) {
counter++;
}
}
}
int counter2 = 0;
for (int i = 0; i < str2.length() - 1; i++) {
for (int k = i + 1; k < str2.length(); k++) {
if (str2[i] == str2[k]) {
counter2++;
}
}
}
if (counter == 0 && counter2 == 0) {
return true;
}
// I added the above part because program below couldn't return 1 for completely different letter formats
// like XYZ ABC DEF etc.
//Converting same letters to same chars for str1
for (int i = 0; i < str1.length()-1; i++) {
for (int k = i+1; k < str1.length(); k++) {
if (str1[i] == str1[k]) {
str1[k] = (char)i;
}
}
str1[i] = (char)i;
}
}
//Converting same letters to same chars for str1
for (int i = 0; i < str2.length() - 1; i++) {
for (int k = i + 1; k < str2.length(); k++) {
if (str2[i] == str2[k]) {
str2[k] = (char)i;
}
}
str2[i] = (char)i;
}
if (str1 == str2) { // After converting strings, it checks whether they are same or not
return true;
}
else {
return false;
}
}
int main(){
cout << "Please enter two string variable: ";
string str1, str2;
cin >> str1 >> str2;
cout << "Same Letter Pattern: " << LetterPattern(str1, str2);
system("pause>0");
}
Examples:
str1
str2
result
AABB
CCDD
true
ABAB
CDCD
true
AAFFG
AAFGF
false
asdasd
qweqwe
true
As you want to see if one string is a Caesar cipher of the other, you might do:
bool LetterPatternImpl(const std::string& str1, const std::string& str2) {
if (str1.length() != str2.length()) { return false; }
std::array<std::optional<char>, 256> mapping; // char has limited range,
// else we might use std::map
for (std::size_t i = 0; i != str1.length(); ++i) {
auto index = static_cast<unsigned char>(str1[i]);
if (!mapping[index]) { mapping[index] = str2[i]; }
if (*mapping[index] != str2[i]) { return false; }
}
return true;
}
bool LetterPattern(const std::string& str1, const std::string& str2) {
// Both ways needed
// so ABC <-> ZZZ should return false.
return LetterPatternImpl(str1, str2) && LetterPatternImpl(str2, str1);
}
By 1 iteration on strings create key-value pairs That define corresponding characters.
In the second iteration check whether each character in the first/second string is compatible with the character with equal index in the second/second string. If there is no incompatibility return true, otherwise false.
First, as you did we can compare the size of 2 strings.
If they are equal we continue.
By iterating on 1 of the strings we can fill a map. Keys of the map are characters seen in the first string and its value is the corresponding character in the second string.
By reaching the nth character we check that whether we have a key or the same as this character or not.
If yes: Check the value that is equal to the nth character of the second string.
If no: we add a new key-value to the map. (the key is the nth character of the first string and the value is the nth character of the second string)
1.
After doing this we should do this again for another string. I mean for example if in the first step characters of the first string were keys, In the second step we should replace the string in the way that characters of second string become keys.
If both of them give true the answer is true. Otherwise false.
2.
Rather than replacing strings and repeat the iteration, we can prevent repetitive values to be added to the map.
To understand paragraph 1 and 2 imagine 1 iteration on strings of "ABC" and "ZZZ".
Notice that arrays can be used instead of map.
And, last but not least, an additional solution using "counting".
If we read the requirement, then you are only interested in a boolean result. That means, as soon as we have a 2nd association for a letter in the first string, then the result is false.
Example: If we have an 'a' and in the 2nd string at the same position a 'b', and then in some next position of the first string again an 'a' but then in the same position of the 2nd string a 'c', then we have 2 different associations for the letter a. And that is false.
If there is only one association per letter, then everything is ok.
How to accomplish "association" and "counting". For the "association, we will use an associative container, a std::unordered_map. And, we associate a letter from the first string, with a std::set of the already processed letters (from the 2nd string). The std::sets iinsert function will not add double letters from the secondt string. So, if there is again a 'b' associated with an 'a', that is completly fine.
But if there is a different associated letter, then the std::set will contain 2 elements. That is an indicator for a false result.
In such case, we stop evaluation characters immediately. This leads to a very compact and fast code.
Please see:
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <set>
bool letterPattern(const std::string& s1, const std::string& s2) {
// Here we will store the result of the function
bool result{ s1.length() == s2.length() };
// And here all associations
std::unordered_map<char, std::set<char>> association{};
// Add associations. Stop if result = false
for (size_t index{}; result && index < s1.length(); ++index)
if (const auto& [iter, ok] {association[s1[index]].insert(s2[index])}; ok)
result = association[s1[index]].size() == 1;
return result;
}
// Some driver test code
int main() {
std::vector<std::pair<std::string,std::string>> testData{
{"AABB", "CCDD"},
{"ABAB", "CDCD"},
{"AAFFG", "AAFGF"},
{"asdasd", "qweqwe"}
};
for (const auto& p : testData)
std::cout << std::boolalpha << letterPattern(p.first, p.second) << "\t for: '" << p.first << "' and '" << p.second << "'\n";
return 0;
}
Not sure about better, but a C++17 solution that builds a regular expression based on the first string's letters and matches it against the second:
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <tuple>
#include <regex>
bool match(const std::string &pattern, const std::string &s) {
std::unordered_map<char, int> indexes;
std::ostringstream builder;
int ref = 1;
for (char c : pattern) {
if (auto backref = indexes.find(c); backref != indexes.end()) {
builder << '\\' << backref->second;
} else {
if (ref > 1) {
builder << "(?!";
for (int n = 1; n < ref; n += 1) {
if (n != 1) {
builder << '|';
}
builder << '\\' << n;
}
builder << ')';
}
builder << "(.)";
indexes.emplace(c, ref++);
}
}
// std::cout << builder.str() << '\n';
return std::regex_match(s, std::regex{builder.str()});
}
int main() {
std::tuple<std::string, std::string, bool> tests[] = {
{"AABB", "CCDD", true},
{"ABAB", "CDCD", true},
{"AAFFG", "AAFGF", false},
{"asdasd", "qweqwe", true},
{"abc", "zzz", false}
};
std::cout << std::boolalpha;
for (const auto &[s1, s2, expected] : tests) {
if (match(s1, s2) == expected) {
std::cout << s1 << " => " << s2 << " = " << expected << ": PASS\n";
} else {
std::cout << s1 << " => " << s2 << " = " << (!expected) << ": FAIL\n";
}
}
return 0;
}
A simple (maybe not very efficient) approach:
#include<iostream>
#include<unordered_map>
using namespace std;
int main(void) {
string s1, s2;
unordered_map<string, char> subs;
cout<<"Enter the strings: ";
cin >> s1 >> s2;
if (s1.length() != s2.length())
cout<<"False"<<endl;
else {
for (int i=0; i<s1.length(); ++i) {
string key(1, s2[i]);
subs[key] = s1[i];
}
string s1_2 = "";
for (int i=0; i<s2.length(); ++i) {
string key(1, s2[i]);
s1_2 += subs[key];
}
if (s1 == s1_2)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
return 0;
}
Time Complexity O(n); Space Complexity O(n)
If I understood right and:
AABB - CCDD = true
AAFFG - AAFGF = false
asdasd - qweqwe = true
That's not pattern, it's check if second string is result of encryption by substitution of first. You can do it in simpler way, by attempting to built substitution table. If it fails, i.e. there are more than one association between source and result, the outcome is false.
Simplest case is that we have to check whole string. If we would need to find that if any substring is substitution of pattern contained in second string, that squares the complexity:
#include <string>
#include <vector>
#include <map>
#include <optional>
#include <limits>
bool is_similar (const std::string& s1, const std::string& s2)
{
if(s1.length() != s2.length()) return false;
using TCh = std::decay_t<decltype(s1)>::value_type;
// for non-unicode characters can use an array
//std::optional<TCh> table[ std::numeric_limits<TCh>::max ];
// std::optional used for clarity, in reality may use `TCh`
// and compare with zero char
std::map< TCh, std::optional<TCh>> table;
for (size_t it = 0; it < s1.length(); ++it)
{
if( table[s1[it]].has_value() && table[s1[it]] != s2[it] ) return false;
if( table[s2[it]].has_value() && table[s2[it]] != s1[it] ) return false;
table[s1[it]] = s2[it];
//table[s2[it]] = s1[it]; if symmetric
}
return true;
}
If we find a new character, we will make it equal to the same position as the other string characters. Next time, if we found it again, we will check based on it.
Suppose we have 'aa' and 'cd'.
1st iteration: 'a'='c'
2nd iteration: already 'a'='c'(1st iteration), so we must need 'c' in our 2nd string.
But in our 2nd string, it is 'd'. so simply it will return false.
#include <bits/stdc++.h>
using namespace std;
// if you want to use map
bool LetterPattern_with_map(string str1,string str2)
{
if(str1.size()!=str2.size()) return false;
map<char,char> mp;
for(int i=0;i<str1.size();i++)
{
if(!mp[str1[i]]) { mp[str1[i]]=str2[i]; continue; }
if(mp[str1[i]]!=str2[i]) return false;
}
return true;
}
// if you want to use array instead of map
bool LetterPattern_with_array(string str1,string str2)
{
if(str1.size()!=str2.size()) return false;
int check[128]={0};
for(int i=0;i<str1.size();i++)
{
if(!check[str1[i]-'A'+1]) { check[str1[i]-'A'+1]=(int)(str2[i]-'A'+1); continue; }
if(check[str1[i]-'A'+1]!=(int)(str2[i]-'A'+1)) return false;
}
return true;
}
int main()
{
cout << "Please enter two string variable: ";
string str1, str2;
cin >> str1 >> str2;
cout << "Same Letter Pattern: " << LetterPattern_with_map(str1, str2)<<'\n';
cout << "Same Letter Pattern: " << LetterPattern_with_array(str1, str2);
}
Is there any inbuilt function available to get strings between two delimiter string in C++?
Input string
(23567)=(58765)+(67888)+(65678)
Expected Output
23567
58765
67888
65678
include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>
std::vector<std::string> tokenize(const std::string& input)
{
std::vector<std::string> result;
std::istringstream stream(input);
std::string thingie; // please choose a better name, my inspiration is absent today
while(std::getline(stream, thingie, '('))
{
if(std::getline(stream, thingie, ')'))
result.push_back(thingie);
else
throw std::runtime_error("expected \')\' to match \'(\'.");
}
return result;
}
void rtc()
{
ifstream myfile(test.txt);
if(myfile.is_open())
while (!myfile.eof())
{
getline(myfile,line);
auto tokens = tokenize(line);
for(auto&& item : tokens)
std::cout << item << '\n';
}
Error C4430 missing type specifier int assumed note:c++ does not support default int
ErrorC2440initializing cannot convertfrom std::vector<_ty>to int
Error C2059syntac error empty declaration
Error C2143syntax error missing;before&&
Error C2059syntax error:')'
Use std::getline:
#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>
std::vector<std::string> tokenize(const std::string& input)
{
std::vector<std::string> result;
std::istringstream stream(input);
std::string thingie; // please choose a better name, my inspiration is absent today
while(std::getline(stream, thingie, '('))
{
if(std::getline(stream, thingie, ')'))
result.push_back(thingie);
else
throw std::runtime_error("expected \')\' to match \'(\'.");
}
return result;
}
int main()
{
std::string test = "(23567)=(58765)+(67888)+(65678)";
auto tokens = tokenize(test);
for(auto&& item : tokens)
std::cout << item << '\n';
}
Live example here.
For those not entirely convinced by the awesome robustness of this solution, I specialized this for double inputs between the parentheses, and used boost::lexical_cast to verify the input:
#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>
#include <boost/lexical_cast.hpp>
std::vector<double> tokenize(const std::string& input)
{
std::vector<double> result;
std::istringstream stream(input);
std::string thingie; // please choose a better name, my inspiration is absent today
while(std::getline(stream, thingie, '('))
{
if(std::getline(stream, thingie, ')'))
{
try
{
result.push_back(boost::lexical_cast<double>(thingie));
}
catch(...)
{
throw std::runtime_error("This wasn't just a number, was it?");
}
}
else
throw std::runtime_error("expected \')\' to match \'(\'.");
}
return result;
}
int main()
{
std::string test = "(23567)=(58765)+(67888)+(65678)";
auto tokens = tokenize(test);
for(auto&& item : tokens)
std::cout << item << '\n';
test = "(2h567)=(58765)+(67888)+(65678)";
tokens = tokenize(test);
}
Live example here. Now go cry about how bad strtok really is, or how bad/unportable the general <regex> implementations are currently. Also, for those who doubt boost::lexical_cast performance-wise, please see the results for yourself.
strpbrk can be used to find the start of each token
or strcspn can be used to count the characters until the next token
then strspn can be used to find the length of each token.
const char tokenChars[] = "0123456789";
char token = input; // say input is "(23567)=(58765)+(67888)+(65678)"
while( 0 != (token = strpbrk( token, tokenChars )) ) // find token
{
size_t tokenLen = strspn( token, token_chars ); // find length of token
// print out tokenLen characters of token here!
token+= tokenLen; // go to end of token
}
http://www.cplusplus.com/reference/cstring/strspn/
http://www.cplusplus.com/reference/cstring/strcspn/
http://www.cplusplus.com/reference/cstring/strpbrk/
Here's the answer if you wanna use pointers:
char test[32] = "(23567)=(58765)+(67888)+(65678)";
char *output = NULL;
char *pos = (char *)test;
int length = 0;
while (*pos != '\0') {
if(*pos == '(' || *pos == ')' || *pos == '+' || *pos == '=') {
*pos = '\0';
if (length > 0) {
output = new char[length + 1];
strncpy_s(output, length + 1, pos - length, length + 1);
length = 0;
cout << output << endl;
delete [] output;
output = NULL;
}
} else {
length++;
}
pos++;
}
While some of the commentators may hate it I like this:
for (p = std::strtok(input, "+"); p != NULL; p = std::strtok(NULL, "+"))
{
// do more stuff
}
This won't work off the bat - the delimiters need expanding - it demonstrates the ease of use.
const char input[] = "(2av67q)=(ble ble)+(67888)+(qpa)";
int s = 0;
for(int i = 0; input[i]; i++)
{
if ( input[i] == ')' )
{
cout << endl;
s = 0;
}
else if ( input[i] == '(' )
{
s = 1;
continue;
}
else
{
if ( s == 1 )
{
cout << input[i];
}
}
}
result:
2av67q
ble ble
67888
qpa
Here is a solution using a regular expression:
std::vector<std::string> get_numbers(std::string const& s)
{
static std::regex regex(R"(^\((\d+)\)=\((\d+)\)(?:\+\((\d+)\))+$)",
std::regex_constants::ECMAScript
| std::regex_constants::optimize);
std::vector<std::string> results;
std::sregex_iterator matches(s.cbegin(), s.cend(), regex);
for (auto first = matches->cbegin(), last = matches->cend();
last != first;
++first)
{
results.push_back(first->str());
}
return results;
}
#include <iostream>
#include <vector>
using namespace std;
void RevStr (char *str)
{
if(*str !=0)
{
vector<char> v1;
while((*str != ' ')&&(*str !=0))
v1.push_back(*str++);
// trying to not add space in the last word of string
if(*str !=0)
{
v1.push_back(' ');
str++;
}
RevStr(str);
cout<<*str;
}
}
int main()
{
RevStr("hello world!");
cout<<endl;
}
I want to change the order of words in the string for example " how are you" => "you are how"
I am having some problem, its not printing correctly (print only w), please help me and tell me what i did wrong. However i know that I should not call "cout<<*str;
" since i am inserting the "array of char" in stack (recurssion) but i dont know what i need to do.
C++ makes it simple:
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
std::string reverse(std::string const& text)
{
std::stringstream inStream(text);
std::stringstream outStream;
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(inStream), std::istream_iterator<std::string>(), std::back_inserter(words));
std::copy(words.rbegin(), words.rend(), std::ostream_iterator<std::string>(outStream, " "));
return outStream.str();
}
int main()
{
std::cout << reverse("Hello World") << "\n";
}
A common approach to do this is to reverse the entire string first, then for each word, reverse the letters in the word. So no recursion is necessary. You might find it easier to give this a try (yes, I know this isn't exactly an answer to your question :) ).
Use cout << str, not cout << *str to print a string. There's an operator<< overload for char *. But maybe that's not what you're trying to do; I can't quite follow your logic, in any event.
You're losing the "hello" part.
The algorithm you seem to go for does this:
each call to RevStr isolates the first word in the string it is passed as a parameter
calls RevStr with the remaining of the string
prints the word it isolated at step 1 as the stack unwinds
Basically, you should be printing the v1 data.
I would strongly advise making using some of the functionality exposed via std::string as a place to start.
One way you might do this would look like this:
std::string ReverseString(std::string s)
{
std::stack<std::string > stack;
std::string tmpstr = "";
std::string newstr = "";
size_t strsize = s.size();
size_t pos = 0; size_t tmppos = 0;
size_t i = 0; size_t stacksize = 0;
while( pos < strsize )
{
tmppos = s.find(" ", pos, 1); // starting as pos, look for " "
if (tmppos == std::string::npos) // std::string::npos => reached end
{
tmppos = strsize; // don't forget the last item.
}
tmpstr = s.substr(pos, tmppos-pos); // split the string.
stack.push(tmpstr); // push said string onto the stack
pos = tmppos+1;
}
stacksize = stack.size();
for ( i = 0; i < stacksize; i++ )
{
tmpstr = stack.top(); // grab string from top of the stack
stack.pop(); // stacks being LIFO, we're getting
if ( i != 0 ) // everything backwards.
{
newstr.append(" "); // add preceding whitespace.
}
newstr.append(tmpstr); // append word.
}
return newstr;
}
It's by no means the best or fastest way to achieve this; there are many other ways you could do it (Jerry Coffin mentions using std::vector with an iterator, for example), but as you have the power of C++ there, to me it would make sense to use it.
I've done it this way so you could use a different delimiter if you wanted to.
In case you're interested, you can now use this with:
int main(int argc, char** argv)
{
std::string s = "In Soviet Russia String Format You";
std::string t = ReverseString(s);
std::cout << t << std::endl;
}
given that its a char*, this reverses it inplace (ie, doesn't require more memory proportional to the incoming 'str'). This avoids converting it to a std::string ( not that its a bad idea to, just because it's a char* to start with.)
void reverse_words(char* str)
{
char* last = strlen(str) + str;
char *s, *e;
std::reverse(str,last);
for(s=e=str; e != last; e++)
{
if(*e == ' ')
{
std::reverse(s,e);
s = e+1;
}
}
std::reverse(s,e);
}
void Reverse(const string& text)
{
list<string> words;
string temp;
for ( auto cur = text.begin(); cur != text.end(); ++cur)
{
if (*cur == ' ')
{
words.push_front(temp);
temp.clear();
}
else
{
temp += *cur;
}
}
if (! temp.empty())
{
words.push_front(temp);
}
for_each(words.begin(), words.end(), [](const string& word) { cout << word << " "; });
cout << endl;
}
void swap(char* c1, char* c2) {
char tmp = *c1;
*c1 = *c2;
*c2 = tmp;
}
void reverse(char* s, char* e) {
if (s == NULL || e == NULL)
return;
while(s < e)
swap(s++, e--);
}
void reverse_words(char* line) {
if (line == NULL)
return;
reverse(line, line+strlen(line)-1);
char *s = line;
char *e;
while (*s != '\0') {
e = s;
while (*e != ' ' && *e != '\0') ++e;
--e;
reverse(s,e);
s = e+2;
}
}