Program gets "Expression: string subscript out of range" - c++

#include <iostream>
#include <string>
using namespace std;
string Latin(string words)
{
string strWord, strSentence = "";
int length = 0, index = 0;
while (words[index] != '\0')
{
if(words.find(' ', index) != -1)
{
length = words.find(' ', index);
length -= index;
strWord = words.substr(index,length);
strWord.insert(length, "ay");
strWord.insert(length, 1, words[index]);
strWord.erase(0,1);
index += length +1;
}
else
{
strWord = words.substr(index);
length = strWord.length();
strWord.insert(length, "ay");
strWord.insert(length,1,words[index]);
strWord.erase(0,1);
index = words.length();
}
strSentence += (strWord + " ");
}
return strSentence;
}
int main()
{
string str;
getline(cin,str);
str = Latin(str);
cout<<str<<endl;
return 0;
}
I get this error that says
I have no clue what to do. As I am new to this, this is a program that is suppose to ask for user input of a length of words and translate them into pig Latin. Any help would be greatly appreciated.

Unless I really wanted to make my own life difficult, I'd do this quite a bit differently. First, I'd use a std::stringstream to break the input string into words to process. Then, I'd use std::rotate to move the first character of the string to the end. Finally, I'd wrap that all in std::transform to manage applying the function to each word in succession.
std::string line;
std::getline(std::cin, line);
std::stringstream buffer(line);
std::stringstream result;
std::transform(std::istream_iterator<std::string>(buffer),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(result, " "),
[](std::string s) {
std::rotate(s.begin(), s.begin() + 1, s.end());
s += "ay";
return s;
});
Of course, this doesn't know the special rules for things like words that start with vowels or letter pairs like sh or ch, but it looks like that's outside the scope of the task at hand.
For more on std::rotate, I recommend watching some of Sean Parent's videos.

Related

Converting a string of words to single string without spaces? [duplicate]

What is the preferred way to remove spaces from a string in C++? I could loop through all the characters and build a new string, but is there a better way?
The best thing to do is to use the algorithm remove_if and isspace:
remove_if(str.begin(), str.end(), isspace);
Now the algorithm itself can't change the container(only modify the values), so it actually shuffles the values around and returns a pointer to where the end now should be. So we have to call string::erase to actually modify the length of the container:
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
We should also note that remove_if will make at most one copy of the data. Here is a sample implementation:
template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
T dest = beg;
for (T itr = beg;itr != end; ++itr)
if (!pred(*itr))
*(dest++) = *itr;
return dest;
}
std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());
From gamedev
string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());
Can you use Boost String Algo? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573
erase_all(str, " ");
You can use this solution for removing a char:
#include <algorithm>
#include <string>
using namespace std;
str.erase(remove(str.begin(), str.end(), char_to_remove), str.end());
For trimming, use boost string algorithms:
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
// ...
string str1(" hello world! ");
trim(str1); // str1 == "hello world!"
Hi, you can do something like that. This function deletes all spaces.
string delSpaces(string &str)
{
str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
return str;
}
I made another function, that deletes all unnecessary spaces.
string delUnnecessary(string &str)
{
int size = str.length();
for(int j = 0; j<=size; j++)
{
for(int i = 0; i <=j; i++)
{
if(str[i] == ' ' && str[i+1] == ' ')
{
str.erase(str.begin() + i);
}
else if(str[0]== ' ')
{
str.erase(str.begin());
}
else if(str[i] == '\0' && str[i-1]== ' ')
{
str.erase(str.end() - 1);
}
}
}
return str;
}
If you want to do this with an easy macro, here's one:
#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end())
This assumes you have done #include <string> of course.
Call it like so:
std::string sName = " Example Name ";
REMOVE_SPACES(sName);
printf("%s",sName.c_str()); // requires #include <stdio.h>
string replaceinString(std::string str, std::string tofind, std::string toreplace)
{
size_t position = 0;
for ( position = str.find(tofind); position != std::string::npos; position = str.find(tofind,position) )
{
str.replace(position ,1, toreplace);
}
return(str);
}
use it:
string replace = replaceinString(thisstring, " ", "%20");
string replace2 = replaceinString(thisstring, " ", "-");
string replace3 = replaceinString(thisstring, " ", "+");
In C++20 you can use free function std::erase
std::string str = " Hello World !";
std::erase(str, ' ');
Full example:
#include<string>
#include<iostream>
int main() {
std::string str = " Hello World !";
std::erase(str, ' ');
std::cout << "|" << str <<"|";
}
I print | so that it is obvious that space at the begining is also removed.
note: this removes only the space, not every other possible character that may be considered whitespace, see https://en.cppreference.com/w/cpp/string/byte/isspace
#include <algorithm>
using namespace std;
int main() {
.
.
s.erase( remove( s.begin(), s.end(), ' ' ), s.end() );
.
.
}
Source:
Reference taken from this forum.
Removes all whitespace characters such as tabs and line breaks (C++11):
string str = " \n AB cd \t efg\v\n";
str = regex_replace(str,regex("\\s"),"");
I used the below work around for long - not sure about its complexity.
s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return (f==' '||s==' ');}),s.end());
when you wanna remove character ' ' and some for example - use
s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return ((f==' '||s==' ')||(f=='-'||s=='-'));}),s.end());
likewise just increase the || if number of characters you wanna remove is not 1
but as mentioned by others the erase remove idiom also seems fine.
string removeSpaces(string word) {
string newWord;
for (int i = 0; i < word.length(); i++) {
if (word[i] != ' ') {
newWord += word[i];
}
}
return newWord;
}
This code basically takes a string and iterates through every character in it. It then checks whether that string is a white space, if it isn't then the character is added to a new string.
Just for fun, as other answers are much better than this.
#include <boost/hana/functional/partial.hpp>
#include <iostream>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/filter.hpp>
int main() {
using ranges::to;
using ranges::views::filter;
using boost::hana::partial;
auto const& not_space = partial(std::not_equal_to<>{}, ' ');
auto const& to_string = to<std::string>;
std::string input = "2C F4 32 3C B9 DE";
std::string output = input | filter(not_space) | to_string;
assert(output == "2CF4323CB9DE");
}
I created a function, that removes the white spaces from the either ends of string. Such as
" Hello World ", will be converted into "Hello world".
This works similar to strip, lstrip and rstrip functions, which are frequently used in python.
string strip(string str) {
while (str[str.length() - 1] == ' ') {
str = str.substr(0, str.length() - 1);
}
while (str[0] == ' ') {
str = str.substr(1, str.length() - 1);
}
return str;
}
string lstrip(string str) {
while (str[0] == ' ') {
str = str.substr(1, str.length() - 1);
}
return str;
}
string rstrip(string str) {
while (str[str.length() - 1] == ' ') {
str = str.substr(0, str.length() - 1);
}
return str;
}
string removespace(string str)
{
int m = str.length();
int i=0;
while(i<m)
{
while(str[i] == 32)
str.erase(i,1);
i++;
}
}
string str = "2C F4 32 3C B9 DE";
str.erase(remove(str.begin(),str.end(),' '),str.end());
cout << str << endl;
output: 2CF4323CB9DE
I'm afraid it's the best solution that I can think of. But you can use reserve() to pre-allocate the minimum required memory in advance to speed up things a bit. You'll end up with a new string that will probably be shorter but that takes up the same amount of memory, but you'll avoid reallocations.
EDIT: Depending on your situation, this may incur less overhead than jumbling characters around.
You should try different approaches and see what is best for you: you might not have any performance issues at all.

Getting the substring of string with multiple instances of the same delimiter [duplicate]

This question already has answers here:
How do I iterate over the words of a string?
(84 answers)
Closed 4 years ago.
I have a string of data that looks like
string line = "Number:Description:Price:Weight";
I want to separate the string into 4 different variables via the delimiter ":". I was trying this via the substring method
char delimiter = ':';
string number = line.substr(0, line.find(delimiter));
It works fine for the first variable. However, I am unable to figure out how to iterate to the next instance of the ":" for the other variables.
std::string::find() takes a starting index as an optional parameter:
string line = "Number:Description:Price:Weight";
string::size_type start, end;
char delimiter = ':';
end = line.find(delimiter);
string number = line.substr(0, end);
start = end + 1;
end = line.find(delimiter, start);
string desc = line.substr(start, end-start);
start = end + 1;
end = line.find(delimiter, start);
string price = line.substr(start, end-start);
string weight = line.substr(end + 1);
Alternatively, you can split the string on delimiters by using std::istringstream with std::getline():
string line = "Number:Description:Price:Weight";
string number, desc, price, weight;
char delimiter = ':';
istringstream iss(line);
getline(iss, number, delimiter);
getline(iss, desc, delimiter);
getline(iss, price, delimiter);
getline(iss, weight);
It is much easier with a simple for loop:
#include <iostream>
#include <vector>
int main()
{
std::string line = "Number:Description:Price:Weight";
std::vector<std::string> vecStrings;
std::string word;
size_t count = 0;
for (auto const& it : line)
{
if (it != ':') word += it;
if ((it == ':') || (count + 1 == line.size()))
{
vecStrings.emplace_back(word);
word.clear();
}
++count;
}
for(const auto& it: vecStrings)
std::cout << it << "\n";
return 0;
}
See live action: https://www.ideone.com/DiAvjO
Update: If you need something different, you can do the same thing with std::for_each() and a lambda:
#include <algorithm>
std::for_each(std::begin(line), std::end(line), [&](char &letter)
{
if (letter != ':') word += letter;
if ((letter == ':') || (count + 1 == line.size()))
{
vecStrings.emplace_back(word);
word.clear();
}
++count;
});
However, a much simpler solution to this would be to use std::istringstream. Thanks to RemyLebeau for pointing out this:
#include <sstream>
std::stringstream sstr(line);
std::string word;
while (std::getline(sstr, word, ':'))
{
vecStrings.emplace_back(word);
}
you can make use of strtok like below
#include <string.h>
int main()
{
char line[] = "Number:Description:Price:Weight";
char * token = std::strtok (line,":");
while (token != NULL)
{
cout << token << '\n';
token = std::strtok(NULL, ":");
}
return 0;
}
Make necessary changes as per your need
cstring has strtok that does exactly what you want.

c++ std::string array as function parameter

I'm kind of new to C++. I want to make split function for std::string in c++ like java split function in String class(I don't want to use boost library). so I made custom split function which is..
using namespace std;
void ofApp::split(string ori, string tokens[], string deli){
// calculate the number of tokens
int length = 0;
int curPos = 0;
do{
curPos = ori.find(deli, curPos) + 1;
length++;
}while(ori.find(deli, curPos) != string::npos);
length++;
// to save tokens, initialize tokens array
tokens = new string[length]; // this is the line I'm suspicious about..
int startPos = 0;
int strLength = 0;
int curIndex = 0;
do{
strLength = ori.find(deli, startPos) - startPos;
tokens[curIndex++] = ori.substr(startPos, strLength);
startPos = ori.find(deli, startPos) + 1;
}while(ori.find(deli, startPos) != string::npos);
tokens[curIndex] = ori.substr(startPos, ori.length() - startPos);
}
First, I thought passing parameter as string tokens[] is the way call by reference, so when function is finished, tokens[] array will be full of tokens seperated by deli string. But when i call this function like
string str = "abc,def,10.2,dadd,adsf";
string* tokens;
split(str, tokens, ",");
after this, tokens array is completely empty. On my guess, this happens because of the line
tokens = new string[length];
I think memory space for tokens array as local variable is allocated and when split function is finished, this memory space will be free as block is finished.
when i try to debug, split function itself is working very well as tokens array is full of tokens at least in split function block. I think my guess is right but how can I solve this problem? Any solution? I think this is not only matter of std::string array, this is homework of "call by reference".
Requirement
pass std::string[] type to function parameter (return tokens[] is OK too. But I think this will have same problem)
when function is finished, array must full of tokens
tokens array length must be calculated in split function(if user has to calculate tokens length, it is foolish function). Because of this, memory for tokens array can't be allocated before split function call.
Thank you in advanced for your great answer!
As #chris suggested, something like the following code should work.
Example Code
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> split(const std::string& delimiter, const std::string& str)
{
std::vector<std::string> result;
std::size_t prevPos = 0;
while (prevPos != std::string::npos)
{
std::size_t currPos = str.find(delimiter, prevPos);
result.push_back(str.substr(prevPos, currPos - prevPos));
prevPos = currPos;
if (prevPos != std::string::npos)
{
// Skip the delimiter
prevPos += delimiter.size();
}
}
return result;
}
int main()
{
std::string str("this,is,a,test");
std::vector<std::string> splitResult = split(",", str);
for (const auto &s : splitResult)
{
std::cout << "'" << s << "'\n";
}
std::cout << "\n";
str = "this - is - a - test";
splitResult = split(" - ", str);
for (const auto &s : splitResult)
{
std::cout << "'" << s << "'\n";
}
return 0;
}
Example Output
'this'
'is'
'a'
'test'
'this'
'is'
'a'
'test'

Printing input string words in reverse order

Using if and while/do-while, my job is to print following user's inputs (string value) in reverse order.
For example:
input string value : "You are American"
output in reverse order : "American are You"
Is there any way to do this?
I have tried
string a;
cout << "enter a string: ";
getline(cin, a);
a = string ( a.rbegin(), a.rend() );
cout << a << endl;
return 0;
...but this would reverse the order of the words and spelling while spelling is not what I'm going for.
I also should be adding in if and while statements but do not have a clue how.
The algorithm is:
Reverse the whole string
Reverse the individual words
#include<iostream>
#include<algorithm>
using namespace std;
string reverseWords(string a)
{
reverse(a.begin(), a.end());
int s = 0;
int i = 0;
while(i < a.length())
{
if(a[i] == ' ')
{
reverse(a.begin() + s, a.begin() + i);
s = i + 1;
}
i++;
}
if(a[a.length() - 1] != ' ')
{
reverse(a.begin() + s, a.end());
}
return a;
}
Here is a C-based approach that will compile with a C++ compiler, which uses the stack to minimize creation of char * strings. With minimal work, this can be adapted to use C++ classes, as well as trivially replacing the various for loops with a do-while or while block.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 1000
#define MAX_WORD_LENGTH 80
void rev(char *str)
{
size_t str_length = strlen(str);
int str_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx = 0;
for (str_idx = str_length - 1; str_idx >= 0; str_idx--)
word_buffer[word_buffer_idx++] = str[str_idx];
memcpy(str, word_buffer, word_buffer_idx);
str[word_buffer_idx] = '\0';
}
int main(int argc, char **argv)
{
char *line = NULL;
size_t line_length;
int line_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx;
/* set up line buffer - we cast the result of malloc() because we're using C++ */
line = (char *) malloc (MAX_LINE_LENGTH + 1);
if (!line) {
fprintf(stderr, "ERROR: Could not allocate space for line buffer!\n");
return EXIT_FAILURE;
}
/* read in a line of characters from standard input */
getline(&line, &line_length, stdin);
/* replace newline with NUL character to correctly terminate 'line' */
for (line_idx = 0; line_idx < (int) line_length; line_idx++) {
if (line[line_idx] == '\n') {
line[line_idx] = '\0';
line_length = line_idx;
break;
}
}
/* put the reverse of a word into a buffer, else print the reverse of the word buffer if we encounter a space */
for (line_idx = line_length - 1, word_buffer_idx = 0; line_idx >= -1; line_idx--) {
if (line_idx == -1)
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s\n", word_buffer);
else if (line[line_idx] == ' ')
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s ", word_buffer), word_buffer_idx = 0;
else
word_buffer[word_buffer_idx++] = line[line_idx];
}
/* cleanup memory, to avoid leaks */
free(line);
return EXIT_SUCCESS;
}
To compile with a C++ compiler, and then use:
$ g++ -Wall test.c -o test
$ ./test
foo bar baz
baz bar foo
This example unpacks the input string one word at a time,
and builds an output string by concatenating in reverse order.
`
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string inp_str("I am British");
string out_str("");
string word_str;
istringstream iss( inp_str );
while (iss >> word_str) {
out_str = word_str + " " + out_str;
} // while (my_iss >> my_word)
cout << out_str << endl;
return 0;
} // main
`
This uses exactly one each of if and while.
#include <string>
#include <iostream>
#include <sstream>
void backwards(std::istream& in, std::ostream& out)
{
std::string word;
if (in >> word) // Read the frontmost word
{
backwards(in, out); // Output the rest of the input backwards...
out << word << " "; // ... and output the frontmost word at the back
}
}
int main()
{
std::string line;
while (getline(std::cin, line))
{
std::istringstream input(line);
backwards(input, std::cout);
std::cout << std::endl;
}
}
You might try this solution in getting a vector of string's using the ' ' (single space) character as a delimiter.
The next step would be to iterate over this vector backwards to generate the reverse string.
Here's what it might look like (split is the string splitting function from that post):
Edit 2: If you don't like vectors for whatever reason, you can use arrays (note that pointers can act as arrays). This example allocates a fixed size array on the heap, you may want to change this to say, double the size when the current word amount has reached a certain value.
Solution using an array instead of a vector:
#include <iostream>
#include <string>
using namespace std;
int getWords(string input, string ** output)
{
*output = new string[256]; // Assumes there will be a max of 256 words (can make this more dynamic if you want)
string currentWord;
int currentWordIndex = 0;
for(int i = 0; i <= input.length(); i++)
{
if(i == input.length() || input[i] == ' ') // We've found a space, so we've reached a new word
{
if(currentWord.length() > 0)
{
(*output)[currentWordIndex] = currentWord;
currentWordIndex++;
}
currentWord.clear();
}
else
{
currentWord.push_back(input[i]); // Add this character to the current word
}
}
return currentWordIndex; // returns the number of words
}
int main ()
{
std::string original, reverse;
std::getline(std::cin, original); // Get the input string
string * arrWords;
int size = getWords(original, &arrWords); // pass in the address of the arrWords array
int index = size - 1;
while(index >= 0)
{
reverse.append(arrWords[index]);
reverse.append(" ");
index--;
}
std::cout << reverse << std::endl;
return 0;
}
Edit: Added includes, main function, while loop format
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
// From the post
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
int main ()
{
std::string original, reverse;
std::cout << "Input a string: " << std::endl;
std::getline(std::cin, original); // Get the input string
std::vector<std::string> words = split(original, ' ');
std::vector<std::string>::reverse_iterator rit = words.rbegin();
while(rit != words.rend())
{
reverse.append(*rit);
reverse.append(" "); // add a space
rit++;
}
std::cout << reverse << std::endl;
return 0;
}
This code here uses string libraries to detect the blanks in the input stream and rewrite the output sentence accordingly
The algorithm is
1. Get the input stream using getline function to capture the spacecs. Initialize pos1 to zero.
2. Look for the first space in the input stream
3. If no space is found, the input stream is the output
4. Else, get the position of the first blank after pos1, i.e. pos2.
5. Save the sub-string bewteen pos1 and pos2 at the beginning of the output sentence; newSentence.
6. Pos1 is now at the first char after the blank.
7. Repeat 4, 5 and 6 untill no spaces left.
8. Add the last sub-string to at the beginning of the newSentence. –
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string sentence;
string newSentence;
string::size_type pos1;
string::size_type pos2;
string::size_type len;
cout << "This sentence rewrites a sentence backward word by word\n"
"Hello world => world Hello"<<endl;
getline(cin, sentence);
pos1 = 0;
len = sentence.length();
pos2 = sentence.find(' ',pos1);
while (pos2 != string::npos)
{
newSentence = sentence.substr(pos1, pos2-pos1+1) + newSentence;
pos1 = pos2 + 1;
pos2 = sentence.find(' ',pos1);
}
newSentence = sentence.substr(pos1, len-pos1+1) + " " + newSentence;
cout << endl << newSentence <<endl;
return 0;
}

set<string>: how to list not strings starting with given string and ending with `/`?

for example we have in our set:
bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog
bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog
bin/obj/Debug/vc100.idb
bin/obj/Debug/vc100.pdb
So this is what I tried based on this grate answer:
#include <iostream>
#include <algorithm>
#include <set>
#include <string>
#include <iterator>
using namespace std;
struct get_pertinent_part
{
const std::string given_string;
get_pertinent_part(const std::string& s)
:given_string(s)
{
}
std::string operator()(const std::string& s)
{
std::string::size_type first = 0;
if (s.find(given_string) == 0)
{
first = given_string.length() + 1;
}
std::string::size_type count = std::string::npos;
std::string::size_type pos = s.find_last_of("/");
if (pos != std::string::npos && pos > first)
{
count = pos + 1 - first;
}
return s.substr(first, count);
}
};
void directory_listning_without_directories_demo()
{
set<string> output;
set<string> demo_set;
demo_set.insert("file1");
demo_set.insert("file2");
demo_set.insert("folder/file1");
demo_set.insert("folder/file2");
demo_set.insert("folder/folder/file1");
demo_set.insert("folder/folder/file2");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
demo_set.insert("bin/obj/Debug/vc100.idb");
demo_set.insert("bin/obj/Debug/vc100.pdb");
std::transform(demo_set.begin(),
demo_set.end(),
std::inserter(output, output.end()),
get_pertinent_part("bin/obj/Debug/"));
std::copy(output.begin(),
output.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
int main()
{
directory_listning_without_directories_demo();
cin.get();
return 0;
}
This outputs:
CloudServerPrototype/
file1
file2
folder/
folder/folder/
vc100.idb
vc100.pdb
and we are given with bin/obj/Debug/string. We want to cout:
vc100.idb
vc100.pdb
CloudServerPrototype/
How to do such thing?
Quick example of what you want to do.
String.find(): http://www.cplusplus.com/reference/string/string/find/
String.subStr(): http://www.cplusplus.com/reference/string/string/substr/
string str = "bin/obj/Debug/vc100.pdb";
string checkString ("bin/obj/Debug");
// Check if string starts with the check string
if (str.find(checkString) == 0){
// Check if last letter if a "/"
if(str.substr(str.length()-1,1) == "/"){
// Output strating at the end of the check string and for
// the differnce in the strings.
cout << str.substr(checkString.length(), (str.length() - checkString.length()) ) << endl;
}
}
It's not clear with which part of the problem you are stuck, so here is a starter for you.
To get the parts of the strings between "given string" and the final '/' (where present):
std::string get_pertinent_part(const std::string& s)
{
std::string::size_type first = 0;
if (s.find(given_string) == 0)
{
first = given_string.length() + 1;
}
std::string::size_type count = std::string::npos;
std::string::size_type pos = s.find_last_of("/");
if (pos != std::string::npos && pos > first)
{
count = pos + 1 - first;
}
return s.substr(first, count);
}
To insert these parts into a new set (output) to guarantee uniqueness you can use the following:
std::transform(your_set.begin(),
your_set.end(),
std::inserter(output, output.end()),
get_pertinent_part);
You may wish to pass given_string into get_pertinent_part(), in which case you'll need to convert it to a functor:
struct get_pertinent_part
{
const std::string given_string;
get_pertinent_part(const std::string& s)
:given_string(s)
{
}
std::string operator()(const std::string& s)
{
std::string::size_type first = 0;
//
// ...same code as before...
//
return s.substr(first, count);
}
};
You can then call it this way:
std::transform(your_set.begin(),
your_set.end(),
std::inserter(output, output.end()),
get_pertinent_part("bin/obj/Debug"));
To output the new set:
std::copy(output.begin(),
output.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
Sorting the results is left as an exercise.
The easiest way I can think of, using the standard C functions, would be:
char * string1 = "bin/obj/Debug"
char * string2 = "bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog"
char result[64];
// the above code is just to bring the strings into this example
char * position = strstr(string1, string2);
int substringLength;
if(position != NULL){
position += strlen(string2);
substringLength = strchr(position, '/') - position;
strncpy(result, position, substringLength);
}else{
strcpy(result, string1); // this case is for when your first string is not found
}
cout << result;
The first thing that occurs, is finding the substring, string1, in the string we are analyzing, being string2. Once we found the starting point, and assuming it was there at all, we add the length of that substring to that starting point using pointer arithmatic, and then find the resulting string's length by subtracting the starting position from the ending position, which is found with strchr(position, '/'). Then we simply copy that substring into a buffer and it's there to print with cout.
I am sure there is a fancy way of doing this with std::string, but I'll leave that to anyone who can better explain c++ strings, I never did manage to get comfortable with them, haha