-4

I am trying to split a single string, with spaces, into three separate strings. For example, I have one string (str1). The user inputs any 3 words such as "Hey it's me" or "It's hot out". From there, I need to write a function that will take this string (str1) and divide it up into three different strings. So that (taking the first example) it will then say:

Hey (is the first part of the string)
it's (is the second part of the string)
me (is the third part of the string)

I'm having difficulty which manipulation I should be using to split the string at the spaces.

This is the code I have so far, which is just how the user will enter input.I am looking for the most basic way to accomplish this WITHOUT using istringstream! Using only basic string manipulation such as find(), substr().

** I am looking to create a separate function to perform the breaking up of string ** I figured out how to get the first section of input with this code:

cout << "Enter a string" << endl;
getline(cin, one);

position = str1.find(' ', position);
first_section = str1.substr(0, position);

But now I have no idea how to get the second section or the third section of the string to be divided up into their own string. I was thinking a for loop maybe?? Not sure.


#include <iostream>
#include <string>
using namespace std;

int main() {
   string str1;
   cout << "Enter three words: ";
   getline(cin, str1);
   while(cin) {
        cout << "Original string: " << str1 << endl;
        cin >> str1;
   }

   return;
}
Alyssa
  • 23
  • 1
  • 2
  • 8

3 Answers3

0

I'm having difficulty which manipulation I should be using to split the string at the spaces.

  1. Use a std::istringstream from str1.
  2. Read each of the tokens from the std::istringstream.

// No need to use a while loop unless you wish to do the same
// thing for multiple lines.
// while(cin) {

    cout << "Original string: " << str1 << endl;
    std::istringstream stream(str1);
    std::string token1;
    std::string token2;
    std::string token3;

    stream >> token1 >> token2 >> token3;

    // Use the tokens anyway you wish
// }

If you wish to do the same thing for multiple lines of input, use:

int main() {
   string str1;
   cout << "Enter three words: ";
   while(getline(cin, str1))
   {
      cout << "Original string: " << str1 << endl;
      std::istringstream stream(str1);
      std::string token1;
      std::string token2;
      std::string token3;

      stream >> token1 >> token2 >> token3;

      // Use the tokens anyway you wish

      // Prompt the user for another line
      cout << "Enter three words: ";
   }
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

Perhaps the most basic solution is to use that which resides inside of your loop to read a single word. For example:

cin >> word1;       // extracts the first word
cin >> word2;       // extracts the second word
getline(cin, line); // extracts the rest of the line

You can use the result or return value of these expressions to check success:

#include <string>
#include <iostream>

int main(void) {
    std::string word1, word2, line;
    int success = std::cin >> word1 && std::cin >> word2
                                    && !!std::getline(std::cin, line); // double-! necessary?
    if (success) { std::cout << "GOOD NEWS!"  << std::endl; }
    else         { std::cout << "bad news :(" << std::endl; }
    return 0;
}

Alternatively, in such a string I would expect two spaces. My suggestion would be to use string::find to locate the first and second spaces like so:

size_t first_position  = str1.find(' ', 0);

You should probably check this against string::npos as an opportunity to handle errors. Following that:

size_t second_position = str1.find(' ', first_position + 1);

Next error handling check and after that, it should then be trivial to use string::substr to split that string into sections like so:

string first_section  = str1.substr(0              , first_position)
     , second_section = str1.substr(first_position , second_position)
     , third_section  = str1.substr(second_position, string::npos);
autistic
  • 1
  • 3
  • 35
  • 80
  • for some reason when i go to store the first_position in the first_section string, I get an error that says: [Error] no matching function for call to 'std::basic_string::substr(int, std::string&)' – Alyssa May 19 '17 at 04:34
  • @Alyssa Would you mind providing some code to demonstrate that problem? It seems like you're calling something like `str1.substr(0, some_string);` where `some_string` is the cause of the error; you need to provide an *integral* (`size_t`, specifically) value. That's just a guess, though, and I can't validate or invalidate it without the code you're having problems with... – autistic May 20 '17 at 02:22
0

I have this Utility class that has a bunch of methods for string manipulation. I will show the class function for splitting strings with a delimiter. This class has private constructor so you can not create an instance of this class. All the methods are static methods.

Utility.h

#ifndef UTILITY_H
#define UTILITY_h

// Library Includes Here: vector, string etc.

class Utility {
public:
    static std::vector<std::string> splitString( const std::string& strStringToSplit,
                                                 const std::string& strDelimiter,
                                                 const bool keepEmpty = true );

private:
    Utility();
};

Utility.cpp

std::vector<std::string> Utility::splitString( const std::string& strStringToSplit, 
                                               const std::string& strDelimiter, 
                                               const bool keepEmpty ) {
    std::vector<std::string> vResult;
    if ( strDelimiter.empty() ) {
        vResult.push_back( strStringToSplit );
        return vResult;
    }

    std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd;
    while ( true ) {
        itSubStrEnd = search( itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end() );
        std::string strTemp( itSubStrStart, itSubStrEnd );
        if ( keepEmpty || !strTemp.empty() ) {
            vResult.push_back( strTemp );
        }

        if ( itSubStrEnd == strStringToSplit.end() ) {
            break;
        }

        itSubStrStart = itSubStrEnd + strDelimiter.size();
    }

    return vResult;    
} 

Main.cpp -- Usage

#include <string>
#include <vector>
#include "Utility.h"

int main() {
    std::string myString( "Hello World How Are You Today" );

    std::vector<std::string> vStrings = Utility::splitString( myString, " " );

    // Check Vector Of Strings
    for ( unsigned n = 0; n < vStrings.size(); ++n ) {
        std::cout << vStrings[n] << " ";
    }
    std::cout << std::endl;

    // The Delimiter is also not restricted to just a single character
    std::string myString2( "Hello, World, How, Are, You, Today" );

    // Clear Out Vector
    vStrings.clear();

    vStrings = Utility::splitString( myString2, ", " ); // Delimiter = Comma & Space

    // Test Vector Again
    for ( unsigned n = 0; n < vStrings.size(); ++n ) {
        std::cout << vStrings[n] << " ";
    }
    std::cout << std::endl;

    return 0;
}
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59