The answer to your earlier question showed one way to do just what you ask, but didn't directly show how to access any given string by index. In the comment by @RemyLebeau above there are several approaches outline. One of the easiest remains separating the newline separated strings into a std::vector<std::string>
. You can then obtain the index where the wanted string is located and then .erase()
that index (iterator at that index), or swap two indexes, etc..
You take it up to the point of creating the std::stringstream
in the snippet of code you show, you simply need to complete the process.
To locate the index where the wanted string is found, you can use a simple for
loop to obtain the index. The following program takes as its first argument the substring to find in your multi-line input string:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
int main (int argc, char **argv) {
if (argc < 2) { /* validate one argument provided for wanted substring */
std::cerr << std::string {"usage: "} + argv[0] + " substring\n";
return 1;
}
const std::string want {argv[1]}; /* wanted substring */
std::vector<std::string> vs {}; /* vector<string> for strings */
std::string s {"199\n200\n208\n210\n200"}; /* input string */
std::string tmp; /* tmp to read stringstream */
std::stringstream ss (s); /* initialize stringstream */
while (ss >> tmp) { /* loop reading tmp from stringstream */
vs.push_back(tmp); /* add string to vector of string */
}
size_t ndx = vs.size(); /* index of desired substring */
for (size_t i = 0; i < vs.size(); i++) { /* loop over each string */
if (vs[i] == want) { /* if wanted substring */
ndx = i; /* save index */
break;
}
}
if (ndx != vs.size()) { /* if found, output index of substring */
std::cout << want << " is index: " << ndx << '\n';
}
else {
std::cout << want << " does not exist in input.\n";
}
}
Example Use/Output
$ ./bin/str_multiline 208
208 is index: 2
Once you have the index, you can std::swap
or .erase()
that index and write the modified collection of strings back to a std::stringstream
or output it as desired.
If the wanted substring isn't found, you have:
$ ./bin/str_multiline 207
207 does not exist in input.
Using <algorithm>
std::find_if()
To Do The Same
You can use some of the niceties of the algorithms library to automate the index find by using std::find_if to return the iterator to the index in the array of strings where the wanted string exists (or the end iterator if the wanted string isn't found). To obtain the index, you can simply subtract the beginning iterator, e.g.
...
#include <algorithm>
...
size_t ndx; /* index of desired substring */
std::vector<std::string> vs {}; /* vector<string> for strings */
std::string s {"199\n200\n208\n210\n200"}; /* input string */
std::string tmp; /* tmp to read stringstream */
std::stringstream ss (s); /* initialize stringstream */
while (ss >> tmp) { /* loop reading tmp from stringstream */
vs.push_back(tmp); /* add string to vector of string */
}
/* locate index of wanted string with find_if - begin iterator */
if ((ndx = std::find_if (vs.begin(), vs.end(),
[want](std::string n) {
return n == want;
}) - vs.begin()) != vs.size()) {
std::cout << want << " is index: " << ndx << '\n';
}
else {
std::cout << want << " does not exist in input.\n";
}
(same use/output)
Manipulating The String Directly
You can avoid using the vector of strings altogether by looping down the string with the std::basic_string::find to locate the first '\n'
. Your first substring occurs between the beginning and the index returned. Keeping track of the index and using as pos + 1
, you have the beginning of the second substring to start your next call to std::basic_string::find
(repeat until end of string)
The only caveat there is it is up to you to maintain the locations where each string begins and ends in order to manipulate the string. It's more manual position accounting than is needed using the array of strings approach. But both are equally fine.
There are more ways as well, these are just a few.
Let me know if this is closer to what you were looking for rather than the answer to your previous question. If you compare with the previous answer, this answer essentially separates the substrings in the same way, but adds how to identify the index of the wanted substring.