0

In the below program, it works fine when I input string of length less than or equal to 10 but when I exceed the string length, getline works fine but the subsequent input statement won't work (not taking input) /* used proper header */

int main () 
{
int a,b;
char s[10];
cin>>a;  //work fine
cin.ignore(); 
cin.getline(s,10); // work fine but if the length of string is more than 10...

cin>>b;  //...this line doesn't work
cout<<"a="<<a<<"s="<<s<<" b="<<b;
getch();
}

2 Answers2

1

Here is your solution:

#include <climits>
#include <iostream>
using namespace std;

int main() {
    int  a, b;
    char s[11]; // <-- Size should be 11, the last character will be '\0'
    cin >> a;
    cin.ignore(); // better change it to cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cin.getline(s, 11); // <-- this line sets failbit if the input exceeds 10 characters

    // add these lines :
    if (!cin) { // <-- checks if failbit is set
        cin.clear(); // <-- clears the set flags
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); // <-- ignores the whole line
    }
    // if anything had gone bad, it has been fixed by now

    cin >> b;
    cout << "a = " << a << "\ns = " << s << "\nb = " << b;
}


A more complex but better one:

#include <climits>
#include <iostream>
using namespace std;

int main () 
{
    cin.exceptions(ios_base::failbit|ios_base::badbit); // <-- tells compiler to treat failbit and badbit as exceptions
    int a, b;
    char s[11];
    cin >> a;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    try {
        cin.getline(s, 11);
    } catch (ios_base::failure &e) {
        // cerr << e.what() << endl;
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    cin >> b;
    cout << "a = " << a << "\ns = " << s << "\nb = " << b;
}
brc-dd
  • 10,788
  • 3
  • 47
  • 67
  • @Hack06 I just read your comment on the question: *You should make your variable s as a pointer to...* Firstly, the approach you are suggesting using pointers is very much complex. The case is not of VLAs or dynamic arrays. You don't even know how long your string is gonna be. For that approach you'll need to keep on resizing your array, copying contents... Better way is to directly use `std::string`. Secondly, OP is explicitly using here a static array. Suggesting him to use `std::string` is surely not a solution. If he'd been using `string`, he may not have even experienced such thing. :) – brc-dd Jul 14 '20 at 11:51
  • Thanks for the solution, it works for me. Thanks a ton. – Saurabh Shukla Jul 16 '20 at 22:09
-1

Simple solution , use scanf("%[^\n]",s) instead

It reads a whole line into an array until you press Enter key. You can modify it as you want. Just replace ‘\n’ with the character you want to be the end of the input.

Here's how in your case :

    int main () {

        int a,b;
        char s[10];

        cin>>a; 
        cin.ignore(); 
        scanf("%[^\n]",s);
        cin>>b;      

        cout<<"a="<<a<<"s="<<s<<" b="<<b;

        return 0;

    }
vishwampandya
  • 1,067
  • 11
  • 11
  • 1
    Hey better give this a look : [Why is the gets function so dangerous that it should not be used?](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) and modify/delete your answer. – brc-dd Jul 14 '20 at 11:53
  • Thank you very much for your advice, I got to know later that using gets() function was really dangerous. Now I have changed my approach. – vishwampandya Jul 14 '20 at 12:43
  • Your approach still has a problem. Firstly, `s` should be of `11` characters, since it has to hold a `\0` char at the end. Secondly, you need to explicitly set `s[10] = 0` after your `scanf`, otherwise `cout << s` will simply print an array of `11`(not `10`) characters plus an extra character which may appear like a block or some special symbol (garbage value). Thirdly, no need to do a `cin.ignore()` before `scanf()`, change format string to `" %[^\n]"`. Notice the space before `%`, it'll do the work of `ignore`. – brc-dd Jul 14 '20 at 13:04
  • *Continuing the above comment...* Fourth, `scanf` will not work for inputs like `hello world` as `scanf` terminates scanning for a specifier as soon as it encounters a white space. I believe that's the sole logic behind using `getline`, otherwise, if he had string not having any spaces, he may have used directly `cin >> s;` :) – brc-dd Jul 14 '20 at 13:10