-1

i was wondering if this was a safe way of splitting up string into specific variables. I am currently not getting the correct results. Need newFirstName to contain Joe. newLast name to contain Robbin. NewTeam to contain Oilers and so on. What i am currently getting is nothing in all of the variables except for newFirstname. A point in the correct direction would be much appreciated.

    string line = "Joe|Robbin|Oilers|34|23";
    char* strToChar = NULL;
    char* strPtr = NULL;

    string newFirstName = " ";
    string newLastName = " ";
    string newTeam = " ";
    int newAssists = 0;
    int newGoals = 0;

    sscanf(line.c_str(), "%[^|]s%[^|]s%[^|]s%d|%d",(char*)newFirstName.c_str(), (char*)newLastName.c_str(), (char*)newTeam.c_str(), &newGoals, &newAssists);

Saw lots of great answers but before i did i came up with:

    string line = "Joe|Robbin|Oilers|34|23";
    char* strToChar = NULL;
    char* strPtr = NULL;
    string newFirstName = " ";
    string newLastName = " ";
    string newTeam = " ";
    int newAssists = 0;
    int newGoals = 0;
    int count = 0;



    std::string delimiter = "|";

    size_t pos = 0;
    std::string token;
    while ((pos = line.find(delimiter)) != std::string::npos) 
    {
        count++;
        token = line.substr(0, pos);
        std::cout << token << std::endl;
        line.erase(0, pos + delimiter.length());

        switch (count)
        {
        case 1:
            newFirstName = token;
            break;
        case 2:
            newLastName = token;
            break;
        case 3:
            newTeam = token;
            break;
        case 4:
            newGoals = atoi(token.c_str());
            break;
        }


    }
    newAssists = atoi(line.c_str());
CP_nate
  • 41
  • 6
  • 1
    You can't assign to `.c_str()` this way. The strings don't have enough space allocated for the strings you're putting into them. – Barmar Apr 13 '17 at 21:45
  • *i was wondering if this was a safe way of splitting up string into specific variables* -- Quick answer -- No. Stop using casts, and stop using `C`. – PaulMcKenzie Apr 13 '17 at 21:45
  • There's a reason why `std::string::c_str()` returns `const char *` -- you can't modify the string directly. – Barmar Apr 13 '17 at 21:46
  • What would be the c++ equivalent of sscanf to easily extract the data from the string separated by a | character? – CP_nate Apr 13 '17 at 21:49
  • Well, the first step in doing it in c++ would be to use `std::string` as a real class, not a c_str holder. Then you could look at examples like http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c – infixed Apr 13 '17 at 21:59

2 Answers2

1

To split a string by some delimiter other than space, the simplest is to use a stringstream along with std::getline, which permits to specify your delimiting character.

std::istringstream iss(line);
std::getline(iss, newFirstName, '|');
std::getline(iss, newLastName, '|');
std::getline(iss, newTeam, '|');
iss >> newAssists;
iss.ignore(); // drop the '|'
iss >> newGoals;

The way you were doing it has many problems indicated in the comments. Most important error was trying to write directly in a std::string's buffer through sscanf, which breaks the most important rule of data encapsulation and leads to undefined behavior.

A.S.H
  • 28,433
  • 5
  • 19
  • 45
1

I was wondering if this was a safe way of splitting up string into specific variables.

My suggestion:

  1. Use std::istringstream and std::getline to tokenize the line.
  2. Pull the numbers of out of the tokens using std::stoi.

Here's a working example.

#include <iostream>
#include <sstream>
#include <string>

int main()
{
   std::string line = "Joe|Robbin|Oilers|34|23";
   std::istringstream str(line);

   std::string newFirstName;
   std::string newLastName;
   std::string newTeam;
   std::string newAssistsString;
   std::string newGoalsString;

   std::getline(str, newFirstName, '|');
   std::getline(str, newLastName, '|');
   std::getline(str, newTeam, '|');
   std::getline(str, newAssistsString, '|');
   std::getline(str, newGoalsString);

   // Sanity check.
   if (!str )
   {
      std::cout << "Unable to extract the tokens from the line\n";
      return EXIT_FAILURE;
   }

   int newAssists = std::stoi(newAssistsString);
   int newGoals = std::stoi(newGoalsString);

   std::cout
      << newFirstName << " "
      << newLastName << " "
      << newTeam << " "
      << newAssists << " "
      << newGoals << std::endl;

   return EXIT_SUCCESS;
}

Output

Joe Robbin Oilers 34 23
R Sahu
  • 196,807
  • 13
  • 136
  • 247