14

I am trying to check whether an input string is alphanumeric or more uppercase or empty. If the input string is among the above-malfunctioned strings, I simply want to return false/0 otherwise work with rest of the program which is working fine. The chunk of my program which is given problem :

std::string myfunc(std::string input){
    std::string b="";

    if (!input.size()) return 0;
    for (int i = 0; i < input.size(); i++){

        if ( input[i] < 'a' || input[i] > 'z'|| isalpha(input[i]) || isupper(input[i]) ) return 0;
    }
    b = input;
    //just copy the input string for now.
    return b;
}

and I call this function as

int main(){
    std::string input="Somthing";
    std::cout << myfunc(input)<< std::endl;
    return  0;
}

getting the below error?

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
Aborted (core dumped)

This program runs well without these two edge cases. I am not able to understand the error and find a fix to it? Any suggestions on what I am doing wrong?

Anu
  • 3,198
  • 5
  • 28
  • 49
  • 4
    The issue is `return 0;` – πάντα ῥεῖ Jan 29 '19 at 20:41
  • 1
    Also pass the string by `const&`. – Matthieu Brucher Jan 29 '19 at 20:46
  • 3
    maybe you want to return a `std::optional` when the function returns either a string or nothing – 463035818_is_not_an_ai Jan 29 '19 at 20:46
  • yeah, I was looking of this type, since I wanna return both, string in the normal case, but integer if there a malfunctioned string is received! – Anu Jan 29 '19 at 20:48
  • nice example, why it is important to post a mcve ;). The code you posted here looks like you want to return a `bool` not a `string` (we cannot know what `...` is), and thats what you got the answer for. Please read about [mcve] – 463035818_is_not_an_ai Jan 29 '19 at 20:51
  • @MatthieuBrucher, any specific reason to pass string as const&, I just passed my string as value! and I an changing it inside the functions, I an just using it. – Anu Jan 29 '19 at 20:52
  • 1
    Are you always changing it inside? And what do you mean by changing it? `const&` is better if you may not always require changing it or returning it. – Matthieu Brucher Jan 29 '19 at 20:56
  • `...` is variadic code. I expect it to show up in the Standard about the same time as telepathy support so the compiler can generate the program you want, not the one you coded. – user4581301 Jan 29 '19 at 20:58
  • @user463035818, Any idea on how to enable `std::optional` for types `bool and string`? in the online doc, I am supposed to provide an optional type as a parameter to it! such as `std::optional`, I think I need to refactor my code since this scheme doesn't work. Any suggestion! – Anu Jan 29 '19 at 21:08
  • `std::optional` is either a string or not, why do you want a bool in addition? You only return the string or `0`,no? – 463035818_is_not_an_ai Jan 29 '19 at 21:11
  • @user463035818, that makes sense, it has the same meaning! but, even after using `#include`, my compiler doesn't recognize `optional`, any suggestion on it! – Anu Jan 29 '19 at 21:19
  • @Anu I'd still say that you're putting two different pieces of functionality into one function. First a validity check and then some kind of string processing. Two functions seems like the way to go to me. Or if the validity check is really an error check then maybe throw an exception. – john Jan 29 '19 at 21:21
  • std::optional is c++17 i think, make sure you compiler supports it – 463035818_is_not_an_ai Jan 29 '19 at 21:24

3 Answers3

17

The problem is the two return 0; statements in your function. The function returns a std::string, which has no constructors that accept an int as input. But, it does have a constructor that accepts a const char * pointer, which 0 is implicitly convertible to. However, constructing a std::string with a null char * pointer is undefined behavior, and your implementation has chosen to throw a std::logic_error exception that you are not catching in your code.

In this case, I would simply return a blank string instead:

std::string myfunc(const std::string &input){
    if (input.empty()) return "";
    for (int i = 0; i < input.size(); ++i){
        char ch = input[i];
        if ( !((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) ) return "";
    }
    return input;
}

The caller can then check if the return value is empty, if it wants to:

if (myfunc(input).empty())
    // error, do something
else
    // OK, do something else

Which would be better served with a function that returns a bool instead of a std::string:

bool isvalid(const std::string &input){
    if (input.empty()) return false;
    for (int i = 0; i < input.size(); ++i){
        char ch = input[i];
        if ( !((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) ) return false;
    }
    return true;
}

// if you still needed this function for something...
std::string myfunc(const std::string &input){
    if (!isvalid(input)) return "";
    return input;
}

if (!isvalid(input))
    // error, do something
else
    // OK, do something else
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

If you want to return false (or true) then you should change the return type of your function to bool

bool myfunc(std::string input) {
^^^^

Secondly if you mean to return false then that's what you should return

if (!input.size()) return false;
                          ^^^^^

Returning 0 from a boolean function is not an error because 0 will automatically be converted to false, but clearly it's stylistically better to say what you mean.

john
  • 85,011
  • 4
  • 57
  • 81
  • I do understand that, but my return type is std::string(the expected return from the function). Could you suggest what should be the return value for the edge cases if I want to keep the return type of the functions as the string. – Anu Jan 29 '19 at 20:45
  • You're asking to return either a bool or a string from your function? That is possible in some languages but in a *strongly typed* language like C++ it's difficult. Your best bet would be to split your function in two, an initial function that returns true or false, and then a second function that returns a string, but is only called if the first function returns true. – john Jan 29 '19 at 20:48
  • @anu You could return `std::optional`, or throw an exception where you would have returned false. – juanchopanza Jan 29 '19 at 21:08
  • 1
    @anu What is wrong with simply returning a blank string on failure? `return "";` or `return string();` – Remy Lebeau Jan 30 '19 at 00:52
0

I have faced this error. 

The solution to this error is to use string as a stringstream --- Name you to want.Then replace name instead cout and return name.str();

like this

string to_string(){        stringstream ss;     ss<< age << ","<< first_name <<","<<last_name <<","<< standard ;     return ss.str();}