Sign in to follow this  
Kris2456

[C++] few questions re. file I/O

Recommended Posts

Kris2456    100
Hi. I am trying to write a program that analyzes the path of ants, however i have some questions about file i/o. 1. Is there anyway to open the file without having to ask at runtime. IE. is it possible to get your program to open files like windows does? So you drop the file on the programs' icon and it auto opens that file. 2. When reading in data how do i skip a line after having read in only two values? 3. When reading in from a set of directories in the programs directory, how do i write these in C++. IE: like this? "Ants/data/path/path1.txt".

Share this post


Link to post
Share on other sites
MJP    19755
Quote:
Original post by Kris2456
1. Is there anyway to open the file without having to ask at runtime. IE. is it possible to get your program to open files like windows does? So you drop the file on the programs' icon and it auto opens that file.


If you do this in windows, the name of the file dropped on the icon will be the first thing in your command line string. There's also ways to things like have your program open a file when an icon is dragged and dropped onto the application window, but this gets much more complicated.


Quote:
Original post by Kris2456
2. When reading in data how do i skip a line after having read in only two values?


Depends on which function/class you're using for file i/o. With std::ifstream, you can simply use getline to retrieve an entire lines at a time and store it in a string. So you could just call that and disregard the string it gives you.

Quote:
Original post by Kris2456
3. When reading in from a set of directories in the programs directory, how do i write these in C++. IE: like this? "Ants/data/path/path1.txt".


This depends on the file system. In most common operating systems, that string will be added to the working directory. So for example if you were running your app in "c:\MyApp\" and you opened a file using that above string, you would be opening up "c:\MyApp\Ants\data\path\path1.txt".

Share this post


Link to post
Share on other sites
Kris2456    100
Thanks for your help on that.

However what i meant by the "skip a line" question is this.

The file looks like this:

Time | X | Y | Obs. | Behav

I only care about the X and Y colums, but i dont care about the rest. What makes it worse is, is that sometimes the Behav column is ommited meaning the lines are not always 5 values long. What i want to do is read in (and ignore) time, then x & y, and then go to the next line.

Share this post


Link to post
Share on other sites
Doggan    528
Quote:
Original post by Kris2456
Thanks for your help on that.

However what i meant by the "skip a line" question is this.

The file looks like this:

Time | X | Y | Obs. | Behav

I only care about the X and Y colums, but i dont care about the rest. What makes it worse is, is that sometimes the Behav column is ommited meaning the lines are not always 5 values long. What i want to do is read in (and ignore) time, then x & y, and then go to the next line.


If you use getline() like the previous poster mentioned, you will end up with a string containing the entire line: Time | X | Y | Obs. | Behav. You can then parse this yourself (in code), with the logic for parsing X, and Y - ignoring the rest of the line (time, obs, behav). With getline(), it doesn't matter if there is a Behav column or not - you deal with this in your actual code when parsing the string.

Share this post


Link to post
Share on other sites
Kris2456    100
I have tried to find some examples of code to extract the floating point values from the output of getline() but so far i have only found examples where they use pieces of text.

Anyone got a suggestion on how to do this?

Share this post


Link to post
Share on other sites
rip-off    10976
You can use a stringstream to parse a string. A stringstream is like an fstream, except its data source is a string in memory:

#include <fstream>
#include <sstream>
#include <string>

void foo(const std::string &filename)
{
std::ifstream in(filename.c_str());
std::string line;
while(std::getline(in,line))
{
std::stringstream stream(line);
std::string type;
stream >> type;

if(type == "Time")
{
float x, y;
stream >> x >> y;
// use x and y
}
else if(/* others... */)
{
// ...
}
else
{
// bad line error, or just ignore it
}
}
}



Although it isn't relevant to your problem, you should note also that you can add things to a stringstream instance, and then obtain a string from the entire stream. This can be very handy. Example:

std::stringstream stream;
stream << "Time " << x << y;
// use stream.str()

Share this post


Link to post
Share on other sites
Kris2456    100
Ok, so this is really wierd.

I've set up everything like you said (great stuff btw), but i am having the following problem.

I have a loop:


while(getline(fin,str))
{
line<<str;
line>>time>>current.x>>current.y;

line.clear();
...


line is a stream, while str is a string.

This does indeed get a line, but it does something odd.
Imagine this is my file:

1 2 3 4
5 6 7 8

it reads in 1, then 2 and 3. However, instead of going to the next line like i want it to, and read in 5,6, and 7. It reads in 4,5, and 6.

Its almost like it does not skip a line, but continues on. Any help would be appreciated.

Share this post


Link to post
Share on other sites
rip-off    10976
std::stringstream::clear() only resets the error bits. It does not empty the stringstream. Look closely at my code. I create the stringstream inside the loop so you are always dealing with a fresh one.

There are ways of "resetting" a stringstream, but TBH I am not convinced they are worth it in this case. Your bottleneck in this case will be the hard drive, not stringstream creation.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this