restricting string input to numbers and letters only

Pages: 12
Hi all, in a part of a program I have to restrict user to input only letters and digits in a string, so I did this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 string name;
bool test;
do {
  test = true;
  cout << "\n\n\tEnter name: ";
  cin >> name;
   for (unsigned short n = 0; n <= name.length()-1; n++){
    if (!(isdigit(name.at(n)) || isalpha(name.at(n))))
    test = false;
}

    if (!test)
    cout << "\n\n\t!ERROR!\n\n";
}
while(!test);


it looks pretty simple and straight forward but unfortunately it accepts space as a valid choice (which I'm not allowed).
And if I stick it into my program (I kept it separately so I don't mess up to much) and I input space it just executes all the loop at once and the program is finished.

So I added this:

1
2
 if (isspace(name.at(n)))
        test = false;


to see if that will help but it does absolutely nothing..

To finish my way to long post I will just say this:
HELP PLEASE!
it accepts space as a valid choice
Actually it is not. operator>> cannot extract whitespaces on default settings. It will stop as soon as it encounters one. Anything after it will remain in input buffer for subsequent reads. So there is no possibility that there would be spaces in your string, so this test does nothing.

example:
1
2
3
4
5
std::string s1, s2;
std::cin >> s1;
std::cout << "S1 is: " << s1 << '\n';
std::cin >> s2;
std::cout << "S2 is: " << s2 << '\n';
Enter string with space in the middle on first prompt and see what happens.
If I want 'space' to be recognized I need to getline!!!!!
So obvious, that was my blond moment of the day...
Thank you
now my program runs for as long as this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<iostream>
#include<iomanip>

using namespace std;

int main ()
{
     unsigned short numJudges, numCeleb;
     float score, addScore, finalScore = 0, min, max, max2=0;
     string name, winner;
    do {
     cout << "\n\n\tEnter number of judges: ";
     cin >> numJudges;
     if (numJudges < 3 || numJudges > 6)
        cout << "\n\n\tERROR! Number of judges must be between 3 and 6" << endl;
    }
     while (numJudges < 3 || numJudges > 6);


    do {
     cout << "\n\n\tEnter number of paricipants: ";
     cin >> numCeleb;
     if (numCeleb < 10 || numCeleb > 15)
        cout << "\n\n\tERROR! Number of participants must be between 10 and 15" << endl;
    }
    while (numCeleb < 10 || numCeleb > 15);


     for (unsigned short i = 1; i <= numCeleb; i++){


bool test;
do {
        test = true;
            cout << "\n\n\tEnter name of celebrity " << i << " : ";
            getline (cin, name, '\n');
            for (unsigned short n = 0; n <= name.length() - 1; n++){
                if(!(isdigit(name.at(n)) || isalpha(name.at(n))))
                test = false;
            }
                if (!test)
                cout << "\n\n\tERROR! Name can consist of letters and numbers only.\n";
}
while (!test);


it goes as far as asking for the name and then get : terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at

any idea why? it works when I keep that part of a program separate so I just copied it to my main program but then it crashes..
First problem (crash): n <= name.length() - 1 should be canonical n < name.length() 
Second problem (getline does not get proper input): http://stackoverflow.com/a/21567292
In short: std::getline(std::cin >> std::ws, name);
Last edited on
I think I've gotten this error before. Like an array, if you go pass the amount of elements an array, you're going to go out of bounds. So I recommend you check what's going with one of your strings.
Last edited on
I changed this to n < name.length () but it didn't help.
I also checked the link you gave above but i just don't get it.
I'm all new to this and we just had like 2 classes on string and that was the only way to getline I know.
But anyway I copied what you gave me there and this time I could actually put in the name and then I got the same 'terminate...'
I changed this to n < name.length () but it didn't help.
Do you still get crash? Same error message?

I also checked the link you gave above but i just don't get it.
That is why I wrote In short line with needed changes to getline
Last edited on
Ok I think I've found the problem. This is a cin and getline problem. Your program is skipping the input(particularly the name input). Here is an example with an output.

1
2
3
4
5
6
7
8
9
10
11
12
    string str;
    int x;

    cout << "Enter integer. ";
    cin >> x;

    cout << "Enter string. ";
    getline(cin, str, '\n');

    cout << endl;

    cout << x << " " << str << endl;



Enter integer. 10
Enter string.
10

Process returned 0 (0x0)   execution time : 1.565 s
Press any key to continue.


So you see, your program is skipping your input. This means that your string is empty.

There are many ways to fix this.

first try to use cin.ignore.

If that doesn't work,try cin.ignore(numericlimit<streamsize>::max(, '\n'); // Probably spelled this function but it's in the limits header file so you can look it up.

if that doesn't work, then use a dummy variable to eat up the input buffer.

There are more possible courses of action that you can take to fix this problem but these are the ones I mainly use.
Last edited on
Yes I get exactly the same error message. And I did copy your line, but the only think that changed was that this time I was able to input the name and then I got the same error.

deathslice how come str outputs the same as x?

I'm sorry if I'm a bit of a pain, but I am a true beginner and loads of things do not make any sense to me. You would think that if I get assignment, I shouldn't be expected to do anything different than I learned in class, but now they forgot to tell me that there are different ways of getting a line..
Can you post whole code and give an example of input?
first i input number of judges (form 1 to 6) then number of participants (from 10 to 15)
and then I need to input a name of participant

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<iostream>
#include<iomanip>


using namespace std;

int main (){
     unsigned short numJudges, numCeleb;
     float score, addScore, finalScore = 0, min, max, max2=0;
     string name, winner;
    do {
     cout << "\n\n\tEnter number of judges: ";
     cin >> numJudges;
     if (numJudges < 3 || numJudges > 6)
        cout << "\n\n\tERROR! Number of judges must be between 3 and 6" << endl;
    }
     while (numJudges < 3 || numJudges > 6);


    do {
     cout << "\n\n\tEnter number of paricipants: ";
     cin >> numCeleb;
     if (numCeleb < 10 || numCeleb > 15)
        cout << "\n\n\tERROR! Number of participants must be between 10 and 15" << endl;
    }
    while (numCeleb < 10 || numCeleb > 15);


     for (unsigned short i = 1; i <= numCeleb; i++){


bool test;
do {
        test = true;
            cout << "\n\n\tEnter name of celebrity " << i << " : ";
            getline (cin, name, '\n');
            for (unsigned short n = 0; n <= name.length(); n++){
                if(!(isdigit(name.at(n)) || isalpha(name.at(n))))
                test = false;
            }
                if (!test)
                cout << "\n\n\tERROR! Name can consist of letters and numbers only.\n";
}
while (!test);

            addScore = 0,
            min = 6,
            max = 0;

            for (unsigned short a = 1; a <= numJudges; a++){
                do {
                    cout << "\n\n\tEnter score from judge number " << a << " : ";
                    cin >> score;
                    if (score < 0 || score > 6)
                        cout << "\n\n\tERROR! Score must be between 0 and 6." << endl;
                    else if ((((int) (score * 100.0)) % 10) != 0 && ((int) (score * 100.0) % 10) != 9)
                        cout << "\n\n\tERROR! Score can have only one deciamal place" << endl;
                }
                while ((score < 0 || score > 6) || (((int) (score * 100.0)) % 10) != 0 && ((int) (score * 100) % 10) != 9);

                    if (score > max)
                        max = score;

                    if (score < min)
                        min = score;

                        addScore+=score;
                }


                    finalScore = (addScore - max - min) / (numJudges - 2);

                    if (i==1){

                        max2=finalScore;
                        winner=name;
                    }

                    else if(max2<finalScore){

                             max2=finalScore;
                             winner=name;
                           }



                    cout << "\n\n\tFinal score is " << finalScore << endl;
         }

          cout << setw(51) << "And the winner is\n\n" << setw((80+winner.length())/2) << winner << "\n\n"<< setw(42) << max2 << endl;

           return 0;
    }
Last edited on
ebunca, str doesn't output the same thing as x(a string can't accept an integer unless you parse it). You can test it out if you want to see for your self. Maybe after you do that, you'll understand your problem better.

In essence, once you enter in a value for x, the input buffer for the getline function gets eaten up and skipped; outputting an empty string.

*Important---Why is your for loop missing a curly bracket( } ) on line 29?
Last edited on
You did not fix things I posted about:
1
2
getline (cin >> ws, name);
for (unsigned short n = 0; n < name.length(); n++) {


I did not check line 59, but if there would some problems with it, consider using parentheses to set orde of evaluation.
Last edited on
MiiNiPaa I did change them but because I see any improvement I changed it back, the reason I didn't see the improvement is (haha I feel so silly) I actually put in std:: newbies right?

I appreciate you putting up with me, it works now. Thank you for putting your time in it.

death I think I know what your saying I did try it I just misinterpreted it. I see in only puts out x and nothing for string. So is the 'cin >> sw' a normal solution, or there is more surprises waiting for me related to strings.

my for loop closes on line 88 btw

Thanks again
std is not the problem here. It is <= you left was giving you problems.
And yes there is a problem with line 59, but I think I have the solution...
Just as I suspected. I ran your code on c++ shell and as soon as I got to line 36, the program terminated because it skipped that line of code. That is another problem you have beside the one at line 59.
Last edited on
MiiNiiPaa fixed line 36 for me, it is fine now.
I appreciate your input, I would never guess that the program would just skip the line. We only did programs with like 1 input of string and than manipulate it. So that's good to know.
you sure? run it on c++ shell(the little icon above your code to the far right).

Also, your program is giving me a warning that suggests you put parentheses around '&&' within '||' [-Wparentheses].
Last edited on
Pages: 12