Page 1 of 2

[Solved] STL Question

Posted: Sat Jun 20, 2009 8:19 am
by zodiac976
I am having a problem on one of my projects and I am wondering if anyone
knows an STL container that can take data from a file then take a chunk of
the data at the end of the container and move it to the top of the container
until all data is reversed but only the chunks of data. For example test.txt
file contains:
abc
123
newline*
def
456 end of file*


I want to take the data "def" and "456" and move them to the top while moving
"abc" and "123" down one including the newline, like a descending order but not
completely reverse every line like a list container does.

This is how I want the file to look after changing it.
same file contains:
def
456
newline*
abc
123 end of file*

Re: STL Question

Posted: Sat Jun 20, 2009 10:26 am
by zodiac976
I tried using a reverse iterator and even reverse() but they only flip
the whole data in the container upside-down and I also tried push_front
from the list container which does the same thing as reversing.

So far I am having no luck with this issue. :cry:

Re: STL Question

Posted: Sat Jun 20, 2009 11:36 am
by K-Bal
You can push std::strings in your container and read the file in whole lines. Then the reverse iteration should work.

Re: STL Question

Posted: Sat Jun 20, 2009 1:25 pm
by zodiac976
What I want to do is read from a text file and store it in a container then
move say 5 paragraphs of text from the very bottom of the container to
the top of the container while moving the rest of the data down.

It's similar to reversing it but I don't want it to reverse line by line just
the blocks of data, so that the container has what's in the text file but in
descending order.

When I used the reverse() or reverse iterator the data in the container was
rotated 180 degrees or flipped upside-down. :(

I wanted to be able to open the text file and just read the first few lines
so I can use the most recent data but I may have to read from the end of
the file backwards then print it out forward and finally extract the important
data I need from it. Of course I may scrap it and come up with another way. :lol:

Re: STL Question

Posted: Sat Jun 20, 2009 1:51 pm
by zodiac976
I figured out another way to finish this project and it's officially done;
just needs a few tweaks and error checking.

What I did was update my file that holds the important data right before
it writes to the file that keeps a list of actions you did during the program.

Sorry for all the walls of text :lol: and thanks for all the help. :)

Re: STL Question

Posted: Sat Jun 20, 2009 6:08 pm
by MarauderIIC
If you store each chunk as an item in a list, and then you start from the end of that list and go to the beginning, it outputs backwards. What a "chunk" is depends on you and how you process the input.

Re: STL Question

Posted: Sun Jun 21, 2009 8:14 am
by zodiac976
Do you think the STL map would work?

I haven't messed with a map much because they are a little hard
to understand at the moment but I am pretty comfortable with
vectors and lists.

*I might try storing the blocks of "strings" in an item and then
*put it in the list and use a reverse iterator.

Re: STL Question

Posted: Sun Jun 21, 2009 4:22 pm
by MarauderIIC
Maps associate some kind of key with some kind of value; one might use this for reading .ini files, for instance. But since you just want line numbers, vectors are fine.

I wrote this code straight into the forum. I think it'll do what you want -- take five paragraphs from the end and output them in front of the rest. Really the breakpoint (.end()-6) should be stored in a const_iterator, or something, but as I don't use them often, I'm not sure as to the syntax.

Code: Select all

#include <string>
#include <vector>
#include <fstream>
using namespace std;
/* ... */

ifstream file("myfile.txt");
string myChunk;
string myLine;
vector<string> myChunks;

while (file) {
    getline(file, myLine);
    if (myLine == "\n") { //get whole paragraphs that are separated by a newline. (so only add a paragraph to our list when there's a blank line)
        myChunks.add(myChunk);
        myChunk = "";
    } else {
        myChunk += myLine + "\n"; //getline() eats the newline.
    }
}

//.end() is one past the last entry. end()-1 is the last entry, end()-6 is the fifth from the end.
//Start at fifth from the end and go to the end
for (vector<string>::iterator i = myChunks.end()-6; i != myChunks.end(); ++i) {
    cout << *i << endl;
}

//Start at the beginning and go to the fifth from the end.
for (vector<string>::iterator i = myChunks.begin(); i != myChunks.end()-6; ++i) {
    cout << *i << endl;
}

Re: STL Question

Posted: Mon Jun 22, 2009 7:06 am
by zodiac976
MarauderIIC wrote:Maps associate some kind of key with some kind of value; one might use this for reading .ini files, for instance. But since you just want line numbers, vectors are fine.

I wrote this code straight into the forum. I think it'll do what you want -- take five paragraphs from the end and output them in front of the rest. Really the breakpoint (.end()-6) should be stored in a const_iterator, or something, but as I don't use them often, I'm not sure as to the syntax.

Code: Select all

#include <string>
#include <vector>
#include <fstream>
using namespace std;
/* ... */

ifstream file("myfile.txt");
string myChunk;
string myLine;
vector<string> myChunks;

while (file) {
    getline(file, myLine);
    if (myLine == "\n") { //get whole paragraphs that are separated by a newline. (so only add a paragraph to our list when there's a blank line)
        myChunks.add(myChunk);
        myChunk = "";
    } else {
        myChunk += myLine + "\n"; //getline() eats the newline.
    }
}

//.end() is one past the last entry. end()-1 is the last entry, end()-6 is the fifth from the end.
//Start at fifth from the end and go to the end
for (vector<string>::iterator i = myChunks.end()-6; i != myChunks.end(); ++i) {
    cout << *i << endl;
}

//Start at the beginning and go to the fifth from the end.
for (vector<string>::iterator i = myChunks.begin(); i != myChunks.end()-6; ++i) {
    cout << *i << endl;
}
Thanks, I will give it a try today and see.

Re: STL Question

Posted: Mon Jun 22, 2009 8:39 am
by zodiac976
I had to redo some of the code but it did help me figure it out,
so I have to thank you ;). The way I did it was just write the
text into the file upside-down in ascending order like this for
example:

myfile.txt:
line3a
line2a
line1a
*newline*
line3b
line2b
line1b *eof*

The last 3 lines of the text file are the most recent entry so when
I use this code below with that text file it flips it right side up,
with the most recent text at the top in the correct order for easy
extraction :).

Code: Select all

#include <iostream>
#include <fstream>
#include <string>
#include <list>
using namespace std;

int main()
{
	string read;
	list<string> container1;
	list<string>::iterator i;

	ifstream file1("myfile1.txt");
	while(!file1.eof())
	{   //stores the text from the file into the list
		getline(file1, read);
		container1.push_back(read);
	}
	file1.close();

	container1.reverse();   //reverses all text in the list

	ofstream file2("myfile2.txt");
	for (i = container1.begin(); i != container1.end(); i++)
	{   //prints out all the text from the list into the new file in descending order
		file2 << *i << endl;
	}
	file2.close();

	return 0;
}
If needed I can always write the upside-down file right side up at any
time for future use or print out the most recent one easily. Again I
appreciate the help :).

Re: STL Question [Solved]

Posted: Mon Jun 22, 2009 1:46 pm
by MarauderIIC
You're welcome. Just as an FYI:

When using a list, adding an item to the list is fast. Accessing any item past the first item of the list is increasingly slower.
When using a vector, adding an item to the vector is slow, if you don't know the minimum size beforehand (reserve() capacity()). Accessing any item takes the same amount of time as accessing any other item in the vector.

So:
List: Write=fast. Read=slow.
Vector: Write=slow. Read=fast.

So if you do more writes than reads, use a list. If you do more reads than writes (very common), use a vector.

Re: STL Question [Solved]

Posted: Mon Jun 22, 2009 3:15 pm
by zodiac976
MarauderIIC wrote:You're welcome. Just as an FYI:

When using a list, adding an item to the list is fast. Accessing any item past the first item of the list is increasingly slower.
When using a vector, adding an item to the vector is slow, if you don't know the minimum size beforehand (reserve() capacity()). Accessing any item takes the same amount of time as accessing any other item in the vector.

So:
List: Write=fast. Read=slow.
Vector: Write=slow. Read=fast.

So if you do more writes than reads, use a list. If you do more reads than writes (very common), use a vector.
Thanks for that info, I never knew about that but I have a question.
How would I use a vector for reversing as a vector doesn't have the
reverse function?

Re: STL Question [Solved]

Posted: Mon Jun 22, 2009 3:36 pm
by zodiac976
zodiac976 wrote:
MarauderIIC wrote:You're welcome. Just as an FYI:

When using a list, adding an item to the list is fast. Accessing any item past the first item of the list is increasingly slower.
When using a vector, adding an item to the vector is slow, if you don't know the minimum size beforehand (reserve() capacity()). Accessing any item takes the same amount of time as accessing any other item in the vector.

So:
List: Write=fast. Read=slow.
Vector: Write=slow. Read=fast.

So if you do more writes than reads, use a list. If you do more reads than writes (very common), use a vector.
Thanks for that info, I never knew about that but I have a question.
How would I use a vector for reversing as a vector doesn't have the
reverse function?
I really should have thought about that before I posted but I can do
the same thing as the reverse() in a list for a vector by using a
reverse iterator, as I went ahead and did the same exact thing
with the above code but with a vector only :lol:. Sorry for that post.

Now my only problem is figuring out how to transfer between a
vector and list if that is possible at all, since list = writing and
vector = reading. ;)

Re: STL Question [Solved]

Posted: Mon Jun 22, 2009 4:06 pm
by zodiac976
I must be on a roll today as I just figured out how to transfer
between a vector and list woot :shock:. Here is the code I
used for testing it and I hope it helps anyone ;).

Code: Select all

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <list>
using namespace std;

int main()
{
	string read;
	vector<string> vBag;

	ifstream file1("myfile1.txt");
	while(!file1.eof())
	{   //Fill vector with data
		getline(file1, read);
		vBag.push_back(read);
	}
	file1.close();

	list<string> lBag(vBag.begin(), vBag.end());   //Put vector contents into list
	list<string>::iterator x;
	lBag.reverse();   //Reverse list contents

	ofstream file2("myfile2.txt");
	for(x = lBag.begin(); x != lBag.end(); x++)   //Write list contents to file
		file2 << *x << endl;
	file2.close();

	return 0;
}
This code will take the file if written upside-down in ascending
order store it in a list from a vector and then write to a file
from the list right side up in descending order.

Oh yea before I forget since you said vector = fast reading and
list = fast writing, wouldn't this be an efficient way to read and
write to files using STL?

I love programming :mrgreen:....alot

Re: STL Question [Solved]

Posted: Mon Jun 22, 2009 4:29 pm
by MarauderIIC
Vectors have reverse. The documentation even uses reverse in its example http://www.sgi.com/tech/stl/reverse.html

Your indentation is off on your file.close(), by the way.

And I guess you could do list+vector, I mean, I can't think of any real reason to not do it, unless copying between the two is slow.