17

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?

13
  • 5
    The issue is return 0; Commented Jan 29, 2019 at 20:41
  • 2
    Also pass the string by const&. Commented Jan 29, 2019 at 20:46
  • 3
    maybe you want to return a std::optional when the function returns either a string or nothing Commented Jan 29, 2019 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! Commented Jan 29, 2019 at 20:48
  • 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. Commented Jan 29, 2019 at 20:56

3 Answers 3

21

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
Sign up to request clarification or add additional context in comments.

Comments

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.

4 Comments

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.
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.
@anu You could return std::optional<std::string>, or throw an exception where you would have returned false.
@anu What is wrong with simply returning a blank string on failure? return ""; or return string();
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();}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.