NinjaZ
NinjaZ

Reputation: 25

Obtaining First and Last Charsof Each String From A Vector of Strings

I have created a vector<string> names; which stores peoples first names. I want to take each name and create two variables first_letter and last_letter which contains the first and last characters of each name. However I am not quite sure how to get this done since I am just starting with c++. Can anyone explain to me how this can be done, and possibly provide an example?

Upvotes: 1

Views: 127

Answers (8)

vaultah
vaultah

Reputation: 46533

Assuming name is your string and you're OK with using C++11, name.front() and name.back() will work, otherwise dereference the iterator: *name.begin() and *name.rbegin(). Though you'd check whether the name is empty or not:

if (!name.empty()) {
    // Safe to proceed now
}

You can iterate over names like (range loop - since C++11)

for (auto& name : names) {
    // Do things with individual name
}

or (for older C++)

for (vector<string>::iterator it = names.begin(); it != names.end(); it++) {
    // Do things with individual name (*it)
}

It's advised to use constant iterators where possible, if you're not planning to modify strings, replace auto with const auto and ::iterator with ::const_iterator.

Upvotes: 4

Barry
Barry

Reputation: 303107

In C++11 it got easier:

for (std::string& name : names) {
     char first_letter = name.front();
     char last_letter = name.back();
     // do stuff
}

Before that, you'd have to access them directly using operator[]:

for (size_t i = 0; i < names.size(); ++i) {
     std::string& name = names[i];

     char first_letter = name[0];
     char last_letter = name[name.size() - 1];
     // do stuff
}

Upvotes: 4

Felix Glas
Felix Glas

Reputation: 15524

There are many ways to skin this cat.

Here's another short readable example using C++11. What this brings to the table is the use of std::vector::emplace_back which allows for in-place construction of elements, as opposed to move- or copyconstructing. Also shorter syntax which is nice.

Say you have a container that stores the pairs of letters.

std::vector<std::pair<char, char>> letters;

Then use this:

for (auto&& name : names)
    letters.emplace_back(name.front(), name.back());

If you want to throw on empty name strings, simply add a statement before the std::vector::emplace_back statement:

if (name.empty()) throw std::runtime_error("Empty string!");

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

Consider the following approach

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <utility>
#include <iterator>

int main() 
{
    std::vector<std::string> v { "Hello", "NinjaZ", "How", "do", "you", "do" };

    for ( const auto &s : v ) std::cout << s << ' ';
    std::cout << std::endl;

    std::vector<std::pair<char, char>> v2;
    v2.reserve( v.size() );

    std::transform( v.begin(), v.end(), 
                    std::back_inserter( v2 ),
                    []( const std::string &s )
                    {
                        return std::make_pair( s.front(), s.back() );
                    } );

    for ( const auto &p : v2 )
    {
        std::cout << p.first << ' ' << p.second << std::endl;
    }

    return 0;
}

The output is

Hello NinjaZ How do you do 
H o
N Z
H w
d o
y u
d o

Instead of the algorithm std::transform you could use an ordinary range based for loop. For example

for ( const auto &s : v ) v2.push_back( { s.front(), s.back() } );

Upvotes: 0

Tomislav
Tomislav

Reputation: 41

First off, of course, you start with a loop to iterate through the vector. Then you get those characters with substr, it would look something like this

vector <string>::iterator it;
for(it = names.begin(); it != names.end(); it++)
{
    string first = (*it).substr(0, 1);
    string second = (*it).substr((*it).length()-1, 1);
    ..
    do whatever you want to
    ..
}

Upvotes: 0

Jonathan Wakely
Jonathan Wakely

Reputation: 171303

Create a function to get the two letters from a single string:

std::pair<char, char>
first_and_last(const std::string& s)
{
  if (s.length() == 0)
    throw std::runtime_error("Empty string!")
  return {s.front(), s.back()};
}

(for C++03 return std::make_pair(s[0], s[s.length()-1]) or another of the ways to do it shown by the other answers.)

Then apply that function to each name in turn, saving the results in a new vector:

std::vector<std::pair<char, char>> letters;
letters.reserve(names.size());
std::transform(names.begin(), names.end(), std::back_inserter(letters), first_and_last);

Or use the C++11 range-based for loop:

std::vector<std::pair<char, char>> letters;
letters.reserve(names.size());
for (const auto& name : names)
  letters.push_back( first_and_last(name) );

Upvotes: 1

Guy Kogus
Guy Kogus

Reputation: 7341

Something like this? There's no error checking, but it's a start.

vector<string> names = ...;
for (vector<string>::iterator i = names.begin(); i != names.end(); ++i)
{
    string first_letter = i->substr(0, 1);
    string last_letter = i->substr(i->size() - 1, 1);
}

Upvotes: 0

PaulMcKenzie
PaulMcKenzie

Reputation: 35440

Use the string functions front() and back().

Make sure that the string is not empty before using these functions:

Assuming that i is an index into your vector:

if ( !names[i].empty() )
{
    char fChar = names[i].front();
    char bChar = names[i].back();
}

Upvotes: 2

Related Questions