Validate the length of a char * taken from std::cin - c++

I have a pointer called char * panimal_name. This pointer should only be able to take in 20 characters and if the user enters more, it must ask the user to re-enter.
I've tried counting the characters in the stream and also using strlen(), however I'm still having problems.
cout << "Enter Animal Name: ";
cin.ignore();
cin.getline(panimal_name, 20);
Any help would be appreciated.
EDIT: Well I only want it to take at most 20 characters from the user. If that 20 is exceeded it should then ask the user to re-enter valid input. However in this setup, it now messes up the stream for my next inputs. The reason I'm using this, rather than a std::string, is that I'm learning pointers at the moment.
P.S. I know a string would probably be better in this situation for ease of use.

According to MSDN:
If the function extracts no elements or _Count - 1 elements, it calls
setstate(failbit)...
You could check for that failbit to see if the user entered more data than the buffer allows?

You can use c++ methods..
std::string somestring;
std::cout << "Enter Animal Name: ";
std::cin >> somestring;
printf("someString = %s, and its length is %lu", somestring.c_str(), strlen(somestring.c_str()));
you can also use more c++ methods
std::string somestring;
std::cout << "Enter Animal Name: ";
std::cin >> somestring;
std::cout << "animal is: "<< somestring << "and is of length: " << somestring.length();
I guess you could do something with cin to a stringstream to get around the way that cin exctract works.

Consider the following program:
#include <iostream>
#include <string>
#include <limits>
// The easy way
std::string f1() {
std::string result;
do {
std::cout << "Enter Animal Name: ";
std::getline(std::cin, result);
} while(result.size() == 0 || result.size() > 20);
return result;
}
// The hard way
void f2(char *panimal_name) {
while(1) {
std::cout << "Enter Animal Name: ";
std::cin.getline(panimal_name, 20);
// getline can fail it is reaches EOF. Not much to do now but give up
if(std::cin.eof())
return;
// If getline succeeds, then we can return
if(std::cin)
return;
// Otherwise, getline found too many chars before '\n'. Try again,
// but we have to clear the errors first.
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n' );
}
}
int main () {
std::cout << "The easy way\n";
std::cout << f1() << "\n\n";
std::cout << "The hard way\n";
char animal_name[20];
f2(animal_name);
std::cout << animal_name << "\n";
}

Use a larger buffer for user input and check for the last element of your buffer.

Related

How to only accept character on c++

In my program, when the user is prompted for an employee's name, the system prompts him to re-enter his name if he enters a number or only a space. How do I put a requirement decision in parentheses in a while loop, here's my code.
std::string NAME;
std::cout << "Please enter the name: " << std::endl;
std::cin >> NAME;
while (NAME.length() == 0) {
std::cout << "Your input is not correct. Please re-enter your name" << std::endl;
std::cin >> NAME;
}
I'm only going to restrict the input to not being empty, but I don't know how to get the user to only allow characters to enter.
Thank you all.
You can use std::all_of on the string defined in algorithm header file. It should be used with appropriate predicate (isalpha for your case defined in cctype header file). Try this:
#include <iostream>
#include <algorithm>
#include <cctype>
int main()
{
std::string NAME;
std::cout << "Please enter the name: " << std::endl;
while (std::getline(std::cin, NAME)) {
if (NAME.length() == 0)
{
std::cout << "Your input is not correct. Please re-enter your name" << std::endl;
}
// This will check if the NAME contains only characters.
else if (std::all_of(NAME.begin(), NAME.end(), isalpha))
{
break;
}
else {
std::cout << "Only characters are allowed:" << std::endl;
}
}
}
Every character has an ASCII code. Use an if condition to check if an input character falls between the ASCII codes for the English alphabets. ASCII Table. You can convert a character to its ASCII code by simply type-casting it as an integer.
Example: For a character array "ARR", having data: "apple"; doing the following will give you "97".
std::cout << (int)ARR[0] << std::endl;

Weird output at the end of string in Ubuntu terminal

I was trying C++ in Ubuntu terminal. I am getting weird symbols at the end of strings.(This also happened in the past in Codeblocks for Ubuntu but everything worked fine in Codeblocks Windows).
Here is the code:
#include <iostream>
using namespace std;
int main()
{
char name[20];
cout << "\nEnter name: ";
cin.getline(name, 20);
cout << "\nHello ";
cout.write(name, 20);
return 0;
}
Output:
Enter name: Yash
Hello Yash�#��Fy
I have checked other threads with the same problem. All of them had assignment problems where the users did not add '\0' at the end. But here I am doing no such thing. Then why do I get these characters at the end?
cout.write(name, 20);
will (try to) write exactly 20 characters, it will not check for '\0'. You can check such things in your favorite reference.
If you really want to use a char[] for this, you should just write
cout << name;
That will check for the terminating character.
However, it would be better to just ditch the C-style strings and move to std::string instead:
int main () {
std::string name;
std::cout << "\nEnter name: ";
std::getline(std::cin, name);
std::cout << "\nHello ";
std::cout << name;
}
To understand this better, you're never initializing the char name to 0, and cout.write() does not check for null. One option is to initialize char name to 0s from the start:
#include <iostream>
using namespace std;
int main()
{
char name[20] = {0};
cout << "\nEnter name: ";
cin.getline(name, 20);
cout << "\nHello ";
cout.write(name, 20);
return 0;
}
#BaummitAugen's answer is the proper way to do this, though.

c++ unable to get proper string input

I am new to programming just wrote this simple function to calculate length of a string but I am unable to take input string from the user properly(have tried my alternatives).
/////////Function to calculate length of a string////////////////////
void str_length(){
char str[30];
int counter=0;
cout << "Enter string: ";
gets(str);
//cin.getline(str,256);
//cin >> str;
for(int i=0;str[i] != '\0';i++){
counter++;
}
cout << "String length is: " << counter << endl;
}
///////////////////////////////////////////////////////////////
of all possible ways the program either exits abruptly or with 'cin' I can only get partial string till the first space.
If you tried cin.getline(str,256), you'd have needed your buffer to be declared as char str[256].
You shouldn't really be involving yourself with these things however. Stick with std::string:
std::string str; // Declare a string
std::getline(std::cin, str); // Get a line from the std::cin stream and put it in str
unsigned int stringLength = str.length(); // get the length of the string
Why not use the std::string library. It is nice and easy to use.
void str_length()
{
std::string line;
std::cout << " Please input current line: " << std::endl;
std::getline(std::cin, line);
std::cout << "the length of input string is: " << line.length() <<std::endl;
}
I can only agree with my previous speakers and would recommend you to use the better variant by using std::string. Nevertheless if you really want to use C-String than you can use this approach:
std::cin.get(char *s, streamsize n)
This method reads in characters until you press the enter button.
#include<iostream>
#define SIZE 40;
using namespace std;
int main() {
char str[SIZE];
cin.get(str, SIZE-1);
cout << str << endl;
return 0;
}
You should be aware if you have once created an buffer overflow that you will get some trouble at the next call of this method. The problem is that your input buffer will save the remaining characters and at the next call your methods will only read in the remaining characters. To solve this problem you have to clear your input buffer before each input.
Best practice is to use this code in front of each cin.get()
while(cin.get() != '\n');
#include <iostream>
void str_length(){
char str[30];
std::cout<< "Enter string: ";
std::cin>>str;
int counter=0;
for(counter=0;str[counter] != '\0';counter++){}
std::cout<<"String length is "<<counter<<std::endl;
}
OR
#include <iostream>
#include <string>
void str_length(){
std::string str;
std::cout<<"Enter string: "<<std::endl;
std::cin>>str;
std::cout<<"String length is "<<str.size()<<endl;
}

C++ cin problems. not capturing input from user

I have the following method which is not capturing anything from the user.If I input New Band for the artist name, it only captures "New" and it lefts out "Band". If I use cin.getline() instead nothing is captured. Any ideas how to fix this?
char* artist = new char [256];
char * getArtist()
{
cout << "Enter Artist of CD: " << endl;
cin >> artist;
cin.ignore(1000, '\n');
cout << "artist is " << artist << endl;
return artist;
}
This worked just fine. Thank you Roger
std::string getArtist()
{
cout << "Enter Artist of CD: " << endl;
while(true){
if ( getline(cin, artist)){
}
cout << "artist is " << artist << '\n';
}
return artist;
}
std::string getArtist() {
using namespace std;
while (true) {
cout << "Enter Artist of CD: " << endl;
string artist;
if (getline(cin, artist)) { // <-- pay attention to this line
if (artist.empty()) { // if desired
cout << "try again\n";
continue;
}
cout << "artist is " << artist << '\n';
return artist;
}
else if (cin.eof()) { // failed due to eof
// notice this is checked only *after* the
// stream is (in the above if condition)
// handle error, probably throw exception
throw runtime_error("unexpected input error");
}
}
}
The whole thing is a general improvement, but the use of getline is possibly the most significant for your question.
void example_use() {
std::string artist = getArtist();
//...
// it's really that simple: no allocations to worry about, etc.
}
This is the specified behaviour; istreams only read up to a space or a newline. If you want an entire line, you use the getline method, as you already discovered.
Also, please use std::string instead of char* in any new C++ code, unless there are very good reasons otherwise. In this case, it will save you from all kinds of problems like buffer overflows, without any extra effort on your part.
If you're going to have white space separators in your input, you need to use getline for your input. That would make your ignore unnecessary.

C++ - String input with a pointer-to-structure?

How do you use a pointer-to-struct to get input that will be stored in a string variable? I thought simply passing pz->szCompany to getline() would behave the same as if I had used the . operator on a normal instance of Pizza (instead of a pointer-to), but when I run this program it skips over the company name prompt completely.
// Parts of the program omitted.
struct Pizza {
string szCompany;
float diameter;
float weight;
};
Pizza* pz = new Pizza;
cout << "Enter the weight: ";
cin >> pz->weight;
cout << "Enter the company name: ";
// use getline because the company name can have spaces in it.
getline(cin, pz->szCompany);
cout << "Enter the diameter: ";
cin >> pz->diameter;
cout << "\nCompany name: " << pz->szCompany;
cout << "\nWeight: " << pz->weight;
cout << "\nDiameter: " << pz->diameter;
// cannot forget this step.
delete pz;
return 0;
When you use >> to read input, it will leave unread characters in the stream (those, that couldn't be converted to integer, at least the return character you type to enter input), which the following getline will consume thinking it has already read an (empty) line.
#include <limits>
//...
cin >> pz->diameter;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Enter the company name: ";
// use getline because the company name can have spaces in it.
getline(cin, pz->szCompany);
Your problem has nothing to do with the struct or pointers, just the normal behavior of input streams.
You may also have to deal with incorrect input. For example, entering a non-number where a number is expected would put the stream in an error state, so that all subsequent attempts to read would fail unless you deal with it. Better take Neil's advice, but for getting input from the user, it might also make sense to use a function for formatted input that prompts you until you get valid input:
template <class T>
T input(const std::string& prompt, const std::string& error_prompt)
{
std::cout << prompt;
T result;
while (!(std::cin >> result)) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << error_prompt;
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return result;
}
//...
pz->weight = input<float>("Enter the weight: ", "Please enter a numeric value: ");
This has nothing to do with the pointer to the structure instance. It is simply not a good idea to mix line input with formatted input. In fact, it's not a good idea to use formatted input from an interactive input stream at all. You should instead read each input using getline() and then convert to the required type.
Add either:
cout << "Enter the company name: " << std::endl;
or
cout << "Enter the company name: ";
cout.flush();
You problem concerned with bufferization of stream