C++ Infinite Loop - c++

I'm learning C++.
nav is an integer .
I want to ask user for typing a valid value, if he / she type an invalid value.
void main()
{
printf("Type an integer : ");
if(!scanf("%d", &nav))
{
system("cls");
printf("Invalid ! \n");
main();
}
}
But it's blinking after typing first value . It's blinking like reloading screen. I think it's infinite loop.
How can i do it in right way ? I want to ask a number from users, until it's typing a real number .

If the user types an invalid input, scanf() won't consume it, and you'll be left peeking the same offending input character forever. You need to first read whatever the user enters — I recommend using std::getline() — and then try to parse that with strtol(), sscanf() or std::istringstream. Don't use atoi() because it doesn't report failures.
int nav;
{
string line;
while (getline(cin, line))
if (istringstream(line) >> nav)
break;
}
EDIT: See the comments for a rather beautiful rendition of the above logic. I've left it out of the answer because: a) I don't want to steal someone else's idea, and b) I'm not sure I'd present a newcomer to C++ with that formulation — not in one go, at least.
P.S.: You can't call main() in C++.

Two things.
Scanf needs the 'enter' key pressed before it will process input, so the blinking could just be the cursor waiting for the next key.
Also, calling main from main is fairly non-standard. You should look into a 'while' loop.

Your program is not a good one, but nevertheless I will tell you what is happening.
In C/C++, when scanf cannot read an integer (%d) from input, it wouldn't read anything. That is, whatever prevented scanf from reading an int, will remain there. On the next scanf the same character is going to cause an error.
Let me demonstrate by an example. Imagine you are reading many integers from this input:
12 13 Shahbaz 15
Now if you call scanf with %d, you will read 12 and the input would be:
13 Shahbaz 15
Next, you call scanf with %d and you will read 13. now the input would be:
Shahbaz 15
Again, you call scanf with %d. Here, the input begins with an S (after the whitespace) which makes scanf return with a failure as it could not read an integer. The input is left untouched (save perhaps for the whitespace). That is, the input will be:
Shahbaz 15
As you can see, reading the input with %d will give you the exact same error and you are stuck in an infinite loop.
To solve this, you have many choices. This very much depends on how you want to handle the situation, but two methods would be to either read a character (with %c) or a string (with %s) right after printing printf("Invalid\n").
The first method is good for handling input like this:
12 13 q14 15
where q is a mistake that needs to be ignored. The second method is good for handling input like this:
12 13 Shahbaz 15
where the invalid data are meaningful words, but you just want to ignore them.
And the way I would write it, if I wanted to use scanf would be:
int main() // always write int main
{
int nav;
printf("Type an integer: ");
while (scanf("%d", &nav) != 1) // scanf returns number of successful %'s read
{
printf("Invalid number. Try again: ");
scanf("%*s"); // read a %s but ignore it
}
// The rest of the program, using nav
return 0;
}

Related

Check scanf formating without conversions

Is there a way how to check if some specific characters were given on input using scanf without using character conversions?
int main(void)
{
if(scanf("{ ["))
printf("GOOD INPUT\n");
else
printf("BAD INPUT\n");
return 0;
}
This code always gives the bad input option (it expects scanf return value to be 1) but interestingly if I enter other than the desired characters it gives the bad input imediately but if I enter it as its specified in the scanf it blows the bad input at me AFTER I enter the whole input.
So it must be awaiting the input to be in that specified format but my question is: How can I check it, without any conversions, and make according action depending on wether the input was entered correctly or not?
You might use the %n conversion of scanf (it sets below into pos the number of characters read so far)
int pos= -1;
if (scanf("{ [%n", &pos) >=0 && pos>0)
printf("GOOD INPUT\n");
else
printf("BAD INPUT");
Beware, the return count of scanf might be implementation specific (it probably stays at 0). But pos get assigned to a positive offset of scanf did get { followed by some (zero or more) space-like characters followed by a [.
However, what you probably want is some lexical analysis and parsing, then scanf is not a good solution. You'll better read the entire line (e.g. with fgets or getline) and parse it later.
See also the man page of scanf(3)
scanf (and cousins) returns a count of the number of successful conversions. If you specify 0 conversions, then its return value will always be 0.
To use scanf for this task, I'd probably use a couple of scanset conversions:
char a[2], b[2];
if (scanf("%1[{] %1[[]", &a, &b) == 2)
printf("Matched");
Or, you could simplify this a little bit:
char a[2];
if (scanf("{ %1[[]", &a) == 1)
Either way, we've specified each scan set to match only one specified character, but it's still a conversion, so we can see whether it succeeded or failed.
Unfortunately, we still have to assign the result somewhere. scanf does support using * like this: "%*s", to tell it to read a string, but not store the result anywhere--but when you do so, that conversion doesn't get counted in the return value, so (much like before) we can't use it to determine whether we got a match or not.
If good input needs to exactly 3 characters: { space [, use "%*1[ ]" to scan a space and "%n", which saves the scan character count, to insure scanning reach the expected end.
int main(void) {
int n = -1;
scanf("{%*1[ ][%n", *n);
if (n >= 0) {
printf("GOOD INPUT\n");
} else {
printf("BAD INPUT\n");
}
return 0;
}
I'd recommend to read a line of input with fgets() first and then parse the buffer. That can leave stdin in a better known state when bad input happens.

C++ using cin.ignore() to remove first non-int from the input stream [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
So For example if I input:
33a
and I want to remove "a" from the stream and store 33 into an int, how to do this using cin.ignore?
Edits:
To be more precise:so If I have input:
2
3
4a
b
or
2
3
4
a
b
I want to store those 2,3,4 into an array, and also when encountered 'a'(first non-int char), ignore 'a', and then jumped out the input reading loop(ie
while(cin>>num)
)?
TL;DR version based on question edit:
The smart way is to use a std::vector to store the read values and ignore all the messiness of an array of unknown size.
Then
while not done
read a value
if value successfully read
store value
ignore to the end of the line
else
clear stream error
ignore to the end of the line
I'm only providing a pseudocode answer because this looks too much like a homework assignment at this point. All of the required bits and pieces are discussed below and it's up to OP to assemble them correctly.
If you MUST use an array, before storing a value test to make sure you will not overrun the end of the array by storing the value.
Old answer:
Link to documentation.
cin.ignore() ignores one character.
cin.ignore(10) ignores up to 10 characters.
cin.ignore(10, ' ') ignores up to 10 characters or it finds and consumes a space.
Another common case is discarding the rest of the line: cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
So...
int val;
cin >>val;
cin.ignore();
will handle the simple case of reading an int and discarding the next character. Input of "33a" will result in 33 being stored in val, 'a' being ignored, and the end of line (enter keypress) used to trigger this chain of events is left in cin for future consumption. This could be a problem so,
int val;
cin >>val;
cin.ignore((std::numeric_limits<std::streamsize>::max(), '\n');
will read 33 into val, discard 'a` and anything else the user typed in. This may not be what you want. For example, input of "33a 44b"
int val;
cin >>val;
cin.ignore((std::numeric_limits<std::streamsize>::max(), ' ');
will read 33 into val, discard 'a' and anything else the user typed in up to the first space. Another pass through the above code will result in 44 in val, the discard of 'b', and the end of line staying in cin.
Attempting to use std::getline at this point is bad. It will instantly consume the end of line and return an empty string. However, a third pass though the above code will discard the end of line as whitespace and wait for more input from the user.
However users are lousy sources of input, so you want to protect cin >>val; from a user typing in something like "blah", hitting enter, and trying again. "blah cannot convert to an int, so cin will be set into the error state and you need to acknowledge this before continuing.
int val;
while (!(cin >>val)) // continue as long as the user has finger trouble
{
cin.clear() // clear the error state
// discard the rest of the line because who knows what other garbage is on it.
cin.ignore((std::numeric_limits<std::streamsize>::max(), '\n');
// probably want to notify the user and prompt for good input here.
}
//whichever ignore code fits your usecase
or similar will handle the bad input case.
Although it's not immediately obvious now to do it, streams actually incorporate a way to deal with this quite directly (at least assuming I've understood the question correctly).
When you read (for example) a number from a stream, the stream skips any white-space before the number. To figure out whether a character is white-space or not, the stream uses an associated locale--specifically, the locale's ctype facet.
To have the stream ignore everything except digits, we can provide a locale that classifies everything except digits as white space.
#include <locale>
#include <iostream>
#include <algorithm>
#include <vector>
#include <sstream>
#include <iterator>
class my_ctype : public std::ctype<char> {
public:
mask const *get_table() {
static std::vector<std::ctype<char>::mask>
table(table_size, (mask)space);
std::fill_n(table.begin() + '0', 10, (mask)digit);
return &table[0];
}
my_ctype(size_t refs=0) : std::ctype<char>(get_table(), false, refs) { }
};
int main() {
std::istringstream s("1 2, 9 3 a 4b 2 5");
s.imbue(std::locale(std::locale(), new my_ctype));
int i;
while (s >> i)
std::cout << i << "\n";
}
Result:
1
2
9
3
4
2
5
Note that with this, we don't have to use ignore (or anything else, except the normal stream extractor) to ignore the garbage we don't care about in the stream. The other side of this is that this is useful (at least primarily) when assigned to the stream as a whole. If you want to read 4 numbers this way, then be able to go back to reading everything normally, this probably won't be a useful technique for your situation.

EOF - scanf and printf

I'm tring to do a simple exercise here, but i need to understand how EOF works first.
void main()
{
char s1[1000];
while (scanf("%s", s1)!=EOF)
;
printf("%s",s1);
}
The idea is to have multiple lines in input, and display them.
The problem I have is that if I put
Hello World
This is stackoverflow
When printf is called, it only prints
stackoverflow
Why isn't it printing everything and how do I make it print?
Regards
Remove the semicolon ;:
while (scanf("%s", s1)!=EOF)
printf("%s",s1);
Note that this will still exhibit odd behavior at end of file depending on how it ends exactly. Furthermore, it splits the input into words, which are separated by spaces or new lines. You may want to simply split into lines.
So you may be better served with for instance:
while (gets(s1)!=NULL)
puts(s1);
This code fragments reads your input line by line until end-of-file.
To read everything (or as much as your buffer can hold), you can use:
char s1[1000] = "";
fread(s1, sizeof(s1) - 1, 1, stdin);
puts(s1);
However, my preferred method of reading a text file is:
using namespace std;
string line;
while (getline(cin, line))
{
cout << line << endl;
}
That is because usually I want to process a file line by line, and getline with a string ensures the line buffer is always big enough.
You probably want this:
char s1[1000][20];
int i = 0 ;
while (!feof(stdin))
fgets(s1[i++], 20, stdin) ;
int j ;
for (j = 0; j < i; j++)
printf("%s\n", s1[j]);
Here you can enter at most 1000 lines that are maximum 19 characters long.
What you have is a loop that reads words into a buffer until it reaches EOF (and does nothing with those words), followed by a printf to print the contents of the buffer. The printf is after the loop (not in it), so executes once after the loop completes. At that time, the buffer will contain the last word read, so that is what gets printed.
The EOF return test means "nothing more to be read", which isn't necessarily an end of file (might be an error condition of some kind), but in practice that distinction can be ignored. Looping until your reading function returns EOF or NULL (depends on function) is good practice.
If you want to print each word as it is read, you need to put a printf in the loop.
If you want to store the words for later processing, you need to store them somewhere. That means declaring some storage space, or allocating space on the heap, and some bookkeeping to track how much space you've used/allocated.
If you want lines rather than words, you should use fgets instead of scanf("%s". Note that fgets returns NULL rather than EOF when there's nothing more to be read.
Because it only prints the last thing that is read from the file ("stackoverflow"). This is caused by the semicolon after the end of your while(...); - this means that you are doing while(...) { /* do nothing */} - which is probably not what you wanted
Also, printf("%s",s1)!='\0'; makes no sense at all. For one thing, printf returns the number of characters printed - '\0' is the value zero written as a character constant. And of course, doing != 0 of the result without some sort of use of the comparison is pretty much pointless too.
Use fgets instead of scanf if you want to read one line at at time. scanf will stop reading when it finds a whitespace. fgets will read till the end of the line.
Use fgets(). Simple and sweet
char buf[1000];
while (fgets(buf, sizeof buf, stdin) != NULL) {
fputs(buf, stdout);
}
Here is how end-of-file works in C. The input channels are called input streams; disk files and stdin are both input streams. The "end-of-file" state is a flag that a stream has, and that flag is triggered when you try to read from a stream, but it turns out there are no more characters in the stream, and there never will be any more. (If the stream is still active but just waiting for user input for example, it is not considered to be end-of-file; read operations will block).
Streams can have other error states, so looping until "end-of-file" is set is usually wrong. If the stream does go into an error state then your loop will never exit (aka. "infinite loop").
The end-of-file state can be checked by feof. However, some input operations also can signal an error as well as, or instead of, returning the actual data they were intended to read. These functions can return the value EOF. Usually these functions return EOF in both cases: end-of-file, and stream error. This is different to feof which only returns true in the case of end-of-file.
For example, getchar() and scanf will return EOF if it was end-of-file, but also if the stream is in an error state.
So it is OK to use getchar()'s result as a loop condition, but not feof on its own.
Also, it is sometimes not OK to use scanf() != EOF as a loop condition. It's possible that there is no stream error, but just that the data you requested wasn't there. For example, if you scan for "%d" but there are letters in the stream. Instead, it's better to check for successful conversion (scanf returns the number of successful conversions it performed). Then when you exit your loop, you can go on to call feof and ferror to see whether it was due to end-of-file, or error, or just unexpected input.

C++ User enters a non-integer value for integer variable

I am working on program where a list of options is displayed to the user and he would then enter an integer to specify which option he wants to select.Now I have pre-empted the situation where the user might enter an integer value apart from the valid ones. But if he enters any other value, say a character or a string, the program goes into an infinite loop with the list of options being printed infinitely. How can i rectify this? I mean, I should be able to give my user an error when for a predefined integer variable he enters a value that is not an integer.
Any help appreciated. Here is a sample code.
do{
printf("Select appropriate option.\n");
printf("Press 1 to do this");
printf("Press 2 to do that.\n");
printf("Press 3 to exit the program.\n");
scanf("%d",&choice);
if(choice!=1 && choice!=2 && choice!=3)
printf("You entered an invalid choice. Please enter again.\n");
switch(choice){
case 1:
//do this
break
case 2:
//do that
break;
case 3:
exit(1);
}}
while(choice!=3);
So basically when a user enters a non-integer value for choice I want the program to notify the user and ask him for another input.
It cannot be done with direct scanf into an integer variable. Such scanf will not only accept 1.23, it will also accept 1abcde and other inputs. scanf (and other conversion functions) reads as much as it can in accordance with the requested format. It stops when it finds something that does not satisfy format requirements and simply leaves it untouched.
If you want to perform this sort of analysis, you have to read the input as string and then parse and analyze that string manually.
A C-style code sketch (since you insist on C-style code, despite having tagged it as [C++]) might look as follows
char buffer[100]; /* 100 should be enough for everyone :) */
int n = scanf("%s", buffer);
if (n < 1)
/* ERROR, can't read */;
char *end;
long choice = strtol(buffer, &end, 10);
if (end == buffer || *end != '\0' || errno == ERANGE)
/* ERROR, bad format */;
/* ... */
scanf will not consume any non-digits when converting %d. It will return 0 because it didn't convert anything, and the "bad input" will still be there waiting to be consumed. You have to consume it in some way to be ready for a valid input.
(also note you're excluding 3 in your if before testing for it in your switch)
Use iostream - see http://www.cplusplus.com/reference/iostream/
Having said that if you insist on using scanf - check the return value - i.e. read http://linux.die.net/man/3/scanf
isdigit will check for any input that is a digit(number) type.
For this include header ctype.h.
Also terminate your program using exit(0) if input is incorrect.
For this include header stdlib.h.
#include<ctype.h>
#include<stdlib.h>
char c;
scanf("%c", &c);
if (isdigit(c))
{
case statement...
...
...
}
else
{
printf("Wrong input");
exit(0);
}

What is wrong with my UVa code

I tried to solve this problem in UVa but I am getting a wrong answer and I cant seem to find the error
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2525
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int t,j,k,i=1;
char a[1000];
while(scanf("%d",&t)!=EOF && t)
{
int sum=0;
getchar();
gets(a);
k=strlen(a);
for(j=0;j<k;j++)
{ if(a[j]=='a'||a[j]=='d'||a[j]=='g'||a[j]=='j'||a[j]=='m'||a[j]=='p'||a[j]=='t'||a[j]=='w'||a[j]==32)
sum=sum+1;
else if(a[j]=='b'||a[j]=='e'||a[j]=='h'||a[j]=='k'||a[j]=='n'||a[j]=='q'||a[j]=='u'||a[j]=='x')
sum=sum+2;
else if(a[j]=='c'||a[j]=='f'||a[j]=='i'||a[j]=='l'||a[j]=='o'||a[j]=='r'||a[j]=='v'||a[j]=='y')
sum=sum+3;
else if(a[j]=='s'||a[j]=='z')
sum=sum+4;
}
printf("Case #%d: %d\n",i,sum);
i++;
}
return 0;
}
In the problem description there is a single number that indicates the number of texts that will be in the input afterwards. Your original code was trying to read the number before every row of input.
The attempt to read the number in each one of the rows will fail since the input character set does not include any digits, so you could be inclined to think that there should be no difference. But there is, when you try to read a number it will start by consuming the leading whitespace. If the input is:
< space >< space >a
The output should be 3 (two '0' and one '2' keys), but the attempt to read the number out of the line will consume the two leading whitespace characters and the later gets will read the string "a", rather than " a". Your count will be off by the amount of leading whitespace.
separate your code into functions that do specific things: read the data from the file, calculate the number of key presses for each input, output the result
Benefit:
You can test each function independently. It is also easier to reason about the code.
The maximum size of an input is 100, this means you only need an array of 101 characters( including the final \0) for each input, not 1000.
Since this question is also tagged C++ try to use std::vector and std::string in your code.
The inner for seems right at a cursory glance. The befit of having a specialized function that computes the number of key presses is that you can easily verify it does the correct thing. Make sure you check it thoroughly.