Search code examples
c++ioscanf

Take only digit as input by scanf() and avoid other characters


I want to take the following format of input using scanf() until EOF that will avoid '+' sign and store only integer value.

Input sample:

1+2+8 

Output for the above input:

1 2 8

I wrote the following code for this:

 while(scanf("%d+",&tmp)) //here 'tmp' is int type variable
 {
    v.push_back(tmp);   //'v' is vector<int> type
 }

 for (int i = 0; i < v.size(); i++)
 {
    cout<<v[i]<<" ";
 }

Unfortunately, the while loop works as a infinite loop. What will be the solution for this problem?


Solution

  • std::cin solution

    Since you are already using std::cout1, you can use std::cin instead of scanf. Now, read the number first, and handle the sign after:

    std::vector<int> numbers;
    for (int n; std::cin >> n;) {
        numbers.push_back(n);
        if (std::cin.peek() == '+') { // if the next character is '+'
            std::cin.get();           // then discard it
        }
    }
    

    scanf solution

    If you insist on using scanf (in which case you probably should be using printf as well), you can use the ignore functionality of the control string of scanf:

    std::vector<int> numbers;
    for (int n; std::scanf("%d%*1[+]", &n) == 1;) { // optionally discard '+' after number
        numbers.push_back(n);
    }
    

    Let's break the %*1[+] conversion specification down:

    • % — the beginning of every conversion specification;

    • * — the result of this conversion should be discarded, rather than assigned to an argument;

    • 1 — the width of the conversion (i.e., the maximum number of characters to convert); and

    • [+] — the format specifier which means to match the longest string comprising + exclusively (subject to the width constraint, of course).

    Altogether, this conversion specification means "discard at most one + character".

    If no + sign is present, the scanf will return because consuming zero characters for a field results in a conversion error. The next character will not be consumed (which is expected).

    Note that scanf returns number of receiving arguments (arguments after the format string) successfully assigned (which may be zero in case a matching failure occurred before the first receiving argument was assigned), or EOF if input failure occurs before the first receiving argument was assigned — see the cppreference page.


    1 You are actually writing cout, which is hopefully std::cout brought in scope by using std::cout or using namespace std;.