How to check the length of an input? (C++) - c++

I have a program that allows the user to enter a level number, and then it plays that level:
char lvlinput[4];
std::cin.getline(lvlinput, 4)
char param_str[20] = "levelplayer.exe "
strcat_s(param_str, 20, lvlinput);
system(param_str);
And the level data is stored in folders \001, \002, \003, etc., etc. However, I have no way of telling whether the user entered three digits, ie: 1, 01, or 001. And all of the folders are listed as three digit numbers. I can't just check the length of the lvlinput string because it's an array, so How could I make sure the user entered three digits?

Why not use std::string?
This makes storage, concatenation, and modification much easier.
If you need a c-style string after, use: my_string.c_str()
Here is a hint: To make your input 3 characters long, use std::insert to prefix your number with 0's.

You are really asking the wrong question. Investigate the C++ std::string class and then come back here.

Eh? Why do they need to enter 3 digits? Why not just pad it if they don't? If you really want to check that they entered 3 digits, use strlen. But what I recommend you do is atoi their input, and then sprintf(cmd, "levelplayer.exe %03d", lvlinput_as_integer)

Here's how you could do this in C++:
std::string lvlinput;
std::getline(std::cin, lvlinput);
if (lvlinput.size() > 3) { // if the input is too long, there's nothing we can do
throw std::exception("input string too long");
}
while (lvlinput.size() < 3) { // if it is too short, we can fix it by prepending zeroes
lvlinput = "0" + lvlinput;
}
std::string param_str = "levelplayer.exe ";
param_str += lvlinput;
system(param_str.c_str());
You've got a nice string class which takes care of concatenation, length and all those other fiddly things for you. So use it.
Note that I use std::getline instead of cin.getline. The latter writes the input to a char array, while the former writes to a proper string.

What do you mean you can't check the length of the string? getline generates a NULL terminated c-string so just use strlen(lvlinput).

Neil told you where you should start, your code might look like this.
std::string level, game = "levelplayer.exe ";
std::cout << "Enter the level number : ";
std::cin >> level;
if(level.size() != 3)
{
// Error!
}
else
{
// if you have more processing, it goes here :)
game += level;
std::system(game.c_str());
}

You can check the length of your NULL terminated string that getline returns by using:
int len = strlen(lvlinput);
This works because getline returns a NULL-terminated string.
However, this is besides the point to your problem. If you want to stay away from std::string (and there isn't any particular reason why you should in this case), then you should just convert the string to an integer, and use the integer to construct the command that goes to the system file:
char lvlinput[4];
std::cincin.getline(lvlinput, 4);
char param_str[20];
snprintf(param_str, 20, "levelplayer.exe %03d", atoi(lvlinput));
system(param_str);

Related

Reading text from standard input till meeting one of exact characters, saving it, then continuing reading until end of line

I want to deal with basic operations (+, -, *, /) on big numbers. My standard input line will look like 12345678987654322+12334675432142654765786.
So I want to read first number into one string variable, then sign of operation into another variable and then to continue reading until end of line.
I was thinking about something like this, but it just skips "+" and I have no idea how to include 4 conditions here (+, -, *, /).
std::string firstNumber;
std::string secondNumber;
std::getline(std::cin, firstNumber, '+');
std::getline(std::cin, secondNumber);
Read the whole line into a string.
Loop over the string and extract character by character. As long as the character is a digit, put it into the first "number" variable. If it's a non-digit, then check if it's a valid operator, and report failure if it isn't. Extract the second number, character by character, into the second "number" variable.
This way you can more easily detect errors, and also handle spaces between the numbers and the operator.
You can (and I recommend that you do) put the number-extraction into a separate function so you don't have to duplicate the code for it.
You need to do some work instead of relying on standard functions to do the work for you. What you want can easily be accomplished by reading one character at a time and using a couple of loops
#include <cctype>
#include <string>
#include <iostream>
std::string firstNumber, secondNumber;
char operation, ch;
ch = std::cin.get();
while (isdigit((unsigned char)ch))
{
firstNumber += ch;
ch = std::cin.get();
}
operation = std::cin.get();
ch = std::cin.get();
while (isdigit((unsigned char)ch))
{
secondNumber += ch;
ch = std::cin.get();
}
This code does no error checking at all, which in a real world program would be a serious problem.
What you are being asked to do is a parsing problem. It's a very common thing to do and there is lots and lots of literature on different ways to do parsing.

how to force user to input exactly 8 characters into string

how can I limit a user to input 8 characters into string?
can something like this work?
string MyString;
getline(std::cin, MyString, 8);
or maybe there is a different idea to accomplish it
thanks in advance
clarification:
I want to enable the user to input up to 8 characters in the string, but he may enter less.
You can use a loop..
while (MyString.length() != 8) {
std::cout << "Enter exactly 8 characters:";
getline(std::cin, MyString);
}
its hard to think this will help considering my experience (1mnth!)
at codecademy.com in the "Python" language one might say something like:
my_string = "jackie"
len(my_string)
#would print 5
if my_string is <= ..... # if my string is greater or equal to print the following
print "name is too long "
Hope that generated something other than disgust
sincerely dedicated noobie
There is a difference between requesting 8 characters from the User and preventing the User from entering more than 8.
Requesting 8 from User
You can request 8 characters from the User, but the User is allowed to enter as many characters as the User wants until a newline character is entered. This is the behavior of the standard console input.
The console has buffered the all the characters. Depending on the extraction method, you will be extracting 8 characters from the input buffer into your variable. The remaining characters are still in the buffer.
Preventing User from entering more than 8
This is typically used in entering passwords. The standard C++ input facilities cannot help here.
You will need platform specific control of the input source. You will need to read each character, test for a newline and optionally echo back either the character, a uniform character like '*', or not display any characters.
Since it is platform specific, look up the API for your platform.
#include <iostream>
#include <string>
int main(){
std::string str;
bool cStr = true; //check string
while (cStr){
std::getline(std::cin, str);
if (str.size() <= 8) cStr = false;
}
}
You can add a bool object to test your string using an if-statement. If the string size is less than or equal to 8, it will then advert the bool statement to false allowing the exit of the while loop.

C++: Checking whether a string character is a digit using isdigit. .

I am reading input for my program in a loop using getline.
string temp(STR_SIZE, ' ');
string str_num(STR_SIZE, ' ');
...
getline(cin, temp, '\n');
After which, I use a function to find the next delimiter(white space) and assign all the characters before the white space to str_num. Looks something like this:
str_num.assign(temp, 0, next_white_space(0));
I have verified that this works well. The next step in my solution would be to convert str_num to an int(this part also works well), but I should check to make sure each character in str_num is a digit. Here's the best of what I've tried:
if(!isdigit(str_num[0] - '0')) {
cout << "Error: Not an appropriate value\n";
break; /* Leave control structure */
}
For some reason, This always prints the error message and exits the structure.
Why is that?
I've used operator[] for string objects before, and it seemed to work well. But, here, it's totally messing me up.
Thanks.
std::isdigit takes a char's integer value and checks it.
So, remove the - '0' and just pass str_num[index] to isdigit().
Note: because this function comes from C, the old style of treating chars as integers shows through in the method taking an int. However, chars can promote to int values, so a char becomes an int just fine and this works.

Convert string to int and get the number of characters consumed in C++ with stringstream

I am new to C++ (coming from a C# background) and am trying to learn how to convert a string to an int.
I got it working by using a stringstream and outputting it into a double, like so:
const char* inputIndex = "5+2";
double number = 0;
stringstream ss(inputIndex);
ss >> number;
// number = 5
This works great. The problem I'm having is that the strings I'm parsing start with a number, but may have other, not digit characters after the digits (e.g. "5+2", "9-(3+2)", etc). The stringstream parses the digits at the beginning and stops when it encounters a non-digit, like I need it to.
The problem comes when I want to know how many characters were used to parse into the number. For example, if I parse 25+2, I want to know that two characters were used to parse 25, so that I can advance the string pointer.
So far, I got it working by clearing the stringstream, inputting the parsed number back into it, and reading the length of the resulting string:
ss.str("");
ss << number;
inputIndex += ss.str().length();
While this does work, it seems really hacky to me (though that might just be because I'm coming from something like C#), and I have a feeling that might cause a memory leak because the str() creates a copy of the string.
Is there any other way to do this, or should I stick with what I have?
Thanks.
You can use std::stringstream::tellg() to find out the current get position in the input stream. Store this value in a variable before you extract from the stream. Then get the position again after you extract from the stream. The difference between these two values is the number of characters extracted.
double x = 3435;
std::stringstream ss;
ss << x;
double y;
std::streampos pos = ss.tellg();
ss >> y;
std::cout << (ss.tellg() - pos) << " characters extracted" << std::endl;
The solution above using tellg() will fail on modern compilers (such as gcc-4.6).
The reason for this is that tellg() really shows the position of the cursor, which is now out of scope. See eg "file stream tellg/tellp and gcc-4.6 is this a bug?"
Therefore you need to also test for eof() (meaning the entire input was consumed).

How do I get the next token in a Cstring if I want to use it as an int? (c++)

My objective is to take directions from a user and eventually a text file to move a robot. The catch is that I must use Cstrings(such as char word[];) rather than the std::string and tokenize them for use.
the code looks like this:
void Navigator::manualDrive()
{
char uinput[1];
char delim[] = " ";
char *token;
cout << "Enter your directions below: \n";
cin.ignore();
cin.getline (uinput, 256);
token=strtok(uinput, delim);
if(token == "forward")
{
int inches;
inches=token+1;
travel(inches);
}
}
I've never used Cstrings I've never tokenized anything before, and I don't know how to write this. Our T.A.'s expect us to google and find all the answers because they are aware we've never been taught these methods. Everyone in my lab is having much more trouble than usual.
I don't know the code to write but I know what I want my program to do.
I want it to execute like this:
1) Ask for directions.
2) cin.getline the users input
3) tokenize the inputed string
4) if the first word token == "forward" move to the next token and find out how many inches to move forward then move forward
5) else if the first token == "turn" move to the next token. if the next token == "left" move to the next token and find out how many degrees to turn left
I will have to do this for forward x, backward x, turn left x, turn right x, and stop(where x is in inches or degrees). I already wrote functions that tell the robot how to move forward an inch and turn in degrees. I just need to know how to convert the inputted strings to all lowercase letters and move from token to token and convert or extract the numbers from the string to use them as integers.
If all is not clear you can read my lab write up at this link: http://www.cs.utk.edu/~cs102/robot_labs/Lab9.html
If anything is unclear please let me know, and I will clarify as best I can.
To convert to lower, you can use tolower. It operates one character at a time, so you need a simple loop.
To parse a string into an integer, you can use strtoll.
Move to the next token just means call strtok again (in this case inside an if statement).
To convert a string to lower case, you can use tolower(). tolower works on single chars, so you have to loop through your string and apply it to every char.
To convert a string to a number, use strtol, strtoul, or other related functions.
you simply call strtok again to get the next token.
You will probably need valid input checks i.e. check that there is a next value
typically you would use a while loop
ex
token=strtok(uinput, delim);
while (token != NULL)
{
// use token
//go to next token
token=strtok(uinput, delim);
}
While i can't say something about CString, I spotted a stack overflow fault in your code:
{
char uinput[1]; // <- Here you define a one byte large buffer on the stack
char delim[] = " ";
char *token;
cout << "Enter your directions below: \n";
cin.ignore();
cin.getline(uinput, 256); // and here you put up to 256 bytes into it
I would sugest:
{
const int bufSize = 42; // since 42 is the awnser to everything
char uinput[bufSize];
// ...
cin.getline(uinput, bufSize);