Anu
Anu

Reputation: 3440

How to fix 'std::logic_error' what(): basic_string::_M_construct null not valid error?

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?

Upvotes: 17

Views: 131243

Answers (3)

Muhammad Ansar
Muhammad Ansar

Reputation: 1

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();}

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 596352

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

Upvotes: 20

john
john

Reputation: 87959

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.

Upvotes: 0

Related Questions