Validation for float in c++ [closed] - c++

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am getting input as a float. For example if the user is entering in 3.5 then it works fine. If user enters in 3.X or any other characters it is causing an infinite loop. is there any way in which i can validate the variable so that user can enter only numbers? I am using gcc compiler.

The usual way is to read the data as a string, then convert it to a float, and see of the entire input string was consumed in that conversion. Boost lexical_cast (for one example) can automate most of that for you.

You don't give any sample code, so we can see what you're doing, but I
suspect from the symptoms that you're doing something like:
while ( ! input.eof() ) {
double d;
input >> d;
// do someting with d...
}
There are two problems with this: the first is that once an error occurs
(because 'X' cannot be part of a double), the stream memorizes the
error until it is explicitly cleared, so all following input also fails
(and no further characters are extracted from the string). When you
have a format error in a stream, it is necessary to reset the error
state before continuing.
The second problem with the above is that input.eof() doesn't mean
much until after input has failed; it's not a very useful function.
What you probably want to do is:
double d;
while ( input >> d ) {
// do something with d
}
This will stop reading on the first error. If you want to recover from
errors and continue, then you need something more elaborate:
double d;
while ( input >> d || !input.eof() ) {
if ( input ) {
// do something with d...
} else {
// format error...
input.clear(); // reset the error state...
// advance the stream beyond the error:
// read to next white space (or EOF), or at least
// advance one character.
}
}
Alternatively, it's often more robust to do as others have suggested,
read the input line by line, then scan the line:
std::string line;
while ( std::getline( input, line ) ) {
std::istringstream l( line );
double d;
if ( l >> d >> std::ws && d.get() == EOF ) {
// do something with d...
} else {
// format error...
// we don't have to clear or skip ahead, because we're
// going to throw out the istringstream anyway, and the
// error didn't occur in the input stream.
}
}
This imposes a much more rigorous format: one value per line, but if
you count the lines, you can output the line number in the error
message; the person who has to correct the bad input will appreciate
that.

try
{
double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
from: How to determine if a string is a number with C++?

The best way for reading a double value from input and assuring it's well formed is reading the input as a string, and then parsing it using the standard strtod function included in the stdlib library.
For a more detailed explanation on some different possibilities when parsing that string you can check this other post.

Your post i somewhat unclear, but from what I understand, i think you should use strtof.
Get your data from the user as String, than use the function to convert to float and check if succeeded by comparing the pointers.
for more info check the man pages for strtof.

Related

Ifstream in c++

I need some help with a code.
I need to take this information to my c++ code from another file, the last one is just like this:
Human:3137161264 46
This is what I wrote for it, it takes the word "Human" correctly but then it takes random numbers, not the ones written on the file I just wrote:
struct TSpecie {
string id;
int sizeGen;
int numCs; };
__
TSpecie readFile(string file){
TSpecie a;
ifstream in(file);
if (in){
getline(in,a.id,':');
in >> a.sizeGen;
in >> a.numCs;
}
else
cout << "File not found";
return a; }
Hope you can solve it and thanks for your help
3137161264 causes integer overflow leading to Undefined Behaviour.
So unsigned int sizeGen would be enough for this case, but consider long long (unsigned) int sizeGen too.
Edit 1: As pointed out by #nwp in comments to your question, you can also check your stream if any error has occured:
//read something and then
if (!in) {
// error occured during last reading
}
Always test whether input was successful after reading from the stream:
if (std::getline(in, a.id, ':') >> a.sizeGen >> a.NumCs) {
// ...
}
Most likely the input just failed. For example, the first number probably can't be read successful. Also note that std::getline() is an unformatted input function, i.e., it won't skip leading whitespace. For example the newline after the last number read is still in the stream (at least, since your use of std::getline() finishes on a colon, it will only create an odd ID).

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.

Reading different types of variables from a file in C++

I have a problem with my code in C++ and need some help. There are some related questions but I couldn't really understand the answers.
I have a text file ('parameters.dat' in the example below) that I want to read in with my code written in C++. The file includes different types of variables: Boolean, doubles and integers as well as some comments which I want to skip when reading.
My file looks something like that:
150 // this is an integer
4e-1 // this is a double
1.05 // another double
0 // this is a logical (Boolean) variable: 0 is false and 1 is true
A simple version of the code that I use is
int N;
double var_1, var_2;
bool inital;
ifstream read_parameters;
read_parameters.open("parameters.dat");
read_parameters >> N >> var_1 >> var_2 >> initial;
read_parameters.close();
The comments seem to ruin everything and even without them there seem to be some problems with reading the logical variables correctly. The file that I try to read is made by me, so I can substitute the '//' above with something else if necessary. Does anyone have any advice?
Thanks in advance!
Simple, cheesy way:
Read a token then read_parameters.ignore(numeric_limits<streamsize>::max(), '\n') to discard the rest of the line. eg:
read_parameters >> N;
read_parameters.ignore(numeric_limits<streamsize>::max(), '\n');
read_parameters >> var_1;
read_parameters.ignore(numeric_limits<streamsize>::max(), '\n');
...
This doesn't care if a comment exists or not, but requires modification if you have two or more tokens on a line.
Oh, and remember to test the state of the stream after reading. Plugging in "fubar" for one of the doubles will currently ruin things. read_parameters will be in an error state that needs to be cleared before you can read it again.
if (!read_parameters >> N)
{
std::cerr << "bad input for parameter N" << std::endl;
read_parameters.clear();
}
read_parameters.ignore(numeric_limits<streamsize>::max(), '\n');
Is better, but you probably want to handle an error with something better than a printline.
Take input in a Dynamic Character array then run a for loop in which if a character has ascii 65 - 97 - onward then it will be Alphabet and else if ascii represents integers like 1,2,3 then separte them in another array after calculating total integers as count++ .

c++: istringstream

I am creating a simple command parser using c++, and I am trying to use istream >> to check whether I am inputting a number or a character.
input:
a = 10
b = a
parser.cpp:
string inputLine, varLeft, equal, varRight;
double varValue
// please see update below
while(getline(cin, inputLine)){
istringstream stringSplitter(inputLine);
stringSplitter >> varLeft >> equal;
if(!(stringSplitter >> varValue)){
stringSplitter >> varRight;
}
}
The goal is, later in the code, if varRight is empty, I assume that the line of input was a double literal, otherwise, it's a string that denotes a variable. I understand there might be logical errors associated with mixed input starting with digits, but I am assuming that all input is correctly formatted for now. Why is the a in the second line of input discarded? What fix do you propose?
Update
The problem is not with the while loop statement, it is with the if statement at the end of the while code block.
In the actual code, the loop is not actually a while loop; I am using a vector object holding string commands, and iterating through them using a for loop which goes through the vector using iterators. But, in order to please the commenters, I have fixed it above.
If an input function fails, the stream will not allow any more extractions until you clear the failure state. You'll need to do that, after you've checked that the input to varValue failed, with std::basic_ios::clear:
if(!(stringSplitter >> varValue)){
stringSplitter.clear();
stringSplitter >> varRight;
}
I don't know how you're doing /* not end of input */ at the moment (hopefully you're not checking eof()!), but it's recommended that you do:
while (getline(cin, inputLine)) {
// ...
}
This checks that the line input was successful before diving into the loop.

Problems with garbage characters when reading file [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
I'm having trouble reading data from a file, and concatenating selected parts of the data (text) into a buffer of my own.
The code is like follows:
char buffer[1000];
char* allNewData = (char *)malloc(10000);
while (! myfile.eof() )
{
myfile.getline (buffer, 1000);
pch = strstr (buffer,"bla bla");
if(pch == NULL)
{
char* temp = buffer;
strcat(allNewData, temp);
strcat(allNewData, "\n");
}
else
{
strcat(allNewData, "here's bla bla");
strcat(allNewData, "\n");
}
}
cout<<allNewData<<endl;
When I run the program, allNewData first has some garbage text, followed by the proper/expected results, like this:
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii <-rubbish data
hello <- actual data
I need to get rid of this rubbish data, how can I change the code to achieve this?
You need to clear your newly allocated buffer before using string concatenation functions. They expect a valid string, to be able to find the end and thus the start of where to concatenate.
Use:
allNewData[0] = '\0';
this makes allNewData into an empty string. Do this before the loop, before you start concatenating all the found data.
Also, your code needs to better take care of the various "gotchas" when it comes to I/O and handling memory:
Don't check for EOF before doing a read access.
Check that the read was successful, before using the results of the read.
Make sure you don't exceed the capacity of your buffer when storing data.
Some comments, which you may find helpful or disregard:
What if there is a line longer than 1000 characters? (and say, that 1001-1008 is 'blah blah')? The line will be split into two in your new file and there will be an extra line before "here's blah blah"? Is this now a bug or desired functionality?
What if the line is longer than 1000, but "blah" is 996-1000 and the second "blah" is on the second segment - now you've lost one
What if your file is longer than 10000 characters?
They may sound like trivial questions, but answering them correctly will mean that you'll have to change your approach, I suggest purer C++ approach:
ifstream f_in(<file>);
ostringstream s_out;
string line;
while(f_in.good())
{
getline(f_in, line); // global getline function in <string>
if (line.find("blah blah") != string::npos)
{
s_out << "here's blah blah" << endl;
}
else
{
s_out << line << endl;
}
}
This way you don't have to worry about any of the questions above...
You can also use a combination of getline and ignore
Again... you have to check that your IO operation don't fail and eof() should be used only after a failed IO operation.