0

Given a string, I have to return the middle character or characters(if the string is even) of the string. This is what I came up with.

#include <iostream>
#include <string>

std::string input = "test";
std::string get_middle(std::string input) 
{

if (input.size() % 2 == 0) {
        input.erase(input.begin(), (input.size() / 2) - 1);
        input.erase(input.begin() + 2, (input.size() / 2) - 1);
    }
    else {
        input.erase(input.begin(), (input.size() - 1) / 2);
        input.erase(input.begin() + 1,(input.size() - 1) / 2);
    }
  return input;
}  

The errors have always been at the input.begin() or input.erase() part. Curiously, this example I found on http://www.cplusplus.com/reference/string/string/erase/ works even when it looks the same as mine:

#include <iostream>
#include <string>

int main ()
{
  std::string str ("This is an example sentence.");
  std::cout << str << '\n';
                                           // "This is an example sentence."
  str.erase (10,8);                        //            ^^^^^^^^
  std::cout << str << '\n';
                                           // "This is an sentence."
  str.erase (str.begin()+9);               //           ^
  std::cout << str << '\n';
                                           // "This is a sentence."
  str.erase (str.begin()+5, str.end()-9);  //       ^^^^^
  std::cout << str << '\n';
                                           // "This sentence."
  return 0;
}

What seems to be the issue here?

J Xkcd
  • 383
  • 2
  • 10

4 Answers4

0

The second parameter should be an iterator here and all the codes alike:

input.erase(input.begin() + 1,(input.size() - 1) / 2);

In your case it is a size_t instead of iterator.

iterator erase( const_iterator first, const_iterator last );

first, last range of elements to remove

Oblivion
  • 7,176
  • 2
  • 14
  • 33
  • Oh so the erase function can take different forms?One of those forms is If I input an iterator for my first parameter, I must also input an iterator for my second parameter? – J Xkcd Dec 02 '19 at 16:44
  • @JXkcd it has overloads. Just check the link I cited please. That was the difference between your code and the one you cited – Oblivion Dec 02 '19 at 16:45
  • I have. I did not realise it had overloads, I do now, thank you. – J Xkcd Dec 02 '19 at 16:49
0

You can either use iterators (input.begin() and input.end() are iterators) or int to specify the erase part. You cannot use both at the same time.

input.erase(input.begin(), (input.size() / 2) - 1);

This is false. input.erase(0, (input.size() / 2) -1); should work instead.

If you want to learn more about iterators, which is an interesting concept, you can check : What is an iterator in general?

Alois Christen
  • 543
  • 3
  • 14
  • It does, however, input.begin() is not always equivalent to 0 and my output will be false. – J Xkcd Dec 02 '19 at 16:45
  • @JXkcd `input.begin()` is **always** equal to `0`. `begin` points to the first element which is what the index 0 also represents. – NathanOliver Dec 02 '19 at 16:50
  • Maybe I'm wrong, but for String I think it's always the same. (if someone reading this knows, please tell me) Anyway, you can modify the other part of your `erase` call, by giving it an iterator on the last element you want to delete. Something like : `input.erase(input.begin(), input.begin + ((input.size() / 2) - 1));` – Alois Christen Dec 02 '19 at 16:54
  • When I use the ```erase``` function, it always shifts the string to the left is what you're saying? – J Xkcd Dec 02 '19 at 16:54
  • @Alois Christen Oh I've found a working solution, I used the sequence overload for the first step and then the range overload for the second step. – J Xkcd Dec 02 '19 at 16:56
0

Your direct problem aside, you do not need to erase anything from a std::string to get your taks done.

If you want to return the middle character (or two when the number of characters is even), then just do that:

std::string get_middle(std::string input) {
        auto middle = input.size() /2; 
        if (input.size() % 2 == 1) {
             return { input[middle] };
         } else {
             return std::string{ input[middle-1] } + input[middle];
         }
}  

For some reason I didnt feel like using std::string::substr but instead construct a string from the first character to be returned and then add (+) the second character.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

For starters there is no need to apply the member function erase that to get a tring consisting of middle characters of the source string.

The function for example can look like

#include <iostream>
#include <string>

std::string get_middle( const std::string &s )
{
    return s.empty() ? s 
                     : s.substr( s.size() / 2 - ( s.size() + 1 ) % 2,
                                 1 + ( s.size() + 1 ) % 2 );
}

int main()
{
    std::string s( "Test" );

    std::cout << get_middle( s ) << '\n';
} 

Secondly the class std::string has the following erase methods

basic_string& erase(size_type pos = 0, size_type n = npos); 
iterator erase(const_iterator p); 
iterator erase(const_iterator first, const_iterator last);

Neither of which is used for example in this statement

input.erase(input.begin(), (input.size() / 2) - 1);

So the compiler issues an error.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335