Verify string format with given pattern I'm implementing an auxiliary global function which has to check whether a given string has correct format (i.e., it begins with a letter and only contains letters, numbers or the "_" character).

This function, named ok_tret, will be used in the methods of a couple classes and will help ensure that the attributes are initialized with correct words and the rest of the methods are getting correct words as parameters.

The classes will be used in situations in which incorrect inputs are not frequent. They'll only happen when the user misspells the word, or by ignorance. So my guess is there will be two errors per read at worst.

My first ok_tret proposal returns a bool that tells us whether the given word is correct. This means we'll have to do the cin in the class method and then pass the word to the function. If there's error, then we'll have various function calls, until eventually the functions returns true.

const char *err4 = "ERROR. Init again.";

// Check correctness, return corresponding bool.
bool ok_tret(const string&amp; nom) {
    if (not ((nom[0] &gt;= 'a' and nom[0] &lt;= 'z') or
        (nom[0] &gt;= 'A' and nom[0] &lt;= 'Z'))) {
        cout &lt;&lt; err4 &lt;&lt; endl;
        return false;
    } 
    for (unsigned int i = 1; i &lt; nom.length(); ++i) {
        if (not ((nom[i] &gt;= '0' and nom[i] &lt;= '9') or 
            (nom[i] &gt;= 'A' and nom[i] &lt;= 'Z') or 
            (nom[i] &gt;= 'a' and nom[i] &lt;= 'z') or nom[i] == '_')) {
                cout &lt;&lt; err4 &lt;&lt; endl;
                return false;
        }
    }
    return true;
}


The next proposal also does the cin, so in order to get a correct word there's no need for various function calls.

// Check correctness and cin until nom contains a correct word. Iterative.
void ok_tret(string&amp; nom) {
    bool P = true;
    while (P) {
        if ((nom[0] &gt;= 'a' and nom[0] &lt;= 'z') or 
            (nom[0] &gt;= 'A' and nom[0] &lt;= 'Z')) {
            for (unsigned int i = 1; P and i &lt; nom.length(); ++i)
                if (not ((nom[i] &gt;= '0' and nom[i] &lt;= '9') or 
                    (nom[i] &gt;= 'A' and nom[i] &lt;= 'Z') or 
                    (nom[i] &gt;= 'a' and nom[i] &lt;= 'z') or nom[i] == '_')) 
                    P = false;
        } else P = false; 
        P = !P; 
        if (P) {
            cout &lt;&lt; err4 &lt;&lt; endl;
            cin &gt;&gt; nom;
        }
    }
}


Finally a recursive solution, obviously there will be multiple function calls:

// Check correctness and cin until nom contains a correct word. Recursive.
void ok_tret(string&amp; nom) {
    if (not ((nom[0] &gt;= 'a' and nom[0] &lt;= 'z') or 
        (nom[0] &gt;= 'A' and nom[0] &lt;= 'Z'))) {
            cout &lt;&lt; err4 &lt;&lt; endl;
            cin &gt;&gt; nom;
            ok_tret(nom);
            return;
    }
    for (unsigned int i = 1; i &lt; nom.length(); ++i) {
        if (not ((nom[i] &gt;= '0' and nom[i] &lt;= '9') or 
            (nom[i] &gt;= 'A' and nom[i] &lt;= 'Z') or 
            (nom[i] &gt;= 'a' and nom[i] &lt;= 'z') or nom[i] == '_')) {
                cout &lt;&lt; err4 &lt;&lt; endl;
                cin &gt;&gt; nom;
                ok_tret(nom);
                return;
        }
    }
}


I wanted to know: 


Which proposal looks more natural?
Given the context in which the code will be used, there's no meaningful runtime difference between proposals. But... come on, which one would you choose and why?
If number of errors could be arbitrary (0 to a billion), which one would you choose and why?
I'd instead use the std::isalpha() to check for the alphabets, and for the rest; use isalnum() plus an or condition for the _ character.

Another check, I'd put is whether the input's length is indeed \$ \gt 0 \$. The code then becomes:

// Check correctness, return corresponding bool.
bool ok_tret(const string&amp; nom) {
    if (nom.length() &lt; 1) {
        // handle null strings
        return false;
    }
    if (not (bool) std::isalpha(nom[0])) {
        cout &lt;&lt; err4 &lt;&lt; endl;
        return false;
    } 
    for (unsigned int i = 1; i &lt; nom.length(); ++i) {
        if (not ((bool) std::isalnum(nom[i]) or nom[i] == '_')) {
                cout &lt;&lt; err4 &lt;&lt; endl;
                return false;
        }
    }
    return true;
}