Reading different types of variables from a file in C++ - 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++ .

Related

c++ ifstream Skipping Data

I'm trying to get my program to read two lines out of a six line data file (the other four are two sets of two that are meant to be read to other objects). However, I can only get it to read one -- either the first or the second depending on how I manipulate the code.
Here's what's in my data file:
Mustang Sally
123.45
George Porge
11.99
J. D. Rockerfeller
56321.3
And here's the section of the code where I need to read said data:
void account::readAccount(ifstream &inFile)
{
while (getline(inFile, name))
{
inFile.ignore();
inFile >> savings;
}
}
The code above is only reading in the second line.
I think I'm having a phantom newline problem, which I can't seem to resolve, but I also feel that there's another problem on top of that, which I can't comprehend with my current level of experience regarding file streams.
The code above is only reading in the second line.
Yes because you tell it to ignore. I don't know what exactly two lines you want to get from these, but based on the codes, I'm assuming that you want to read the values at line 2,4. The following code will print out those two lines.
float savings = 0.0f;
while(getline(inFile,line))
{
if(savings > 0.0f) cout << savings << endl;
inFile >> savings;
inFile.ignore(1000, '\n' );
}

Line Breaks when reading an input file by character in C++

Ok, just to be up front, this IS homework, but it isn't due for another week, and I'm not entirely sure the final details of the assignment. Long story short, without knowing what concepts he'll introduce in class, I decided to take a crack at the assignment, but I've run into a problem. Part of what I need to do for the homework is read individual characters from an input file, and then, given the character's position within its containing word, repeat the character across the screen. The problem I'm having is, the words in the text file are single words, each on a different line in the file. Since I'm not sure we'll get to use <string> for this assignment, I was wondering if there is any way to identify the end of the line without using <string>.
Right now, I'm using a simple ifstream fin; to pull the chars out. I just can't figure out how to get it to recognize the end of one word and the beginning of another. For the sake of including code, the following is all that I've got so far. I was hoping it would display some sort of endl character, but it just prints all the words out run together style.
ifstream fin;
char charIn;
fin.open("Animals.dat");
fin >> charIn;
while(!fin.eof()){
cout << charIn;
fin >> charIn;
}
A few things I forgot to include originally:
I must process each character as it is input (my loop to print it out needs to run before I read in the next char and increase my counter). Also, the length of the words in 'Animals.dat' vary which keeps me from being able to just set a number of iterations. We also haven't covered fin.get() or .getline() so those are off limits as well.
Honestly, I can't imagine this is impossible, but given the restraints, if it is, I'm not too upset. I mostly thought it was a fun problem to sit on for a while.
Why not use an array of chars? You can try it as follow:
#define MAX_WORD_NUM 20
#define MAX_STR_LEN 40 //I think 40 is big enough to hold one word.
char words[MAX_WROD_NUM][MAX_STR_LEN];
Then you can input a word to the words.
cin >> words[i];
The >> operator ignores whitespace, so you'll never get the newline character. You can use c-strings (arrays of characters) even if the <string> class is not allowed:
ifstream fin;
char animal[64];
fin.open("Animals.dat");
while(fin >> animal) {
cout << animal << endl;
}
When reading characters from a c-string (which is what animal is above), the last character is always 0, sometimes represented '\0' or NULL. This is what you check for when iterating over characters in a word. For example:
c = animal[0];
for(int i = 1; c != 0 && i < 64; i++)
{
// do something with c
c = animal[i];
}

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.

How do I input variables using cin without creating a new line?

Whenever I input a variable using cin, after one hits enter it automatically goes to a new line. I'm curious if there's a way to use cin without having it go to a new line. I'm wanting to cin and cout multiple things on the same line in the command prompt. Is this possible?
You can't use cin or any other standard input for this. But it is certainly possible to get the effect you are going for. I see you're on Windows using Visual Studio, so you can use, for example, _getch. Here's an example that reads until the next whitespace and stores the result in a string.
#include <conio.h> // for _getch
std::string get_word()
{
std::string word;
char c = _getch();
while (!std::isspace(c))
{
word.push_back(c);
std::cout << c;
c = _getch();
}
std::cout << c;
return word;
}
It's not very good. For example, it doesn't handle non printing character input very well. But it should give you an idea of what you need to do. You might also be interested in the Windows API keyboard functions.
If you want a wider audience, you will want to look into some cross-platform libraries, like SFML or SDL.
you can also use space for input instead of enter
something like this:
cin >> a >> b >> c;
and in input you type
10 20 30
then
a=10
b=20
c=30
As others have noted, you can't do this with cin, but you could do it with getchar(). What you would have to do is:
collect each character individually using getchar() (adding each to the end of a string as it is read in, for instance), then
after reading each character, decide when you've reached the end of one variable's value (e.g. by detecting one or more ' ' characters in the input, if you're reading in int or double values), then
if you've reached the end of the text for a variable, convert the string of characters that you've built into a variable of the appropriate type (e.g. int, double, etc.), then
output any content onto the line that might be required, and then
continue for the next variable that you're reading in.
Handling errors robustly would be complicated so I haven't written any code for this, but you can see the approach that you could use.
I don't think what you want to do can be achieved with cin. What you can do is to write all your input in one line, with a delimiter of your choosing, and parse the input string.
It is not possible. To quote #Bo Persson, it's not something controlled by C++, but rather the console window.
I can't comment but if you leave spaces between integers then you can get the desired effect. This works with cin too.
int a, b, c;
cin>>a; cin>>b; cin>>c;
If you enter your values as 10 20 30 then they will get stored in a, b, and c respectively.
just use the gotoxy statement. you can press 'enter' and input values in the same line
for eg. in the input of a 3*3 matrix:
#include<iostream.h>
#include<conio.h>
void main()
{clrscr();
int a[20][20],x,y;
cout<<"Enter the matrix:\n ";
for(int r=2;r<7;r+=2)
for(int c=2;c<7;c+=2)
{gotoxy(c,r);
cin>>a[r][c];
}
getch();}

Trying to use a while statement to validate user input C++

I am new to C++ and am in a class. I am trying to finish the first project and so far I have everything working correctly, however, I need the user to input a number to select their level, and would like to validate that it is a number, and that the number isn't too large.
while(levelChoose > 10 || isalpha(levelChoose))
{
cout << "That is not a valid level" << endl;
cout << "Choose another level:";
cin >> levelChoose;
}
That is the loop I made, and it sometimes works. If I type in 11 it prints the error, and lets me choose another level. However if the number is large, or is any alpha character it floods the screen with the couts, and the loop won't end, and I have to force exit. Why does it sometimes stop at the cin and wait for user input, and sometimes not? Thanks for the help!
This is an annoying problem with cin (and istreams in general). cin is type safe so if you give it the wrong type it will fail. As you said a really large number or non-number input it gets stuck in an infinite loop. This is because those are incompatible with whatever type levelChoose may be. cin fails but the buffer is still filled with what you typed so cin keeps trying to read it. You end up in an infinite loop.
To fix this, you need to clear the fail bit and ignore all the characters in the buffer. The code below should do this (although I haven't tested it):
while(levelChoose > 10 || isalpha(levelChoose))
{
cout << "That is not a valid level" << endl;
cout << "Choose another level:";
if(!(cin >> levelChoose))
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
Edit: numeric_limits<> is located in the limits include:
#include<limits>
From your description, it seems likely (nearly certain) that levelChose is some sort of numeric type, probably an integer.
When you use operator>> to read a number, anything that couldn't be part of a number (e.g., most letters) will be left in the input buffer. What's happening is that you're trying to read the number, it's failing and leaving the non-digit in the buffer, printing out an error message, then trying to read exactly the same non-digit from the buffer again.
Generally, when an input like this fails, you want to do something like ignoring everything in the input buffer up to the next new-line.
levelChoose appears to be an integer type of some form (int, long, whatever).
It's not valid to input a character into an integer directly like that. The input fails, but leaves the character in the incoming buffer, so it's still there when the loop comes around again.
Here's a related question: Good input validation loop using cin - C++
I suspect the part while(levelChoose > 10..... This does not restrict level to less than 10 (assuming greater than 10 is a large number in your context). Instead it probably should be while(levelChoose < 10...
To check that an expression is not too large, the following could be a possibility to validate (brain compiled code!!)
const unsigned int MAX = 1000;
unsigned int x;
cin >> x;
while(x < MAX){}