From: wittempj@hotmail.com on
GT wrote:
> hi there,
> Right, I used to be able to code in C a long time ago, and am going on to
> C++. I understand the concepts
> (classes, pointers, etc...) but, apart from classes find it difficult to use
> them (can't really see the point of using
> some of them). This is no doubt due to lack of experience as well as lack of
> understanding of some
> fundamentals. I bought Soustrup's bible, tough read, and another book c++
> programmer, which is not really
> adressing some very simple issues, according to me anyway.
> For instance, I wish to read lines from a text file and store them in a char
> vector for later use.
> My prog works fine, except that once the while loop is done, only the last
> line is kept, the previous two have vanished.
> I guess I can find this out for myself, but I have spent many hours so far
> and nothing works. So maybe someone
> out there can pinpoint my newbie mistakes (I probably am using C habits).
> Anyway, here's the code :
> PS: the compiler is Bloodshed dev C++ 4.9.9.2 and creates a template for dos
> window output.
>
> #include <cstdlib>
> #include <cstdio>
> #include <iostream>
> #include <fstream>
> #include <string>
> using namespace std;
> //char InputFile[23]="FileOfNamesOfFiles.txt"; // define name of site
> filenames file
> const int MaxLineLength=255;
> const int NumberOfFiles=3;
> char * InputFile="FileOfNamesOfFiles.txt";
> char LineToRead[MaxLineLength];
> char *HtmlFileName[NumberOfFiles];
> int FileCount=1;
> int main(int argc, char *argv[]) // no idea why the compiler adds int
> argc, char *argv[] or what it means
> {
> FILE* file; // file pointer called pf
> file=fopen(InputFile,"r"); // pf opens
> InputFile="FileOfNamesOfFiles.txt" in read mode
> cout << InputFile << " Est ouvert, lecture des noms de fichiers du
> site.\n";
> while (fgets(LineToRead,MaxLineLength+1,file)!=NULL) //read list of site
> file names
> {
> cout<<"LineToRead -> "<<LineToRead;
> HtmlFileName[FileCount]=LineToRead; // store file names in a char
> vector
> cout<<"HtmlFileName["<<FileCount<<"]"<<"->"<<HtmlFileName[FileCount];
>
> // if (FileCount>NumberOfFiles+1) cout<<"Error : Too many
> files!\n";
>
> if (FileCount==1) cout <<"FileCount "<<FileCount<<" is
> ="<<HtmlFileName[1];
> if (FileCount==2) cout <<"FileCount "<<FileCount<<" is
> ="<<HtmlFileName[2];
> if (FileCount==3) cout <<"FileCount "<<FileCount<<" is
> ="<<HtmlFileName[3];
> FileCount++;
> cout << HtmlFileName[1];
> }
>
> int FileCounter=FileCount;
> for (FileCounter=1;FileCounter<FileCount+1;FileCounter++)
> {
> cout<<"File "<<FileCounter<< "=" <<HtmlFileName[FileCounter]; //
> this gives only the last entry for all
> //three entries
> }
> system("PAUSE");
> return EXIT_SUCCESS;
> }

I would consider to learn a lot on stl, this defines useful concepts on
i/o and on containers. you can rewrite your code then to something like
this:

#include <fstream>
#include <string>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
const int max_line_length = 256;
ifstream f("/home/martin/test.cpp");
string s;
char buff[max_line_length];
vector<string> v;
vector<string>::iterator it;

while (!f.eof())
{
f.getline(buff, max_line_length);
s = buff;
v.push_back(s);
}

for (it = v.begin(); it != v.end(); ++it)
{
cout << *it << endl;
}

return 0;
}

for some info on what argc and argv do, try
http://www.google.com/search?q=argc+argv+tutorial

From: hk_mp5kpdw on

wittempj(a)hotmail.com wrote:
>
> I would consider to learn a lot on stl, this defines useful concepts on
> i/o and on containers. you can rewrite your code then to something like
> this:
>
> #include <fstream>
> #include <string>
> #include <iostream>
> #include <vector>
>
> using namespace std;
>
> int main()
> {
> const int max_line_length = 256;
> ifstream f("/home/martin/test.cpp");
> string s;
> char buff[max_line_length];
> vector<string> v;
> vector<string>::iterator it;
>
> while (!f.eof())
> {
> f.getline(buff, max_line_length);
> s = buff;
> v.push_back(s);
> }

Testing for eof in a looping condition is usually not the way to go.
The eof condition is set only after an attempt to read past the end of
file is made which means that after the last line of data is read, eof
is still false and the loop will try to run one more time. The getline
call will then set eof to true but since we are already in the loop, s
will get set to probably the same contents as the last line from the
file and then pushed back onto the vector... the end result is that the
last line from the file will likely appear in the ouput twice using the
above code. It is often better to rearrange things slightly as
follows, putting the getline call directly in the loop condition:

while( getline(f,s) )
{
v.push_back(s);
}

If the getline call sets eof, then the body of the loop is not executed
and thus the vector will not contain any duplicates. This also avoids
the unnecessary use of the temp character buffer by using the string
version of the getline function to get a string directly.


>
> for (it = v.begin(); it != v.end(); ++it)
> {
> cout << *it << endl;
> }
>
> return 0;
> }
>
> for some info on what argc and argv do, try
> http://www.google.com/search?q=argc+argv+tutorial

From: Chris ( Val ) on

wittempj(a)hotmail.com martin.witte(a)gmail.com wrote in message
news:1155551253.025111.300780(a)p79g2000cwp.googlegroups.com...

[ SNIP ]

| I would consider to learn a lot on stl, this defines useful concepts on
| i/o and on containers. you can rewrite your code then to something like
| this:
|
| #include <fstream>
| #include <string>
| #include <iostream>
| #include <vector>

# include <cstdlib> // for EXIT_FAILURE

| using namespace std;

Even though it is ok for this toy program, you should
get into the habit of *not* exposing the full extent
of namespace std, and restricting access with specific
directives of qualification at the point of use (the
safest option) - Any good book should outline the
possible ramifications of not doing do in larger programs.

| int main()
| {
| const int max_line_length = 256;
| ifstream f("/home/martin/test.cpp");

You need to check here, for success or failure, while
opening the file stream pointed to by 'f':

std::string Filename( "/home/martin/test.cpp" );

if( !f ) {
std::cerr << "ERROR: Could not open " +
Filename + " for reading\n";

return EXIT_FAILURE;
}

| string s;
| char buff[max_line_length];
| vector<string> v;
| vector<string>::iterator it;
|
| while (!f.eof())

Using 'eof' in this fashion is incorrect, and will often
be the cause of the last line in the file being read twice.

The correct idiom is:

while( there is data ) {
Work with data...
}

This would translate to:

std::string Buffer;
while( std::getline( f, Buffer ) ) {
// Work with Buffer...
}

The loop will terminate automatically when there is no
more data.

Once the loop has terminated, we can now check to see that
our loop read the whole file to the end:

if( f.eof() ) { // Returns true if eofbit is set
// Yup, we read the whole file to the end...
}

| {
| f.getline(buff, max_line_length);
| s = buff;
| v.push_back(s);
| }

[snip]

As shown already, better to avoid the istream version
of getline, and use the free standing version that is
specifically designed to work with the std::string class.

The std:;string class was introduced into the world of
C++ for safety, so you should use it whenever possible
over those ugly and error prone character arrays.

Cheers,
Chris Val


 | 
Pages: 1
Prev: register size
Next: a switch statement