while Infinite loop in function - c++

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.

Related

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

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];
}

Input string in C++ do while

I'm trying to read a string as an input.
The string can only contain A C G and T letters and the length can't be more than 20000.
If the length is more than 20000 or it contains any other letter than A C G or T print out "error" and read again.
EXAMPLE INPUT: ACCGGTATTTACG
Here's my code and currently it prints error for every input.
int main()
{
string str;
string tmp;
bool hiba;
do{
cout<<"Str: ";cin>>str;
for(int x = 0;x < str.length();x++){
hiba = (cin.fail() || str[x] != 'A' || str[x] != 'C' ||str[x] != 'G' ||str[x] != 'T' || str.length() > 20000);
if(hiba){
cout<<"Error\n";
cin.clear();
getline(cin,tmp);
break;
}
}
}while(hiba);
}
Here is a direct transliteration of your requirements. Note the use of std::string::find_first_not_of to find "bad" characters. Also note that it returns an empty string should std::cin >> sequence fail. You need to handle that corner case.
std::string read_dna(int max_length) {
std::string sequence;
while (std::cin >> sequence) {
if (sequence.length() > max_length ||
sequence.find_first_not_of("ACGT") != std::string::npos) {
std::cerr << "error" << std::endl;
} else {
return sequence;
}
}
return std::string{};
}

c++ reading a file into a struct and writing a binary file

I have a text file that contains over 5000 lines with data (lottery draw results for Lotto). Each line has the form: number. day.month.year number1,number2,number3,number4,number5,number6
Five sample lines:
27.01.1957 8,12,31,39,43,45
03.02.1957 5,10,11,22,25,27
10.02.1957 18,19,20,26,45,49
17.02.1957 2,11,14,37,40,45
24.02.1957 8,10,15,35,39,49
I have also:
struct Lotto
{
short number_drawing;
char day;
char month;
short year;
char tab[6];
};
I have to write data from this text file into a binary file as struct Lotto.
I have already run out of ideas.
I have beeng trying since few days but my program still doesn't work properly :(
I try to load although one line :)
int main()
{
ifstream text("lotto.txt", ios::in);
ofstream bin("lottoBin.txt", ios::binary | ios::out);
Lotto zm;
short number_drawing;
char day;
char month;
short year;
char tab[6];
char ch;
int records = 0;
while (!text.eof())
{
text >> zm.number_drawing >> ch >> zm.day >> ch >> zm.month >>
ch >> zm.year >> zm.tab[0] >> ch >> zm.tab[1] >> ch >> zm.tab[2] >>
ch >> zm.tab[3] >> ch >> zm.tab[4] >> ch >> zm.tab[5];
records++;
}
cout << "All records: " << records << endl;
Here are some observations that might help you:
You will not be able to directly read a number into a char. Use an intermediate integer.
Define a function to read a record: bool read( std::istream&, Lotto& )
Your while should call the above function: while ( read( is, lotto ) )
A starting point:
bool read( std::istream& is, Lotto& lotto )
{
short t;
char c;
// read data
//
is >> t;
lotto.number_drawing = t;
is >> c;
if ( c != '.' )
return false;
//
is >> t;
lotto.day = char( t );
is >> c;
if ( c != '.' )
return false;
// read rest of fields...
// end of line
while ( is.get( c ) && isspace( c ) && c != '\n' )
;
if ( ! is.eof() && c != '\n' )
return false;
// check data
if ( lotto.month > 12 )
return false;
// check rest of data...
return is.good();
}
int main()
{
ifstream is( "yourfile.txt" );
if ( ! is )
return -1;
Lotto lotto;
while ( read( is, lotto ) )
{
// ...
}
if ( !is.eof() )
return -1;
return 0;
}

I want cin to read until '\n' but I cannot use getline

I have a text file in the following format:
info
data1 data2
info
data1 data2 data3 data4...
The problem is: the count (and length) of the data may be very large and cause run-time problems when getline() is used. So I cannot read the entire line into a std::string. I tried the following:
for(int i=0; i<SOME_CONSTANT ; i++){
string info, data;
cin >> info;
while(cin.peek() != '\n' && cin >> data){
// do stuff with data
}
}
However cin.peek() did not do the trick. The info is read into data in the while loop and program messes things up. How can I fix this?
You can try reading character by character.
char ch;
data = "";
cin >> std::noskipws;
while( cin >> ch && ch != '\n' ) {
if ( ch == " " ) {
// do stuff with data
data = "";
continue;
}
data += ch;
}
cin >> std::skipws;
Use std::istream::getline instead of std::getline. You can choose your buffer size and delimiter.

What is the cin analougus of scanf formatted input?

With scanf there's, usually, a direct way to take formatted input:
1) line with a real number higher than 0, and less than 1. Ending on 'x', e.g: 0.32432523x
scanf("0.%[0-9]x", &number);
2) line represents an addition in the format :30+28=fifty-eight
scanf(":%d+%d=%99s", &number1, &number2, &total);
What is the cin solution, using only the standard library?
You can make a simple class to verify input.
struct confirm_input {
char const *str;
confirm_input( char const *in ) : str( in ) {}
friend std::istream &operator >>
( std::istream &s, confirm_input const &o ) {
for ( char const *p = o.str; * p; ++ p ) {
if ( std::isspace( * p ) ) {
std::istream::sentry k( s ); // discard whitespace
} else if ( (c = s.get() ) != * p ) {
s.setstate( std::ios::failbit ); // stop extracting
}
}
return s;
}
};
usage:
std::cin >> x >> confirm_input( " = " ) >> y;
Use the >> operator to read from cin.
int number1, number2;
std::string text;
char plus, equals;
std::cin >> number1 >> plus >> number2 >> equals >> text;
if (!std::cin.fail() && plus == '+' && equals == '=' && !text.empty())
std::cout << "matched";
It's not as good as scanf because you'd have to verify any literals that were in the scanf string yourself. Doing it with streams will almost certainly be a lot more lines of code than scanf.
I would use scanf.