How to make sure input into a char isn't too long? - c++

So I'm trying to make sure the user enters only one charcter.
Like if the input is "ab", the code will throw an exception.
char ch = ' ';
std::cin >> ch;
// I'm stuck here

You can enter the input into an entire string, and process just the first character:
#include <string>
#include <iostream>
int main()
{
std::string input;
std::cin >> input;
char ch = ' ';
if ( input.size() > 1 )
{
// Entered more than 1 character
}
else
ch = input[0];
}

Related

while Infinite loop in function

bool isDigital(char c) { return ('0' <= c && c <= '9'); }
void DigitalToken( char digitToken[50], char ch ) {
digitToken[0] = ch;
char input = '\0';
cin >> input;
int i = 0;
while ( ( input != ' ' ) && ( input != '\t' ) && ( input != '\n' ) ) { // got a infinite loop
i++;
digitToken[i] = input;
cin >> input;
} // while ( input != ' ' && input != '\t' && input != '\n' )
} // DigitalToken()
int main() {
char ch = '\0';
while ( cin >> ch ) {
if ( isDigital(ch) ) {
char* digitToken = new char[50]();
DigitalToken(digitToken, ch);
cout << digitToken;
delete[] digitToken;
} // else if
} // while
} // main()
I don't understand why I got a infinite loop in DitgitalToken function.
When I input 123, it should be output 123.
I watched it for a long time, but I still don’t know why and how to fix it.
Instead of cin >> input; use input = cin.get();.
You have to be careful while using cin with characters or strings. It treats spaces, tabs, newlines as end of the input and hence do not treat them as input themselves.
Your program blocks in the while loop on cin >> input; after it read "123". As #Arty suggested use cin.get() instead as whitespace is stripped by default. You can also use cin >> noskipws; prior to executing cin >> input;. See skipws.

Using the newline character to break a loop in c++

I'm looking for a way to break a for loop using enter in the visual studio console.
do {
std::cin >> userInput;
if (userInput == '\n')
break;
lineStorage[lineLength] = userInput;
lineLength++;
} while(true);
This is what I have so far, but the newline character won't work for what I need it to. Any suggestions or insight would help.
P.S. I cannot use a sentinel value other than the newline character resulting from the enter button.
P.S. More context:
char lineStorage[80] = { 'a' };
char userInput = ' ';
const char lineEnd = '\n';
int lineLength = 0;
std::cout << "Enter a line:";
do {
std::cin >> userInput;
if (userInput == '\n')
break;
lineStorage[lineLength] = userInput;
lineLength++;
} while (true);
Reading with >> by default skips whitespace, and a newline is whitespace. I suggest using getline() instead:
for(int i = 0; i < 80; i++) {
if (!getline(std::cin, userInput) || userInput.empty())
break;
lineStorage[lineLength] = userInput;
lineLength++;
}
If your lineStorage is really supposed to store individual words, you can split userInput on spaces before storing the words.
Edit: now that you've shown that userInput is a single character, I think you should just use std::cin.get(userInput) to read one character at a time. That will let you get the newlines in the style of your original code.
I like the other answer better, but something like this should also work:
do {
cin.get(userInput);
if (userInput == 10) {
break;
} else {
lineStorage[lineLength] = userInput;
lineLength++;
}
} while (true);
more clear will be
#include <stdio.h>
#include <stddef.h>
int main(int argc , char *argv[])
{
char t[70]={0},x;
while(1)
{
scanf("%[^ ^\n]%c",t ,&x);
if(x == '\n') break;
}
}

How to stop a while loop in c++

"Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them.
Exit the program when a terminating '|' is entered."
my attempt
#include <iostream>
#include <cstdlib>
using namespace std;
int main(){
int firstnumber;
int secondnumber;
int stopnumber;
while(stopnumber!='|'){
cout <<"Please enter an integer, followed by another integer: \n";
cin >> firstnumber >> secondnumber;
cout <<"\n" << firstnumber <<" "<< secondnumber<< " \n";
}
return 0;
}
the program takes 2 number and prints them, but when i enter '|' , it goes in infinite loop. How to stop the program when i enter '|'
Thanks
This is how your loop should look like:
Read a character (std::cin::get).
If successful and your character is the stop symbol, break the loop.
If your character is not a digit (::isdigit), continue looping.
If your character is a digit, put it back(std::cin::putback).
Read two integers.
If successful, display them, if not, clear the stream (std::cin::clear).
You will have to patiently try to understand what get, putback & isdigit are doing.
[EDIT]
Run it
#include <iostream>
#include <cctype>
int main()
{
char c;
while ( std::cin.get( c ) && c != '|' )
{
if ( !std::isdigit( c ) )
continue;
std::cin.putback( c );
int i, j;
if ( std::cin >> i >> j )
std::cout << i << ' ' << j << std::endl;
else
std::cin.clear();
}
return 0;
}
Your loop is testing stopnumber which is never set. If you set stopnumber to either firstnumber or secondnumber then perhaps you can get your logic to work but there is a step missing as it is.
Ok, I think I have found my answer
I tried putting my cin in the while loop as such
int firstnumber;
int secondnumber;
while (cin >> firstnumber >> secondnumber)
And it worked! Thanks everyone for your help
This depends on whether you need to exit directly after you receive the '|' character or whether you mind running through the rest of the loop first before exiting it......
Personally I'd want to exit straight after receiving the '|' so would follow the basic idea of....
int a,b;
while(){
read your values a,b in
if (a='|' || b='|'){exit()};
print your values
}
std::stoi(std::string) - returns int from std::string
#include <iostream>
#include <string>
bool isNumber(std::string &str) {
for (auto i : str) {
if (i < '0' || i > '9') return false;
return true;
}
int main () {
int a, b;
std::string s;
while (true) {
std::cin >> s;
if (s == "|" || !isNumber(s)) break;
a = std::stoi(s);
std::cin >> s;
if (s == "|" || !isNumber(s)) break;
b = std::stoi(s);
std::cout << a << " " << b << std::endl;
}
return 0;
}

How to parse this data of unknown size

I have a simple text file containing instructions per a line. e.g
A 1 1
B 2 1 A
C 3 1 A
D 4 1 B C
Basic syntax is Letter, Num, Num, Letter(s)
I just don't know what function I should be calling to parse the data, and how to parse it in the given syntax. I feel like there's so many ways to do it.
The following C++ example shows one of possible way to read single characters from file, controlling end of line:
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
int main(void)
{
ifstream inpFile("test.txt");
string str;
char c;
while (inpFile.good()) {
// read line from file
getline(inpFile, str);
// make string stream for reading small pieces of data
istringstream is(str);
// read data ingnoring spaces
do
{
is >> c; // read a single character
if (!is.eof()) // after successful reading
cout << c << " "; // output this character
} while (is.good()); // control the stream state
cout << "[End of line]" << endl;
}
cout << "[End of file]" << endl;
}
Here istringstream is used to process single line that is got by getline.
After reading a char with is >> c value in c can be checked for content, e.g.:
if (!is.eof()) // after successful reading
{
// analyze the content
if ( isdigit(c) )
cout << (c - '0') << "(number) "; // output as a digit
else
cout << c << "(char) "; // output as a non-number
}
Note: if file can contain not single characters / digits, but numbers and words, type of c should be appropriate (e.g. string)
In C++, read an entire line and make a stream from it, then read from that stream with >>.
Example:
std::ifstream file(filename);
std::string line;
while (file.getline(line))
{
std::istringstream in(line);
char letter;
int number1;
int number2;
std::vector<char> letters;
if (in >> letter >> number1 >> number2)
{
char letter2;
while (in >> letter2)
{
letters.push_back(letter2);
}
}
}
This is C example that read lines, and then goes (using pointer) from the beginning to output readable characters (with code greater than 32):
#include <stdio.h>
#include <ctype.h>
#define MAX_LINE_LEN 80
int main(void)
{
FILE * inpFile = fopen("test.txt", "r");
char buf[MAX_LINE_LEN];
char *p;
while (!feof(inpFile))
{
// read a line from file
if (fgets(buf, MAX_LINE_LEN, inpFile) != NULL)
{
p = buf; // start from the beginning of line
// reading data from string till the end
while (*p != '\n' && *p != '\0')
{
// skip spaces
while (isspace(*p) && *p != '\n') p++;
if (*p > 32)
{
// output character
printf("%c ", *p);
// move to next
p++;
}
}
}
printf("[End of line]\n");
}
printf("[End of file]\n");
return 0;
}
To extract numbers and words from the line you can do something like:
// reading data from string till the end
while (*p != '\n' && *p != '\0')
{
// skip spaces
while (isspace(*p) && *p != '\n') p++;
if (*p > 32)
{
int num;
char word[MAX_LINE_LEN];
// trying to read number
if (sscanf(p, "%i", &num))
{
printf("%i(number) ", num);
}
else // read string
{
sscanf(p, "%s", word);
printf("%s(string) ", word);
}
// move to next space in the simplest way
while (*p > 32) p++;
}
}

How do you parse a c-string?

Hi I'm trying to take a c-string from a user, input it into a queue, parse the data with a single space depending on its contents, and output the kind of data it is (int, float, word NOT string).
E.g. Bobby Joe is 12 in 3.5 months \n
Word: Bobby
Word: Joe
Word: is
Integer: 12
Word: in
Float: 3.5
Word: months
Here's my code so far:
int main()
{
const int maxSize = 100;
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
std::cin.getline(cstring, maxSize, '\n');
//Keyboard Buffer Function
buffer::keyboard_parser(cstring);
return EXIT_SUCCESS;
}
Function:
#include <queue>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
namespace buffer
{
std::string keyboard_parser(char* input)
{
//Declare Queue
std::queue<std::string> myQueue;
//Declare String
std::string str;
//Declare iStringStream
std::istringstream isstr(input);
//While Loop to Read iStringStream to Queue
while(isstr >> str)
{
//Push onto Queue
myQueue.push(str);
std::string foundDataType = " ";
//Determine if Int, Float, or Word
for(int index = 0; index < str.length(); index++)
{
if(str[index] >= '0' && str[index] <= '9')
{
foundDataType = "Integer";
}
else if(str[index] >= '0' && str[index] <= '9' || str[index] == '.')
{
foundDataType = "Float";
break;
}
else if(!(str[index] >= '0' && str[index] <= '9'))
{
foundDataType = "Word";
}
}
std::cout << "\n" << foundDataType << ": " << myQueue.front();
std::cout << "\n";
//Pop Off of Queue
myQueue.pop();
}
}
}
Right now with this code, it doesn't hit the cout statement, it dumps the core.
I've read about using the find member function and the substr member function, but I'm unsure of how exactly I need to implement it.
Note: This is homework.
Thanks in advance!
UPDATE: Okay everything seems to work! Fixed the float and integer issue with a break statement. Thanks to everyone for all the help!
Your queue is sensible: it contains std::strings. Unfortunately, each of those is initialised by you passing cstring in without any length information and, since you certainly aren't null-terminating the C-strings (in fact, you're going one-off-the-end of each one), that's seriously asking for trouble.
Read directly into a std::string.
std::istreams are very useful for parsing text in C++... often with an initial read of a line from a string, then further parsing from a std::istringstream constructed with the line content.
const char* token_type(const std::string& token)
{
// if I was really doing this, I'd use templates to avoid near-identical code
// but this is an easier-to-understand starting point...
{
std::istringstream iss(token);
int i;
char c;
if (iss >> i && !(iss >> c)) return "Integer";
}
{
std::istringstream iss(token);
float f;
char c; // used to check there's no trailing characters that aren't part
// of the float value... e.g. "1Q" is not a float (rather, "word").
if (iss >> f && !(iss >> c)) return "Float";
}
return "Word";
}
const int maxSize = 100; // Standard C++ won't let you create an array unless const
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
if (std::cin.getline(cstring, maxSize, '\n'))
{
std::istringstream iss(cstring);
std::string token;
while (iss >> token) // by default, streaming into std::string takes a space-...
token_queue.push(token); // ...separated word at a time
for (token_queue::const_iterator i = token_queue.begin();
i != token_queue.end(); ++i)
std::cout << token_type(*i) << ": " << *i << '\n';
}