-1

I am updating this again because I am utterly lost, I apologize. I think I can more clearly word it now after trying this solutions, so here goes:

Say I have a string that goes:

"
199  
200  
208  
210    
200 
"

Here's the update: I may have worded it poorly before, so here it is in no uncertain terms: How do I make it so if that string is called s, then s[0] = 199 (rather than 1), s[1] = 200 (rather than 9), s[2] = 208 (rather than 9), etc. I am sorry to keep coming back here, but I really want to resolve this.

By the way, this is my code so far:

int main()
{
    int increase_altitude = 0;

    int previous = 10000;
    std::string s;
    while (std::getline(std::cin, s))
    {
        std::stringstream ss(s);
    }
CS Student
  • 33
  • 6
  • 3
    If you want to manipulate numbers, transform your input string into an array of numbers and work with that, much easier and faster. – Martin Apr 27 '22 at 16:33
  • Did you save the line endings in the string? You'll need some *marker* to indicate the end of a line. IMHO, better to use `std::vector` – Thomas Matthews Apr 27 '22 at 16:45
  • Better to use that as opposed to what? – CS Student Apr 27 '22 at 16:49
  • You should have edited [your previous question](https://stackoverflow.com/q/72022994/445976) to clarify or add information instead of posting this duplicate. – Blastfurnace Apr 27 '22 at 17:33
  • If you have a *single string* containing line breaks, put the entire string into an `std::istringstream` and then extract the individual strings from it using `std::getline()`. For instance, you can use that logic to split the string into a ` std::vector` for easier use. Of course, you could just use `std::string::find(first_of)()` and `std::string::substr()` for that, too. Or any of a number of other ways to split up the string. See [Parse (split) a string in C++ using string delimiter (standard C++)](https://stackoverflow.com/questions/14265581/) and other similar questions – Remy Lebeau Apr 27 '22 at 17:41

1 Answers1

0

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.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85