2

I've been trying to split a name into first and last name, but I'm sure my implementation is not the best one as far as simplicity.

string name = "John Smith";
    string first;
    string last (name, name.find(" "));//getting lastname
    for(int i=0; i<name.find(" "); i++)
    {
        first += name[i];//getting firstname
    }
    cout << "First: "<< first << " Last: " << last << endl;

Thanks in advance

FrustratedWithFormsDesigner
  • 26,726
  • 31
  • 139
  • 202
miatech
  • 2,150
  • 8
  • 41
  • 78
  • 8
    I know you're probably writing this for a simple use, but you should be aware that splitting names can be dicey; there are two-word surnames, surnames that come first, and so on. – Cascabel Jan 09 '11 at 01:16

5 Answers5

5

How about using the substr method from string to split things up combined with find:

std::string name = "John Smith"
std::size_t pos = name.find(" ");
std::cout << "First: " << name.substr(0, pos) << " Last: " << name.substr(pos, std::string::npos) << std::endl;

where I've also used the std::string::npos to indicate the last position of a string. Techincally, I could just get away with name.substr(pos) as npos is the default parameter.

Also, see this SO post about string splitting. You'll find better items there, like mention of the Boost split function.

Community
  • 1
  • 1
wheaties
  • 35,646
  • 15
  • 94
  • 131
  • Nice solution. But if not using "using namespace std;", you should also prefix "string" and "cout" with the "std::" thingy, no? – liorda Jan 09 '11 at 01:20
  • hey, I second that! great solution.... when I first started looking for a solution, the link you posted was the one I come across, but I couldn't make it work with my specific string....Thanks – miatech Jan 09 '11 at 05:34
  • What happens to all the middle names. As a result I would use find_first_of() to find the end of the first name and find_last_of() to find the beginning of the last name. – Martin York Jan 09 '11 at 08:45
  • @Martin York in truth I would not use my solution if I had to actually split names. There are multiple examples where names aren't in shape, i.e. in Spain they generally have two last names, one from the father and one from the Mother. A name splitting engine would have a ton of rules. I am assuming his question revolved around but a simple pairing. – wheaties Jan 09 '11 at 14:36
  • @wheaties: True. Given the simple requirements from the OP your solution holds. Just be careful of extra spaces on the front of the string and note words are generally split by `White Space` not just the `Space Character`. – Martin York Jan 09 '11 at 17:52
1

If there are undetermined number of leading, trailing, and in-between spaces (and/or tabs), then the following is a very clean (but not necessarily most efficient) alternative that I can suggest:

std::istringstream ssname( name ); // needs <sstream> header
string first, last;
ssname >> first >> last;
sly
  • 1,722
  • 1
  • 10
  • 15
0

Can try

strtok

function to split the string, code will be clean

Akhil
  • 2,269
  • 6
  • 32
  • 39
  • strtok is very messy. It modifies the input string (which in C++ is not nice as we try and stay const correct). – Martin York Jan 09 '11 at 08:42
0

@ Akhil :: I would not recommend to use strtok in a c++ program as it cannot be used to run multiple instances of strtok as it uses a static variable in its implementation. Well you can ofcourse use it if you are going to use a single instance at any point of time..but better to go with c++ design patterns wheb you are using c++ :)

Arunmu
  • 6,837
  • 1
  • 24
  • 46
0

Extending the idea by sly:

#include <map>
#include <memory>
#include <functional>
#include <algorithm>
#include <iostream>
#include <sstream>


int main()
{
    std::string             name    = "   Martin Paul Jones   ";
    std::string::size_type  s       = name.find_first_not_of(" \t\n\r");
    std::string::size_type  e       = name.find_last_not_of(" \t\n\r");
    std::string             trim    = name.substr(s, (e - s + 1));
    std::string             first   = trim.substr(0, trim.find_first_of(" \t\n\r"));
    std::string             last    = trim.substr(trim.find_last_of(" \t\n\r") + 1);

    std::cout << "N(" << name << ") " << " T(" << trim << ") First(" << first << ") Last(" << last << ")\n";

    // Alternative using streams
    std::stringstream       namestream(name);
    namestream >> first >> last;
    while(namestream >> last) { /* Empty */ } // Skip middle names
    std::cout << "N(" << name << ")  First(" << first << ") Last(" << last << ")\n";
}

Try:

> g++ xx.cpp
> ./a.out
N(   Martin Paul Jones   )  T(Martin Paul Jones) First(Martin) Last(Jones)
N(   Martin Paul Jones   )  First(Martin) Last(Jones)
Martin York
  • 257,169
  • 86
  • 333
  • 562