Length limit of array of characters
My question revolves around the program shown below (environment is Mac Xcode).
#include <iostream>
int main () {
char nameOne [5];
std::cin >> nameOne; // input: BillyBobThorton
std::cout << nameOne; // output: BillyBobThorton
char nameTwo [5] = "BillyBobThorton"; // compile error, initializer string too long
std::cout << nameTwo;
return 0;
}
I have a char array of开发者_运维百科 length 5, so I would expect the maximum amount of characters I could store in this array to be 4 (plus the null terminating char). And this is indeed the case when I attempt to store a string to the nameTwo
variable. However, when I use an array of characters as the variable to store user input, the array length is outright ignored and the array seemingly expands to accomodate the extra characters.
Why is this the case, and is there perhaps a more appropriate way to store user input to an array of characters?
Is there perhaps a more appropriate way to store user input to an array of characters?
Yes! The most appropriate way in C++ is to use std::string
. This will prevent your user overrunning the end of the buffer you've allocated and corrupting your stack. If you only want to display a certain number of characters, you can limit on output (or during some validation routine) using std::string::substr()
. Here's an example.
#include <iostream>
#include <string>
int main ()
{
std::string nameOne;
std::cin >> nameOne; // input: BillyBobThorton
std::cout << nameOne.substr(0, 5); // output: Billy
const std::string nameTwo = "BillyBobThorton";
std::cout << nameTwo.substr(0, 5); // output: Billy
return 0;
}
It doesn't "seemingly expand," rather it unsafely passes the boundaries of your array and can and will cause memory corruption as a result.
There are "safe" functions that will limit the length of the user's input. Have a look at scanf with the length limiter (%xxxs
where xxx is the max length), or scanf_s on Windows.
std::cin does not know the size of the buffer when we use operator>>(char*). It only know that it have to fill a char array starting at the given address. And when it fills a char*, it read the input until it encounter the new-line (\n).
If you want to read anything that the user gives as input, you can use a std::string instead of an array of char (std::cin >> string; or std::getline(std::cin, string); to also remove the new-line from the input buffer).
If you want to limit the number of characters to be read, you should use std::cin.get(char*, size) or std::cin.get(streambuf&, size);
It is always preferable to limit the input length to avoid to read a very long string (a few thousand chars or more).
The most appropriate way in C++ is to use std::string
Expanding on this, it is almost always bad practice to stream from cin into a fixed size buffer, regardless of the size of the buffer. That is what leads to the infamous buffer overflow. The data coming from standard input could be of any length and you should always check that the buffer you are copying into is big enough to hold whatever you want to put into it.
When you use std::cin and std::string checking that the buffer is large enough as well as reallocating it as needed is all taken care of for you.
That being said, there is, of course, a way to restrict how much cin extracts, see How to set maximum read length for a stream in C++?
精彩评论