-1

I want to pass a string to the compiler for example "Mr. Adam, I am Eve" . I want to lower the case of that phrase and remove all the punctuation marks and spaces by using (isalpha), i.e.- afterwards the string should be: mradamiameve which will be stored in another string called result for example. I need help with this. Any suggestions?

This is what I have done so far, which does not work:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, char* argv[]) 
{
    string str = "Mr. Adam, I am Eve";
    string result;
    for (size_t i = 0; i < str.length(); ++i)
    {
        if (isalpha(str[i]))
        {       
            result[i] = str[i];
        }
    }

    // here str should be = "mradamiameve" YET it is still "Mr. Adam, I am Eve" 
    cout << "after using to tolower() and isalpha() str is:" << str << endl; 
    return 0;
}
Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
  • 1
    [Standard algorithms](http://en.cppreference.com/w/cpp/algorithm) – Justin Apr 22 '18 at 19:20
  • 1
    This `result[i] = str[i];` should be: `result.push_back(str[i]);` or adding the `std::tolower` : `result.push_back(std::tolower(str[i]));` and that's all. You 're done. – DimChtz Apr 22 '18 at 19:24

2 Answers2

2

If you are on c++11 you could use range based loop:

#include <iostream>
#include <cctype>
#include <string>

int main()
{ 
    std::string result, str = "Mr. Adam, I am Eve";

    for (unsigned char c : str)
        if (std::isalpha(c))
            result += std::tolower(c);

    std::cout << result << std::endl;
}
Killzone Kid
  • 6,171
  • 3
  • 17
  • 37
  • Pedantic: `std::string` is templated on `char`, not `unsigned char`. `char` has implementation defined signedness, so sometimes, `char` and `unsigned char` represent the same range of values, but `char` could just as easily by `signed`. For ASCII, this doesn't matter, but if your data falls outside the ASCII range this can cause problems. Use `for (char c : str)` (or `for (auto c : str)` if `str` might be a different specialization of `std::basic_string`) for strict correctness. – ShadowRanger May 02 '18 at 19:13
  • @ShadowRanger I did this on purpose to force `unsigned char` for `std::isalpha` and `std::tolower`. The example note on [this page](http://en.cppreference.com/w/cpp/string/byte/tolower) shows similar use of string with algorithms, when the argument is also forced to `unsigned char` – Killzone Kid May 02 '18 at 19:25
  • Ah, right. Those functions come from C, and work with `int`, not `char`, so the upcast from (maybe `signed`) `char` to `int` will do strange things when the values are outside the ASCII range. I'd still favor an explicit cast at time of use, rather that hoping the compiler doesn't complain that you're implicitly casting `char` to `unsigned char`, but yeah, it would need to be `unsigned char` when passed to `isalpha`/`tolower`. – ShadowRanger May 02 '18 at 19:28
1

In your code, the variable result was never resized. Then, you are trying to access indexes that are out of bounds, which is undefined behavior.

Instead, you should append the lowercase of the character (in case it is a desired one - isalpha returns true), using the push_back method.

result.push_back(tolower(str[i]));
Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
Rabster
  • 933
  • 1
  • 7
  • 11