Creating an error message if user inputs too many characters - c++

I'm pretty new to coding so I apologize if this is trivial. I'm supposed to create an error message when the user enters more characters than my const int SIZE2 array, which is 20 characters.
My array is called major:
>cout << "Enter your major: " << endl << endl;
>48 cin.width(SIZE2);
>49 cin.get(major,SIZE2, '\n');
>50 majorLength = strlen(major);
>51
>52 if(majorLength > SIZE2)
>53 {
>54 cout << "Too many characters, Enter major again: " << endl;
>55 cin.get(major, SIZE2, '\n');
>56 cin.ignore(100, '\n');
>57
>58 }
It's compiling just fine but skipping over my if-statement.

iostream.get() (here invoked as cin.get()) reads an exact number of bytes and then ends. In your case, it will specifically never read more than SIZE2 bytes into major; as a result, if(majorLength > SIZE2) will always be false. Also, if you enter too many bytes, major will only have the first 20 - the rest are truncated. (FWIW, your code is only matching 19 characters right now.)
Note that you probably shouldn't try to do this - there's not really a good way to check the length of a stream before you read it, and if you decide to just read it all and then check its size, you run the risk of overflowing your buffer - assuming it's fixed size.
You can, however, determine if, after reading, the buffer is empty or not. To determine if there is any more input in the buffer beyond SIZE2, you can capture one character with std::cin.get() and then examine this character. If the character is \n, it means there was no more input in the buffer; if it is not, that means the character buffer had too much input in it. This will also trigger if the input is completely blank.
#include <iostream>
int main () {
int SIZE2 = 20;
char str[SIZE2];
char c;
std::cin.get (str, SIZE2+1); // get c-string of 20 chars
std::cin.get(c); //get last buffer character
if(c != '\n') {
std::cout << "bad input!" << std::endl;
}
std::cout << str << std::endl;
return 0;
}
Demo

Related

char array initialization using cin.get()

I am trying something different with cin.get() like given below:
char chArray[30]="character array with size "; //current string size is 25 character with null character
cout<< chArray << sizeof(chArray)<< endl;
cout<< "Now we will try to enter more than 30 character in chArray using cin.get()";
cin.get(chArray,100);
cout<< chArray << endl << sizeof(chArray)<< endl;
output of above code is very strange as given below:
character array with size 30
Now we will try to enter more than 30 character in chArray using cin.get().
The character array size is 30 but we are entering more than 30 using cin.get() but the size is still 30.
How is size of chArray not changing from 30 to the size of the string we entered using cin.get()?
Please explain.
A fixed array is not dynamically sizable. Once the array is declared, it cannot change size (sizeof() is fixed at compile-time). Your code has a buffer overflow that will corrupt surrounding memory if you try to enter more characters than the array can hold. In your example, your array can only hold 30 chars max, but you are telling cin that it can read up to 100 chars (well, 99, plus a null terminator) into the array.
For what you are trying to do, you need to read into a std::string instead of a char[] array. The size() of a std::string can change dynamically at runtime, eg:
#include <string>
std::string str = "character string with size ";
std::cout << str << str.size() << std::endl;
std::cout << "Now we will try to enter more than 30 character in str using cin";
std::cin >> str; // or: std::getline(std::cin, str);
std::cout << str << std::endl << str.size() << std::endl;
How is size of chArray not changing from 30 to the size of the string we entered using cin.get()?
Arrays in C++ have fixed size. They are created on the stack with a fixed size given by the programmer. That means you give them a specific size and it is known to the compiler at compile time. This size does not change. Ever.
If you write more characters into the array than the size for example writing 100 characters in an array of size 30, it is called buffer overflow or buffer overrrun. It basically means you crossed the boundary i.e., the fixed size set, which is 30 in this case.
The other characters entered (after the limit of 30) can go anywhere in the memory because it is undefined where they will go. If you try to print this array, your program will terminate with an error:
*** stack smashing detected ***: terminated
The error in this particular case means you tried to put more data into the stack than it's capacity.
However, we have string in C++, which you can use if you want a container which changes its size as required. Example:
std::string mystr;
std::cout << "Mystr size before: " << mystr.size() << '\n';
std::getline (std::cin, mystr);
std::cout << "Mystr size after: " << mystr.size() << '\n';

console not returning expected number of characters in cin buffer

I am creating a console version of "Bull Cow Game". In the game, the user has a certain number of tries to guess what the secret word is. Every time they guess, the program returns the number of "Bulls" and "Cows" they guessed correctly. The user gets a "Bull" for every character that they guess in the right place and a "Cow" for every character that they guess correctly but is not in the right place.
My problem is in my getGuess() function. In the do-while loop, the program is supposed to loop if the user inputs anything other than the number of characters in "answer". When I run my program, I get some unexpected and confusing results:
1) No matter what I input for the first "guess", the program tells me that cin's gcount() is 0 or 1 characters after setw(). I could input 50 characters or 2 and the program would output the same result. If the gcount is 1, then this counts as one of the allotted guesses which is an undesirable result. If the cin.gcount() is 0, the program correctly does not count the guess as valid but I am still confused as to why the cin.gcount() is 0 at all.
2) If I change the number of characters in my guess from the previous guess, the program tells me that the cin.gcount() is whatever the cin.gcount() was after the previous guess instead of after the current guess. This is also an undesirable result since if the user decides to input the correct number of characters, the program will not accept the user's guess as valid.
I am confused as to why this is happening since isn't cin.ignore() supposed to dump all of the extraneous characters that setw() doesn't accept? Why would the number of characters in the cin buffer carry over from one guess to the other?
Here is the function in question:
string getGuess()
{
string guess = "";
const int MAX_LENGTH = 4;
/*ensures that "guess" is the same length as answer. This
will make it so that the program avoids comparing "guess"
to "answer" if "guess" has more characters than "answer".
This do-while loop also ensures that a user can't overflow
the cin buffer by theoretically inputting more characters
than the buffer could contain*/
bool endLoop = false;
do {
cout << "Enter a word containing exactly " << MAX_LENGTH << " characters: ";
cin >> setw(MAX_LENGTH) >> guess;
cout << "cin.gcount() after setw(): " << cin.gcount() << " characters" << endl;
/*ensures that the only character in the cin is '\n'. Otherwise
do-while loop continues*/
if (cin.gcount() != 1)
{
cout << "Invalid number of characters. Please input exactly " << MAX_LENGTH
<< " characters" << endl;
}
else
{
endLoop = true;
}
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "cin.gcount() after cin.ignore(): "
<< cin.gcount() << " characters" << endl;
cout << "guess: " << guess << endl;
cout << endl;
} while ( endLoop == false );
cout << endl;
return guess;
}
Note: This was compiled with Microsoft Visual C++, ISO standard c++17.
A couple of misunderstandings I think
1) gcount only tells you how many characters have been read after an unformatted input operation, cin >> guess is not an unformatted input operation.
2) setw on input does not limit the numbers of characters read. If less than the specified width characters are read then the input is padded to make it equal the given width, but it does not stop more characters being read.
Your code is too tricky, forget about fancy I/O operations, do it the straightforward way. Just read a line of characters into a string using getline and check if the characters entered are what you expect. For instance remove the spaces at the beginning and end of that string, then check for internal spaces and finally check if the string is the length you require.

Why is part of my code being skipped and not letting me enter input?

Why does my code skip the last question when I put to much info in for the fist one? What am I doing wrong?
const int SIZEC =31;
char phrase[SIZEC];
cout << " Provide a phrase, up to 30 characters with spaces. > " << endl;
cin.getline(phrase, SIZEC);
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << " The phrase is: " << phrase << endl;
cout << endl;
cout << " Using sring Class Obects " << endl;
cout << "--------------------------" << endl;
cout << endl;
string leter;
cout << " Provide a single character > " << endl;
cin >> leter;
cout << " The single character is: " << leter << endl;
cout << endl;
If the code before this is needed tell me and I'll add it.
Use std::string::resize as a workaround.
string phrase;
getline(cin, phrase);
phrase.resize(30); // phrase will be reduced to 30 chars
string letter; // better to use char letter
cin >> letter;
letter.resize(1);
The main problem is that getline behaves differently in two cases:
If at least SIZEC characters are read and there is no newline character among them (e.g. there should be at least SIZEC+1 bytes to store the data read), it stops reading and sets so-called failbit status bit on the stream, which means "I have failed to read something, so input stream is probably incorrect". Quoting cplusplus.com:
The failbit flag is set if the function extracts no characters, or if
the delimiting character is not found once (n-1) characters have
already been written to s.
If newline character is encountered, failbit is not set and the newline character is succesfully read and ignored by getline.
What happens next is more interesting: extraction functions (all of them, I assume) fail immediately if the input stream is bad() (that is, either failbit, badbit, or eofbit are set on the stream). In particular, if previous extraction operation failed, all subsequent will fail as well. So, basically, if first line of the input cannot be fitted in your phrase array, then cin becomes "bad" and all further read operations do nothing.
You can override that behavior by manually resetting the failbit after calling getline like this:
cin.clear();
Following read operations will succeed until another one fails.
In your particular case, I assume that you want to read the first line regardless of the length, and then a second line. I that case, I think you
should to first check whether getline failed (by checking cin.failbit() or cin.good()) and then either do nothing (if it did not and there is no need in reading extra newline) or resetting the failbit and ignoring characters till the first newline. Something like this:
#include <iostream>
#include <limits>
#include <string>
using namespace std;
int main() {
char buf[5];
cin.getline(buf, sizeof buf);
if (!cin) { // operator ! is overloaded for `istream`, it's equal to `good()`
// If stream is bad: first line of the input was truncated,
// and following newline character was not read.
// Clear failbit so subsequent read operations do something.
cin.clear();
// Read remaining of the first line.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
// At this point, first line of the input is consumed
// regardless of its length
int x;
cin >> x;
cout << "String: |" << buf << "|\n";
cout << "x: " << x << "\n";
}
You can read more on StackOverflow here and there.
However, if there is no reason to use C-style string together with istreams, I'd suggest you using string and std::getline instead (like in Shreevardhan's answer); it will produce cleaner code and there will be no extra cases.

What is the length of my array?

Hello everyone I'm having trouble with strlen and arrays, it keeps saying my string length is only one? If anyone could help it would be great here's my code:
#include <iostream>
using namespace std;
#include <cstring>
int main()
{
char word1[20];
int len = strlen(word1);
cout << "enter a word!\n";
cin.get(word1, 20, '\n'); cin.ignore(50,'\n');
cout << len;
}
Just read the back and forth in the comments, updating my answer to try and give some more intuition behind what's going on.
char word1[20]; Sets a place in your computer's memory that can eventually be filled by data up to 20 characters. Note that this statement alone does not "clear" the memory of whatever is currently there. As sfjac has pointed out, this means that literally anything could be in that space. It's highly unlikely that whatever is in this space is a character or anything your code could readily understand.
int len = strlen(word1); Creates an integer and sets it equal to the value of the number of characters currently in word1. Note that, because we have not specified any content for word1, you're taking the length of whatever happened to be in that memory space already. You've limited the maximum to 20, but in this case, whatever data junk is in there is giving you a length of 1.
cout << "enter a word!\n"; Prompt the user for a word
cin.get(word1, 20, '\n'); cin.ignore(50,'\n'); Get the word, store it in word1. At this point, word1 is now defined with actual content. However - you've already defined the variable len. The computer does not know to automatically redefine this for you. It follows the steps you provide, in order.
cout << len; Print the value stored in len. Because len was created prior to the user entering their data, len has absolutely nothing to do with what the user entered.
Hope this helps give you some intuition that will help beyond this one question!
#Chris is correct but perhaps a small explanation. When you declare a character array like char word1[20] on the stack, the array will not be initialized. The strlen function computes the length of the array by counting the number of characters from the address of word1 to the first null byte in memory, which could be pretty much anything.
I highly recommend using std::string for text.
If you must use character arrays:
Define a named identifier for the capacity.
Define the array using the named identifier.
The capacity should account for a terminating nul, '\0', character to
mark the end of the maximum text length.
Using the above guidelines you have the simple program:
int main(void)
{
std::string a_word_string;
std::string line_of_text_string;
const unsigned int c_string_capacity = 32U;
char c_string[c_string_capacity];
// The std::string functions
cout << "Enter some text: ";
getline(cin, line_of_text_string); // read a line of text
cout << "\nEnter a sentence: ";
cin >> a_word_string;
cin.ignore(10000, '\n'); // Ignore remaining text in the buffer.
// The C-style string functions
cout << "Enter more text: ";
cin.read(c_string, c_string_capacity);
c_string[c_string_capacity - 1] = '\0'; // Insurance, force end of string character
cout << "You entered " << (strlen(c_string)) << " characters.\n";
return EXIT_SUCCESS;
}
The std::string class is more efficient and can handle dynamically size changes.
The length of the array is the value of c_string_capacity which was used when defining the array.
The length of the text in the array is defined as strlen(c_string), which is the number of characters before the terminating nul is found.
You have to calculate len after reading in word1, otherwise you are left with undefined behaviour.
char word1[20];
cout << "enter a word!\n";
cin.get(word1, 20, '\n'); cin.ignore(50,'\n');
int len = strlen(word1);
cout << len;
It's a good idea to always initialize objects when you declare them. Since objects inside of a scope are not guaranteed to be initialized.
In C++11 for example, you can do this:
char arr[10]{}; // this will initialize the objects in the array to default.
char arr[10]{0}; // the same.

How do I fill an array with characters from user input, while counting how many array indexes have been used? (using cin.get)

I need to use the get function and count how many indexes have been filled I have been running into a couple problems.
It seems that using cin.get in this way only allows me to fill the array and doesn't allow me to count how many variables in the array have been filled:
#include <iostream>
int main()
{
char line[25];
cout << " Type a line terminated by enter\n>";
cin.get( line, 25 );
}
I have a feeling that I need to use a for loop such as the one below, but the problem with this is it doe not end with enter, the user has to fill the whole array and I need to be able to enter any amount of characters under the limit. Also the example did not use sentinel value, so though it would seem to solve this, it doesn't seem to be the solution.
void fill_array(char array[], int max_count, int& num_used)
{
char input;
int index = 0;
cout << "Enter a text string to test" << endl;
for( index = 0;index < max_count; index++)
{
cin.get(input);
array[index] = input;
num_used++;
}
}
You can use gcount to get the number of characters read byt the last unformatted operation, like cin.get.
char line[25];
cout << " Type a line terminated by enter\n>";
cin.get( line, 25 );
std::streamsize read_chars = cin.gcount();