I have written a root macro that first asks the user for several parameters. As I update this macro, running it often to see the effect of my changes, it is a nuisance to have to re-enter a bunch of parameters each time I run it. I would like to modify the macro so that some default value is assigned to each parameter should the user hit “enter” instead of typing a number. Then I can run the macro and hit enter a bunch of times to get it to start quickly. I have tried many different approaches to this, all of which work using a regular c++ compiler, but none work within root. An example of my code is:
#include "Riostream.h"
int rootws()
{
Int_t* ptr = new Int_t;
cout << "Enter int: ";
cin.unsetf(ios::skipws);
cin >> *ptr;
if(!cin.good())
{
cout << "Not an integer " << endl;
}
else cout << "the number is " << *ptr << endl;
delete ptr;
return 0;
}
This is what happens in root:
[0] .L rootws.C
root [1] rootws()
Enter int: <- just hit enter here
Not an integer
(int)0
root [2] rootws()
Enter int: Not an integer <- didn’t type anything here
(int)0
root [3]
So it works the first time, but, unless I quit and re-open Root, every succesive time it appears to assume something has already been typed (or at least that an error flag is already set- I have tried resetting the error bits to no avail). It does not matter what I type the first time around, successive runs always give the result seen above.
delete ptr;
} [/code]should have the behavior you want. (Note that I am not sure why you unset the skipping of white space, this seems to make thing much more complex).
I am unsetting the skip whitespace flag because I do not want to ignore the instance when only return is pressed (doing this should provide my macro with a default value). Your code hangs until a character or number is typed.
It seems that the problem originates with unsetting this flag, as removing that line removes the original problem.(although of course it adds the new problem of doing nothing when only return is pressed, and that’s the whole point of what I’m trying to do)
I tried resetting the flag after the if statement, but this did not work either.
This code will do what I need. Thank you very much for your help.
Read on only FYI if you have time to spare…
This code does still have a problem if the user enters a value that is not a number and not whitespace. (This is of course irrelevant for my macro since the user should never enter anything other than those two.) When N of these characters are typed, the macro must be re-run N times before allowing new input:
root [37] rootws()
Enter int: …hey
h…Not an integer 99
root [38] rootws()
Enter int: …e…Not an integer 99
root [39] rootws()
Enter int: …y…Not an integer 99
root [40] rootws()
Enter int: …
…Not an integer 99
I do not fully understand the concept of consuming characters, but if I had to guess I’d say cin causes parts of the stream to be consumed or removed, but our three cin statements only consume integers, whitespaces, and the single next non-number, non-whitespace character. I believe using cin.getline solves this problem (provided the user doesn’t type more than 15 characters):
#include "Riostream.h"
void rootws()
{
Int_t* ptr = new Int_t;
*ptr = 99;
Char_t str[15];
cout << "Enter int: ";
cin.unsetf(ios::skipws);
cin >> *ptr;
if(!cin.good())
{
cout << "Not an integer " << *ptr << endl;
cin.clear();
}
else cout << "the number is " << *ptr << endl;
//get next character
Char_t c;
cin >> c;
//if next character is not ws, consume up
//to the next 15 characters and newline
if(!isspace(c))
{
cin.getline(str, 15, '\n');
}
cin.clear();
delete ptr;
}
This just seems like a lot of code to do something simple. Is there no way to flush out the stream succinctly or delete then recreate the stream object?