splitting string into vector c++ - c++

I wrote a simple code to split the string from each '/' and store into vector.
My string may start with / or not and definetelly will end with /. For example if my string is:
string="/home/desktop/test/"
I want to <"/","home","desktop","test"> and another example
string="../folder1/folder2/../pic.pdf/"
I want to store <"..","folder1","folder2","..","pic.pdf"
However, my code gives me <" ","home","desktop","test"," "> for the first example and
<"..","folder1","folder2","..","pic.pdf"," "> for the second example
Is there anyone to help me ?
Here is my code for this :
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string strLine("/cd/desktop/../test/");
string strTempString;
vector<int> splitIndices;
vector<string> splitLine;
int nCharIndex = 0;
int nLineSize = strLine.size();
// find indices
for(int i = 0; i < nLineSize; i++)
{
if(strLine[i] == '/')
splitIndices.push_back(i);
}
splitIndices.push_back(nLineSize); // end index
// fill split lines
for(int i = 0; i < (int)splitIndices.size(); i++)
{
strTempString = strLine.substr(nCharIndex, (splitIndices[i] - nCharIndex));
splitLine.push_back(strTempString);
cout << strTempString << endl;
nCharIndex = splitIndices[i] + 1;
}
}

The C++ String Toolkit Library (Strtk) has the following solution to your problem:
http://www.codeproject.com/Articles/23198/C-String-Toolkit-StrTk-Tokenizer

Some things to do in the code that should fix this, there might be a better and more elegant solution for this.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string strLine("/cd/desktop/../test/");
string strTempString;
vector<int> splitIndices;
vector<string> splitLine;
int nCharIndex = 0;
int nLineSize = strLine.size();
// find indices
if(nLineSize!=0 && strLine[0]=='/')
{
splitLine.push_back(strLine.substr(0,1));
nCharIndex++;
}
for(int i = 1; i < nLineSize; i++)
{
if(strLine[i] == '/')
splitIndices.push_back(i);
}
// fill split lines
for(int i = 0; i <int(splitIndices.size()); i++)
{
strTempString = strLine.substr(nCharIndex, (splitIndices[i] - nCharIndex));
splitLine.push_back(strTempString);
nCharIndex = splitIndices[i] + 1;
}
}
Edit :
Cleaned the code a bit, you can remove the adding the last index part now.
Edit 2:
A possibly more elegant looking solution for this might be by removing the ncharcounter and using your splitting index for that. You can store the first value as '-1' if the first character is not ('/') or as ('0') if it is.
string strLine("/cd/desktop/../test/");
string strTempString;
vector<int> splitIndices;
vector<string> splitLine;
int nLineSize = strLine.size();
// find indices
splitIndices.push_back(-1);
if(nLineSize!=0 && strLine[0]=='/')
{
splitLine.push_back(strLine.substr(0,1));
splitIndices[0]=0;
}
for(int i = 1; i < nLineSize; i++)
{
if(strLine[i] == '/')
splitIndices.push_back(i);
}
// fill split lines
for(int i = 1; i <int(splitIndices.size()); i++)
{
strTempString = strLine.substr(splitIndices[i-1]+1, (splitIndices[i] - (splitIndices[i-1]+1) ));
splitLine.push_back(strTempString);
}

Following change may help:
if (!strLine.empty() && strLine.back() != '/') {
splitIndices.push_back(nLineSize); // end index
}
// fill split lines
for(int i = 0; i < (int)splitIndices.size(); i++)
{
if (splitIndices[i] == 0) {
splitLine.push_back("/");
} else {
strTempString = strLine.substr(nCharIndex, (splitIndices[i] - nCharIndex));
splitLine.push_back(strTempString);
}
nCharIndex = splitIndices[i] + 1;
}

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
std::string s1 = "/home/desktop/test/";
std::string s2 = "../folder1/folder2/../pic.pdf/";
std::vector<std::string> v1;
std::istringstream is1( s1 );
std::string t;
while ( std::getline( is1, t, '/' ) )
{
if ( t.empty() ) v1.push_back( "/" );
else v1.push_back( t );
}
for ( const std::string &t : v1 ) std::cout << t << std::endl;
std::cout << std::endl;
std::vector<std::string> v2;
std::istringstream is2( s2 );
while ( std::getline( is2, t, '/' ) )
{
if ( t.empty() ) v2.push_back( "/" );
else v2.push_back( t );
}
for ( const std::string &t : v2 ) std::cout << t << std::endl;
}

Related

Remove adjacent Duplicates from a String which have count greater than or equal to burst Length

Given a string with repeating characters and a burst length, output the string such that the count of the same adjacent characters in the string is less than the burst length.
Input : abbccccdd, burstLen = 3
Correct Output : abbdd
My Output: abbd
Input : abbcccdeaffff, burstLen = 3
Correct Output: abbdea
My Output: abbea
//Radhe krishna ki jytoi alokik
#include <bits/stdc++.h>
using namespace std;
string solve(string s, int burstLen)
{
stack<pair<char, int>> ms;
for (int i = 0; i < s.size(); i++)
{
if (!ms.empty() && ms.top().first == s[i])
{
int count = ms.top().second;
ms.push({s[i], count + 1});
}
else
{
if(ms.empty() == true || ms.top().first != s[i])
{
if(!ms.empty() && ms.top().second >= burstLen)
{
int count = ms.top().second;
while(!ms.empty() && count--)
ms.pop();
//(UPDATE)
ms.push({s[i], 1});
}
else
ms.push({s[i], 1});
}
}
}
if(!ms.empty() and ms.top().second >= burstLen)
{
int count = ms.top().second;
while(!ms.empty() && count--)
ms.pop();
}
string ans = "";
while (!ms.empty())
{
ans += ms.top().first;
ms.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
int main()
{
string s;
int burstLen;
cin >> s;
cin >> burstLen;
cout << solve(s, burstLen) << "\n";
}
It would be better at least to use the container adapter std::queue instead of std::stack because there would not be a need to call the algorithm std::reverse.
Moreover if items of the stack contain the second data member that stores frequencies then you could just increase this data member for repeated characters instead of placing each repeated character in the stack.
For example this code snippet in your program
if (!ms.empty() && ms.top().first == s[i])
{
int count = ms.top().second;
ms.push({s[i], count + 1});
}
makes the function definition too complicated and unclear because the same character is pushed on the stack with different frequencies.
Nevertheless if you want to use the container adapter std::stack the function definition could look simpler. You are not using features of the class std::string.
Here is a demonstrative program that shows how the function could be written using your approach with std::stack.
#include <iostream>
#include <string>
#include <utility>
#include <stack>
#include <iterator>
#include <algorithm>
std::string solve( const std::string &s, size_t burstLen )
{
std::stack<std::pair<char, size_t>> stack;
for ( const auto &c : s )
{
if ( stack.empty() || stack.top().first != c )
{
stack.push( { c, 1 } );
}
else
{
++stack.top().second;
}
}
std::string ans;
while ( !stack.empty() )
{
if ( stack.top().second < burstLen )
{
ans.append( stack.top().second, stack.top().first );
}
stack.pop();
}
std::reverse( std::begin( ans ), std::end( ans ) );
return ans;
}
int main()
{
std::cout << solve( "abbccccdd", 3 ) << '\n';
std::cout << solve( "abbcccdeaffff", 3 ) << '\n';
}
The program output is
abbdd
abbdea
It is interesting to use the stack when after removing a sequence of characters that is not less than the burst length you get from the left and right side sub-sequences anew sequence that again is not less than burst length and you need also to remove it.
In this case you can use two stacks.
Here is a demonstrative program.
#include <iostream>
#include <string>
#include <utility>
#include <stack>
#include <iterator>
#include <algorithm>
std::string solve( const std::string &s, size_t burstLen )
{
std::stack<std::pair<char, size_t>> stack_in;
for ( const auto &c : s )
{
if ( stack_in.empty() || stack_in.top().first != c )
{
stack_in.push( { c, 1 } );
}
else
{
++stack_in.top().second;
}
}
std::stack<std::pair<char, size_t>> stack_out;
while ( !stack_in.empty() )
{
if ( !stack_out.empty() && stack_out.top().first == stack_in.top().first )
{
if ( stack_out.top().second + stack_in.top().second < burstLen )
{
stack_out.top().second += stack_in.top().second;
}
else
{
stack_out.pop();
}
}
else if ( stack_in.top().second < burstLen )
{
stack_out.push( stack_in.top() );
}
stack_in.pop();
}
std::string ans;
while ( !stack_out.empty() )
{
ans.append( stack_out.top().second, stack_out.top().first );
stack_out.pop();
}
return ans;
}
int main()
{
std::cout << solve( "abbccccdd", 3 ) << '\n';
std::cout << solve( "abbcccdeaffff", 3 ) << '\n';
std::cout << solve( "aabcddeeedccbaa", 3 );
}
The program output is
abbdd
abbdea
aabbaa
I gave it a try but it looks complicated so I suggest making a simpler function using a few functions from the standard library.
Example:
#include <algorithm>
#include <iostream>
#include <initializer_list>
#include <iterator>
std::string solve(const std::string& in, size_t burstlen) {
std::string retval;
for(std::string::const_iterator begin = in.cbegin(), bend;
begin != in.end();
begin = bend)
{
// find the first char not equal to the current char
bend = std::find_if_not(std::next(begin), in.end(),
[curr=*begin](char ch){ return ch==curr; });
if(std::distance(begin, bend) < burstlen) {
// length ok, append it
retval.append(begin, bend);
}
}
return retval;
}
int main() {
std::initializer_list<std::string> tests{
"abbccccdd", "abbcccdeaffff"};
for(auto test : tests) std::cout << solve(test, 3) << '\n';
}
Output:
abbdd
abbdea
My Approach to the Solution :
Create a Stack of pair which consists of character and character count
If the Stack is empty or the top element of the stack is not equal to the current element in the string
Case 1: if the frequency of the top element of the stack is greater than or equal to k, store it in a variable say count, Pop the element of Stack count times.
Case 2: if the Stack is Empty, then simply push the element in stack with frequency 1.
Upon Traversing the complete string, if the top element of the stack is having a frequency greater than bursten, start removing elements from the stack (count) number of times.
Now, we have leftout elements in the stack, Start popping them and store them in a string and reverse the string to preserve the order.
Return the new string.
UPDATE : SOLVED. Missing one line in this condition if(ms.empty() == true || ms.top().first != s[i]) After popping the elements, We also have to insert the present element with character frequency 1.
#include<iostream>
#include<stack>
using namespace std;
string solve(string s, int burstLen)
{
stack<pair<char, int>> ms;
for (int i = 0; i < s.size(); i++)
{
if (!ms.empty() && ms.top().first == s[i])
{
int count = ms.top().second;
ms.push({s[i], count + 1});
}
else
{
if(ms.empty() == true || ms.top().first != s[i])
{
if(!ms.empty() && ms.top().second >= burstLen)
{
int count = ms.top().second;
while(!ms.empty() && count--)
ms.pop();
ms.push({s[i], 1});
}
else
ms.push({s[i], 1});
}
}
}
if(!ms.empty() and ms.top().second >= burstLen)
{
int count = ms.top().second;
while(!ms.empty() && count--)
ms.pop();
}
string ans = "";
while (!ms.empty())
{
ans += ms.top().first;
ms.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
int main()
{
int t;
cin >> t;
while(t--)
{
string s;
int burstLen;
cin >> s >>burstLen;
cout << solve(s, burstLen) << "\n";
}
}
private void solve(){
System.out.printf("%s\n", solve("abbccccdd", 3));
System.out.printf("%s\n", solve("abbcccdeaffff", 3));
}
private LinkedList<Node> addToQueue(String S){
int N = S.length();
LinkedList<Node> queue = new LinkedList<>();
queue.addFirst(new Node(S.charAt(0), 1));
for(int i=1;i<N;i++){
if(!queue.isEmpty() && queue.getFirst().val==S.charAt(i)) {
queue.getFirst().count +=1;
} else {
queue.addFirst(new Node(S.charAt(i), 1));
}
}
return queue;
}
private String solve(String S, int K){
if(S==null || S.length()==0) return "";
int N = S.length();
LinkedList<Node> queue = addToQueue(S);
StringBuilder buf = new StringBuilder();
while(!queue.isEmpty()) {
Node node = queue.removeLast();
int count = node.count;
if(count>=K) continue;
if(isSame(queue, buf)){
while(isSame(queue, buf)) {
count += queue.getLast().count;
queue.removeLast();
}
if(count>=K) buf.deleteCharAt(buf.length()-1);
else {
while(count-->0){
buf.append(node.val);
}
}
} else {
if(count>=K) continue;
while(count-->0){
buf.append(node.val);
}
}
}
return buf.toString();
}
private boolean isSame(LinkedList<Node> queue, StringBuilder buf){
if(queue.isEmpty() || buf.length()==0) return false;
return queue.getLast().val == buf.charAt(buf.length()-1);
}
class Node {
char val;
int count;
public Node(char c, int count){
this.val = c;
this.count = count;
}
}

How to make sure that two strings only have certain alphabets in c++

Aim is to make sure that the user entered input for string 1 and string 2 contains only characters A,T,G or C in any order. If either string contains another other character then error should be displayed. Example:
Input contains error
Error in String #1: aacgttcOgMa
Error in String #2: ggataccaSat
This is my attempt at LCS.cpp file code:
#include "LCS.h"
#include <string>
using namespace std;
bool validate(string strX, string strY)
{
string x = strX;
string y = strY;
char searchItem = 'A';
char searchItem = 'C';
char searchItem = 'G';
char searchItem = 'T';
int numOfChar = 0;
int m = strX.length();
int n = strY.length();
for (int i = 0; i < m; i++)
{
if (x[i] == searchItem)
{
numOfChar++;
}
for (int i = 0; i < n; i++)
{
if (y[i] == searchItem)
{
numOfChar++;
}
}
}
This is my LCS.h file code:
#pragma once
#ifndef LCS_H
#define LCS_H
#include <string>
using namespace std;
bool validate(string strX, string strY);
#endif
And my driver file "Driver6.cpp" has this code:
#include "LCS.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strX, strY;
cout << "String #1: ";
cin >> strX;
cout << "String #2: ";
cin >> strY;
//validate the input two strings
if (validate(strX, strY) == false)
{
return 0;
}
int m = strX.length();
int n = strY.length();
}
Didn't really want to do this but it seems like the best bet rather than going round the houses in the comments:
#include <string>
#include <iostream>
bool validate( const std::string & s ) {
for ( auto c : s ) {
if ( c != 'A' && c != 'T' && c != 'C' && c != 'G' ) {
return false;
}
}
return true;
}
int main() {
std::string s1 = "ATGCCCG";
std::string s2 = "ATGfooCCCG";
if ( validate( s1 ) ) {
std::cout << "s1 is valid\n";
}
else {
std::cout << "s1 is not valid\n";
}
if ( validate( s2 ) ) {
std::cout << "s2 is valid\n";
}
else {
std::cout << "s2 is not valid\n";
}
}
Another technique:
bool validate(const std::string& s)
{
const static std::string valid_letters("ATCGatcg");
for (auto c: s)
{
std::string::size_type position = valid_letters.find_first_of(c);
if (position == std::string::npos)
{
return false;
}
}
return true;
}
The above code searches a container of valid letters.

converting strings to integers by using "stringstream "

I am trying to convert strings of data to integers, (to use it for some calculations ) by using stringstream , but it fails when there is a space.
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
if(stream >> ch) {
values.push_back(n);
}
else {
values.push_back(n);
}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
input : 1,182,08 51 15 --> output : 1 182 8 1 5
there are some digits lost after spaces.
so, what can I do to avoid it?
Complete working code based on seccpur's answer. Visual Studio 2017 Community:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
#define BUFSZ 100 // Set max size of the numbers as a single string
int convertToIntegers(char *s, vector<int> &values);
int main()
{
int count;
int i;
char data[BUFSZ];
vector<int> values;
strcpy_s(data, "1,182,08 51 15");
count = convertToIntegers(data, values);
// for (auto val : values) // Show the result
// cout << val << '\n';
// *** OR ***
for (i = 0; i < count; i++)
cout << values[i] << '\n';
}
//////////////////////////////////////
// Convert a C string to integers
//
int convertToIntegers(char *s, vector<int> &values)
{
vector<string> numbers;
char *next_token;
char* ptr = strtok_s(s, " -.,;", &next_token);
while (ptr)
{
string str(ptr);
numbers.push_back(str);
ptr = strtok_s(NULL, " -.,;", &next_token); // Next number
}
//
// Convert the resulting strings to integers
//
for (auto str : numbers)
values.push_back(stoi(str));
return (int)values.size();
}
If you know you have exactly one character as a separator, either a space, either a comma, the following code will work:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
char c = stream.get();
//if(stream >> ch) {
// values.push_back(n);
//}
//else {
values.push_back(n);
//}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
You are using multiple delimiters in the input ( like whitespace : , ; -) which complicates the matter. Here's a possible snippet using std::strtok:
//Enter a line
string line;
getline(cin, line);
// Convert string to char* so that std::strtok could be used later
char *cstr = new char[line.length() + 1];
std::strcpy(cstr, line.c_str());
vector<string> words;
// split line into multiple strings using multiple delimiters
char* ptr = std::strtok(cstr, " -.,;");
while (ptr)
{
string str(ptr);
words.push_back(str);
ptr = strtok(NULL, " -.,;");
}
delete[] cstr;
// Convert string to int
vector<int> values;
for (auto str : words){
values.push_back(std::stoi(str));
}
// Print the values
for (auto val : values){
cout << val << '\n';
}

How to insert an integer with leading zeros into a std::string?

In a C++14 program, I am given a string like
std::string s = "MyFile####.mp4";
and an integer 0 to a few hundred. (It'll never be a thousand or more, but four digits just in case.) I want to replace the "####" with the integer value, with leading zeros as needed to match the number of '#' characters. What is the slick C++11/14 way to modify s or produce a new string like that?
Normally I would use char* strings and snprintf(), strchr() to find the "#", but figure I should get with modern times and use std::string more often, but know only the simplest uses of it.
What is the slick C++11/14 way to modify s or produce a new string like that?
I don't know if it's slick enough but I propose the use of std::transform(), a lambda function and reverse iterators.
Something like
#include <string>
#include <iostream>
#include <algorithm>
int main ()
{
std::string str { "MyFile####.mp4" };
int num { 742 };
std::transform(str.rbegin(), str.rend(), str.rbegin(),
[&](auto ch)
{
if ( '#' == ch )
{
ch = "0123456789"[num % 10]; // or '0' + num % 10;
num /= 10;
}
return ch;
} // end of lambda function passed in as a parameter
); // end of std::transform()
std::cout << str << std::endl; // print MyFile0742.mp4
}
I would use regex since you're using C++14:
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
int main()
{
std::string text = "Myfile####.mp4";
std::regex re("####");
int num = 252;
//convert int to string and add appropriate number of 0's
std::string nu = std::to_string(num);
while(nu.length() < 4) {
nu = "0" + nu;
}
//let regex_replace do it's work
std::regex_replace(std::ostreambuf_iterator<char>(std::cout),
text.begin(), text.end(), re, nu);
std::cout << std::endl;
return 0;
}
WHy not use std::stringstream and than convert it to string.
std::string inputNumber (std::string s, int n) {
std::stringstream sstream;
bool numberIsSet = false;
for (int i = 0; i < s; ++i) {
if (s[i] == '#' && numberIsSet == true)
continue;
else if (s[i] == '#' && numberIsSet == false) {
sstream << setfill('0') << setw(5) << n;
numberIsSet = true;
} else
sstream << s[i];
}
return sstream.str();
}
I would probably use something like this
#include <iostream>
using namespace std;
int main()
{
int SomeNumber = 42;
std:string num = std::to_string(SomeNumber);
string padding = "";
while(padding.length()+num.length()<4){
padding += "0";
}
string result = "MyFile"+padding+num+".mp4";
cout << result << endl;
return 0;
}
Mine got out of control while I was playing with it, heh.
Pass it patterns on its command line, like:
./cpp-string-fill file########.jpg '####' test###this### and#this
#include <string>
#include <iostream>
#include <sstream>
std::string fill_pattern(std::string p, int num) {
size_t start_i, end_i;
for(
start_i = p.find_first_of('#'), end_i = start_i;
end_i < p.length() && p[end_i] == '#';
++end_i
) {
// Nothing special here.
}
if(end_i <= p.length()) {
std::ostringstream os;
os << num;
const std::string &ns = os.str();
size_t n_i = ns.length();
while(end_i > start_i && n_i > 0) {
end_i--;
n_i--;
p[end_i] = ns[n_i];
}
while(end_i > start_i) {
end_i--;
p[end_i] = '0';
}
}
return p;
}
int main(int argc, char *argv[]) {
if(argc<2) {
exit(1);
}
for(int i = 1; i < argc; i++) {
std::cout << fill_pattern(argv[i], 1283) << std::endl;
}
return 0;
}
I would probably do something like this:
using namespace std;
#include <iostream>
#include <string>
int main()
{
int SomeNumber = 42;
string num = std::to_string(SomeNumber);
string guide = "myfile####.mp3";
int start = static_cast<int>(guide.find_first_of("#"));
int end = static_cast<int>(guide.find_last_of("#"));
int used = 1;
int place = end;
char padding = '0';
while(place >= start){
if(used>num.length()){
guide.begin()[place]=padding;
}else{
guide.begin()[place]=num[num.length()-used];
}
place--;
used++;
}
cout << guide << endl;
return 0;
}

Taking Each Individual Word From a String in C++

I am writing a method in C++ which will take a string of 2 or more words and output each individual word of the string separated by a second or so, using the sleep() method. I am trying to do this using a for loop and substrings. I am unsure also of the regexs which should be used, and how they should be used, to achieve the desired output.
I have reviewed this and this and find my question differs since I am trying to do this in a loop, and not store the individual substrings.
Input:
"This is an example"
Desired output:
"This " (pause) "is " (pause) "an " (pause) "example."
Use std::stringstream, no regular expressions required:
#include <iostream>
#include <sstream>
using namespace std;
int main() {
stringstream ss("This is a test");
string s;
while (ss >> s) {
cout << s << endl;
}
return 0;
}
Also, see How do I tokenize a string in C++?
Here are a pair of implementations that don't involve creating any extraneous buffers.
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp> //for boost::copy
#include <chrono>
#include <iostream>
#include <string>
#include <experimental/string_view> //in clang or gcc; or use boost::string_ref in boost 1.53 or later; or use boost::iterator_range<char*> in earlier version of boost
#include <thread>
void method_one(std::experimental::string_view sv)
{
for(auto b = sv.begin(), e = sv.end(), space = std::find(b, e, ' ')
; b < e
; b = space + 1, space = std::find(space + 1, e, ' '))
{
std::copy(b, space, std::ostreambuf_iterator<char>(std::cout));
std::cout << " (pause) "; //note that this will spit out an extra pause the last time through
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void method_two(std::experimental::string_view sv)
{
boost::copy(
sv | boost::adaptors::filtered([](const char c) -> bool
{
if(c == ' ')
{
std::cout << " (pause) "; //note that this spits out exactly one pause per space character
std::this_thread::sleep_for(std::chrono::seconds(1));
return false;
}
return true;
})
, std::ostreambuf_iterator<char>(std::cout)
);
}
int main() {
const std::string s{"This is a string"};
method_one(s);
std::cout << std::endl;
method_two(s);
std::cout << std::endl;
return 0;
}
Live on coliru, if you're into that.
you can implement your own method:
//StrParse.h
#pragma once
#include <iostream>
static counter = 0;
char* strPar(char* pTxt, char c)
{
int lenAll = strlen(pTxt);
bool strBeg = false;
int nWords = 0;
for(int i(0); i < lenAll; i++)
{
while(pTxt[i] != c)
{
strBeg = true;
i++;
}
if(strBeg)
{
nWords++;
strBeg = false;
}
}
int* pLens = new int[nWords];
int j = 0;
int len = 0;
for(i = 0; i < lenAll; i++)
{
while(pTxt[i] != c)
{
strBeg = true;
i++;
len++;
}
if(strBeg)
{
pLens[j] = len;
j++;
strBeg = false;
len = 0;
}
}
char** pStr = new char*[nWords + 1];
for(i = 0; i < nWords; i++)
pStr[i] = new char[pLens[i] + 1];
int k = 0, l = 0;
for(i = 0; i < lenAll; i++)
{
while(pTxt[i] != c)
{
strBeg = true;
pStr[k][l] = pTxt[i];
l++;
i++;
}
if(strBeg)
{
pStr[k][l] = '\0';
k++;
l = 0;
strBeg = false;
}
}
counter++;
if(counter <= nWords)
return pStr[counter - 1];
else
return NULL;
}
//main.cpp
#include "StrParse.h"
void main()
{
char* pTxt = " -CPlusPlus -programming -is -a - superb thing ";
char* pStr1 = NULL;
int i = 1;
char sep;
std::cout << "Separator: ";
sep = std::cin.get();
std::cin.sync();
while(pStr1 = strPar(pTxt, sep))
{
std::cout << "String " << i << ": " << pStr1 << std::endl;
delete pStr1;
i++;
}
std::cout << std::endl;
}