Objective :
Simplest and similar way to discard any unwanted (which in my case is every non numeric characters but I'd like a solution for a more general case) and remove them from buffer. Example,
#include<stdio.h>
void main(void){
int num1, num2;
printf("Enter num1 here : ");
scanf("%d%*[^\n]%*c", &num);//First scanf statement.
printf("Enter num2 here : ");
scanf("%d", &num2);//Second scanf statement.
printf("num1 is : %d\n
num2 is : %d", num, num2);
}
/* OUTPUT */
1st number : 25 asdfasfasfasf
2nd number : 30
Input 1 : 25
Input 2 : 30
/* This will work by discarding any non */
/* In the program above I didn't write a printf statment to display the text "1st num, 2nd num". This is just so the output is a bit more clear. I am aware of it. */
Now if you change the first scanf from scanf("%d%[^\n]%*c"); to scanf("%d"); and give the same input, you'd get the following output :
#include<stdio.h>
void main(void){
int num1, num2;
printf("Enter num1 here : ");
scanf("%d", &num1);
printf("Enter num2 here : ");
scanf("%d", &num2);
printf("num1 : %d\nnum2 : %d", num1, num2);
}
//OUTPUT//
Enter num1 here : 11 asdf
Enter num2 here : num1 : 11
num2 : 32764
/*As you might see, I am not prompted for 2nd input. Instead the already present characters in the buffer are used.*/
Briefing :
In C scanf("%d%[^\n]%*c"); would remove all the redundant characters like spaces, newline, alphanumeric that come after the number form the buffer before/ after taking another input. How can I achieve the same in C++ where after my cin >> var; would take the remaining characters in the buffer and then discard them. This only works for numbers from 0-9. But what I am interested in is the *[^\n] and *c because it helps me read the characters from buffer without saving them anywhere which technically means that they get discarded.
Exclusions :
cin >> ws;
cin.ignore(numeric_limits::max(),ā\nā);
I've found the aforementioned ways but unless there is no other more viable option available I'd rather not use these since it involves including external libraries #limits and #vector receptively.
Aproximation :
cin.ignore() is the closest and I think it would suffice.
In C scanf("%[^\n]%*c"); would remove all the redundant characters like spaces, newline, alphaNumerics form the buffer before/ after taking another input.
This is amiss in so many ways.
"%[^\n]%*c" scans 1 or more non-'\n' (Attempting to save them) and then 1 '\n'. There must exist a leading non-'\n' else the scanning stops. There is nothing special about spaces and alphanumeric - just '\n' and non-'\n'.
Undefined behavior: "%[^\n]" lacks a matching pointer to save the input. Even with a matching char *, it lacks a width and is prone to buffer overflow. It is worse than gets().
With an input of only "\n", nothing is consumed, nothing is saved. scanf("%[^\n]%*c"); fails to consume anything if the first character is a '\n'. Without checking the return value, the calling code does not know if anything was read. The matching char *, if it was there, is unchanged or potentially indeterminate.
Do not use scanf("%[^\n]%*c"); or its C++ equivalent std::scanf("%[^\n]%*c");
OP's update to scanf("%d%*[^\n]%*c", &num); is still faulty and should not be used in robust code.
It risks undefined behavior due to int overflow. It does not check the return value.
It does not consume the rest of the line when the numeric text is followed by a '\n'. That '\n' remains in stdin.
A better C approach begins with fgets() and checking return values.
Using C++20 onwards, you might want to use std::format. This is basically an implementation of FMT into the standard C++.
For more complex scenarios regular expressions should help.
Related
I am trying to read the last integer from an input such as-
100 121 13 ... 7 11 81
I'm only interested in the last integer and hence want to ignore all
previous integers.
I thought of using cin.ignore but that won't work here due to
unknown integers (100 is of 3 digits, while 13 is of 2 digits & so on)
I can input integer by integer using a loop and do nothing with them. Is there a better way?
It all depends on the use case that you have.
Reading a none specified number of integers from std::cin is not as easy at it may seem. Because, in contrast to reading from a file, you will not have an EOF condition. If you would read from a file stream, then it would be very simple.
int value{};
while (fileStream >> value)
;
If you are using std::cin you could try pressing CTRL-D or CTRL-Z or whatever works on your terminal to produce an EOF (End Of File) condition. But usually the approach is to use std::getline to read a complete line until the user presses enter, then put this line into a std::istringstream and extract from there.
Insofar, one answer given below is not that good.
So, next solution:
std::string line{};
std::getline(std::cin, line);
std::istringstream iss{line};
int value{};
while (iss >> value)
;
You were asking
Is there a better way?
That also depends a little. If you are just reading some integers, then please go with above approach. If you would have many many values, then you would maybe waste time by unnecessarily converting many substrings to integers and loose time.
Then, it would be better, to first read the complete string, then use rfind to find the last space in the string and use std::stoi to convert the last substring to an integer.
Caveat: In this case you must be sure (or check with more lines of code) that there are no white space at the end and the last substring is really a number. That is a lot of string/character fiddling, which can most probably avoided.
So, I would recommend the getline-stringstream approach.
You can try this simple solution for dynamically ignoring rest of the values except the last given in this problem as shown:
int count = 0;
int values, lastValue; // lastValue used for future use
std::cout << "Enter your input: ";
while (std::cin >> values) {
lastValue = values; // must be used, otherwise values = 0 when loop ends
count++;
}
std::cout << lastValue; // prints
Note: A character must be required to stop the while(), hence it's better put a . at last.
Output example
Enter your input: 3 2 4 5 6 7.
7
Try this:
for( int i=0; i<nums_to_ignore; i++) {
int ignored;
std::cin >> ignored;
}
I am trying to take multiple lines of string input (may contain spaces) in c++ using 2D char array but the loop gets terminated without taking any input for n=1 in the code:
When n=2, it takes only one input and when I try to print input[0], it prints blank. But for cout<
char input[100][100];
int n,i;
cout<<"Enter no of lines : ";
cin>>n;
cout<<"Enter "<<n<<" sentences : "<<endl;
for(i=0;i<n;i++)
cin.getline(input[i],100);
This is a common problem when mixing formatted and unformatted input. After a formatted input, the internal buffer is positioned before the first blank character and before the \n. The bullet proof way would be to always use getline and then scan the first line to extract the number of lines. But for such a simple case, it is enough to use a dummy getline after reading the number of line to skip the end of line:
char input[100][100];
int n,i;
cout<<"Enter no of lines : ";
cin>>n;
cin.getline(input[0], 100); // skip the end of line
cout<<"Enter "<<n<<" sentences : "<<endl;
for(i=0;i<n;i++)
cin.getline(input[i],100);
But:
you should always test cin after a read (what if the user types erroneously e instead of 4?)
you should avoid char arrays and always use string in C++ (simpler, cleaner, less error prone)
When you enter number of lines(say 4) you press 4 and then enter key. It is stored as 4\n in stdin that is standard input. When you read using cin.getline() you are reading \n. You will have to use cin.ignore to ignore existing buffer in stdin. However using >> operator is better since it handles newlines.
For multiline input you can input a third parameter to getline(): a delimiter specifying what indicates the end of your input.
I tried to compare std::cin and scanf, I expected them to have same behavior, but actually not:
#include<iostream>
using namespace std;
int main()
{
int i;
cin>>i;
return 0;
}
This receives an input from user, no problem.
But
#include<stdio.h>
int main()
{
int i;
scanf("%d\n",&i);
return 0;
}
I input a integer, program doesn't terminate even if I press "enter" multiple times, unless I enter another integer number.
Note there's an "\n" in scanf's format string.
So I tried to add one statement
printf("%d\n", i);
Well it prints out the 1st number I just input. This is correct but weird, why after scanf, the program requires me to enter any character rather then \n, to exit the program?
I tried both VC and GCC, same problem. What is that \n indicating?
scanf("%d\n",&i);
Let's read the manpage of scanf :
Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
What it means is scanf will search for a integer followed by an optionnal whitespace. that's why he's waiting for you to use two times enter. If you used "%d\n\n", it'll have to be three times. And so on.
If you want only an interger, use scanf("%d",&i);
scanf("%d\n",&i); is equivalent to std::cin >> i >> std::ws;.
If you want the same behaviour for scanf, remove \n: scanf("%d",&i);
This is caused by the fact that any whitespace character in scanf means "skip input until non-whitespace is found"
In C++ , Is this a valid/efficient way to input a series of characters ?
As in :
char abc[100];
cout<<"Enter your address:";
cin>>abc;
This says :
However, cin extraction always considers spaces (whitespaces, tabs, new-line...) as terminating the value being extracted, and thus extracting a string means to always extract a single word, not a phrase or an entire sentence.
Since the above statement is given for Strings and not character arrays , I am confused .
Will this code work properly ?
Note : I am using TurboC++
If you want to read only non-whitespace characters, you can use:
char abc[100];
cout<<"Enter your address:";
cin >> abc;
However, that is risky. If the sequence of non-whitespace characters consists of 100 or more characters, you will run into the problem of accessing memory out of bounds, which will lead to undefined behavior.
If you want to read everything up to a the newline character, you can use:
char abc[100];
cout<<"Enter your address:";
cin.getline(abc, 100);
This has the added advantage that it will not read more than 99 character, saving the last space for the null terminator.
More details on istream::getline() can be found at http://en.cppreference.com/w/cpp/io/basic_istream/getline.
I wish to take inputs from console where the number of inputs are not known. All i know is that they are less then or equal to 10.
I wrote this code but it evaluates the last value twice.
int x;
do{
cin>>x;
cout<<check(x)<<"\n";
}while(std::cin);
The inputs are in this form:
12
2
45
As #LightnessRacesinOrbit commented, it's while(!eof) bug again. You should check the stream state after reading from it, not before.
You can use cin>>x in the while-condition and apply a special value (i.e. anything not a number) as the end flag like this:
while (cin >> x)
{
// got a value
}
You may use istream::geline.
char input[1024]
std::cin.getline (input,1024);
After you read the line, you have to split it by white-spaces as delimiter. Just ignore 11th split onwards. And you may apply atoi or similar functions on the splits (some_split.c_str()) to get the numeric values