Newbie question about class member functions...

S

Some Clown

Greetings,

I am very, very new to C++ and am working my way through a book entitled,
"Beginning Visual C++" by Ivor Horton. Decent book except for the guy's
almost fetish-like love for complex math examples. I spend half my time
deciphering the math before I can even begin to get into the sematics of the
language in his examples. That aside though... I do have a couple of
questions, and they don't relate to Visual C++ specifically.

I've gotten through the first few chapters (9 or so) and am in the middle of
learning 'classes' right now. I thought I'd take a slight pause and try to
apply some of what I've learned (or not as the case may be) to a silly
little program. I am trying to write a program to take a text file playlist
(*.m3u) with a bunch of filenames/paths seperated by newlines and edit it.
It will eventually except command line switches, though I'm far from that
stage right now. It just needs to edit the file and save it under a
different name. so C:\somefile would become F:\somefile (or something like
that).

I have a member function called getFile() and another one called printFile()
that both work as expected with one major exception. In printfile() when I
try to loop through my lineItems[] array I get jibberish (probably because
I'm going past the filled in data). I can specify specifically lineItems[5]
or something and get what's expected, and the commented out loop in
getFile() works as well.

So my question might be, "How to do figure out how much of my array is
filled up and either truncate or get a count of items, so that I don't run
past the end?" I've included source code below, and I'm hoping some of you
experienced folks can give me some pointers. I'd also take pointers on
anything else wrong with my code, though keep in mind, I'm so new to this I
may not understand what you're saying [is wrong]. This is definitely a work
in progress, but that being said, I'm having great fun with it!

Thanks in advance!

---------------------- code --------------------------------------
// Playlist Edit - Version 0.1
// Copyright 2004 by Some Clown


#include <fstream.h>
#include <iostream>

const int MAX = 80; // Maximum number of characters in filename
const int MAX2 = 80; // Maximum number of songs in a playlist
const int maxPath = 200; // Maximum length of path in playlist file

class CPlaylist
{
private:
char* pfileName; // Our filename as passed from main()
char lineItems[MAX2][maxPath];

public:

// Default Constructor
CPlaylist(char* pfn): pfileName(pfn){}

// Default Destructor
~CPlaylist()
{

}

// Function to open a playlist file and read it into an array
void getFile()
{
ifstream theFile(pfileName, ios::nocreate);
if(!theFile)
{
cout << endl
<< "Error opening file!"
<< endl;
exit(1);
}

for(int i = 0; ((i <=MAX2) && (!theFile.eof())); i++)
{
theFile.getline(lineItems, maxPath);
// cout << endl // just for testing
// << lineItems;
}
theFile.close(); // Might need to move this somewhere else once all of the
other
// functions are complete. Or put in some error checking to see
// if file is already closed or not.
}


// Function to edit a playlist file
void editFile()
{
}

// Function to print contents of array containing playlist
void printFile()
{
for(int i = 0; i <=MAX2; i++)
{
cout << endl
<< lineItems;
}

}

};


void main()
{

char fileName[MAX];

cout << endl
<< "Please enter a playlist name: ";
cin.getline(fileName, MAX);
CPlaylist test(fileName);
test.getFile();
test.printFile();


return;
}
 
D

Default User

Some Clown wrote:

const int MAX = 80; // Maximum number of characters in filename
const int MAX2 = 80; // Maximum number of songs in a playlist
const int maxPath = 200; // Maximum length of path in playlist file
char lineItems[MAX2][maxPath];
for(int i = 0; ((i <=MAX2) && (!theFile.eof())); i++)
{
theFile.getline(lineItems, maxPath);


This is wrong. You defined the lineItems array as having MAX2 subarrays.
That means the allowable range is from 0 to MAX2 - 1.

Change this loop to
for(int i = 0; ((i < MAX2) && (!theFile.eof())); i++)

void printFile()
{
for(int i = 0; i <=MAX2; i++)
{

Two problems here. The one from above, plus, what if you didn't read in
MAX2 number of filenames? You should have saved off the last used index.

void main()

main() returns int ALWAYS.


I suggest you scrap that book and get a modern one. You should be using
std::vector and std::string for your early learning exercises. At some
point you will want to tackle arrays, but there is no need to at this
point.



Brian Rodenborn
 
J

Jeff Schwab

Some said:
Greetings,

I am very, very new to C++ and am working my way through a book entitled,
"Beginning Visual C++" by Ivor Horton. Decent book except for the guy's
almost fetish-like love for complex math examples. I spend half my time
deciphering the math before I can even begin to get into the sematics of the
language in his examples. That aside though... I do have a couple of
questions, and they don't relate to Visual C++ specifically.

I've gotten through the first few chapters (9 or so) and am in the middle of
learning 'classes' right now. I thought I'd take a slight pause and try to
apply some of what I've learned (or not as the case may be) to a silly
little program. I am trying to write a program to take a text file playlist
(*.m3u) with a bunch of filenames/paths seperated by newlines and edit it.
It will eventually except command line switches, though I'm far from that
stage right now. It just needs to edit the file and save it under a
different name. so C:\somefile would become F:\somefile (or something like
that).

I have a member function called getFile() and another one called printFile()
that both work as expected with one major exception. In printfile() when I
try to loop through my lineItems[] array I get jibberish (probably because
I'm going past the filled in data). I can specify specifically lineItems[5]
or something and get what's expected, and the commented out loop in
getFile() works as well.

So my question might be, "How to do figure out how much of my array is
filled up and either truncate or get a count of items, so that I don't run
past the end?" I've included source code below, and I'm hoping some of you
experienced folks can give me some pointers. I'd also take pointers on
anything else wrong with my code, though keep in mind, I'm so new to this I
may not understand what you're saying [is wrong]. This is definitely a work
in progress, but that being said, I'm having great fun with it!

Thanks in advance!

<snip> code </>

I'm glad you're having a good time. :) Welcome to C++!

Here are a few words of supposed wisdom. I hope they will be of use.
I've taken the liberty of applying some of them to your program.

1. Don't need the "max" constants.
2. <fstream>, not <fstream.h>.
3. Use std::string instead of raw char arrays.
4. Use std::vector instead of other arrays.
5. Your "default constructor" isn't a default constructor.
A default constructor needs no arguments.
6. There's no need to define an empty, non-virtual destructor.
7. You don't need to pass ios::nocreate to std::ifstream.
8. Print error messages to cerr, not cout.
9. You might consider handling errors using "exceptions." If you're
just not at that point yet, it's okay. :)
10. Don't use std::endl when a plain newline will do.
11. When you do use std::endl, it generally goes after the string
you're printing, not before it.
12. I think you want std::getline, not std::cin.getline.
13. main() always returns int, never void. You don't need a return
statement if the return value is 0.
14. An ifstream will close itself at the end of its scope.
15. You don't need to label every function with "Function." Just
list the function's purpose.

// Playlist Edit - Version 0.1
// Copyright 2004 by Some Clown
// Modified by an unrelated clown.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>

struct Playlist
{
Playlist( std::string const& file ): fileName( file ) { }

/* Open a playlist file and read it into an array
*/
void getFile( )
{
std::ifstream theFile( fileName.c_str( ) );

if( ! theFile )
{
std::cerr << "Error opening file!\n";
exit(1);
}

std::string line;

while( theFile )
{
getline( theFile, line );
lineItems.push_back( line );
}
}

/* Edit a playlist file.
*/
void editFile( ) { /* To be written. */ }

/* Print contents of array containing playlist.
*/
void printFile()
{
std::eek:stream_iterator< std::string > out( std::cout, "\n" );

copy( lineItems.begin( ), lineItems.end( ), out );
}

private:
std::string fileName; // Our filename as passed from main( ).
std::vector< std::string > lineItems;
};

int main( )
{
std::string fileName;

std::cout << "Please enter a playlist name: " << std::flush;
getline( std::cin, fileName );

Playlist test( fileName );

test.getFile( );
test.printFile( );
}
 
S

Some Clown

I suggest you scrap that book and get a modern one. You should be using
std::vector and std::string for your early learning exercises. At some
point you will want to tackle arrays, but there is no need to at this
point.


I am picking up Bjorne Strousup's book this week, but I'd be interested in
any suggestions you or the group has for a good, thorough introduction to
C++ (doesn't have to be Visual C++ oriented.) Truthfully I've had a hard
time with some of Ivor Horton's writing - not that it's neccessarily bad,
just not perfect for me.
 
D

David Harmon

std::ifstream theFile( fileName.c_str( ) );

if( ! theFile )
{
std::cerr << "Error opening file!\n";

Please...
if( ! theFile )
{
std::perror(fileName.c_str());
 
S

Some Clown

Jeff Schwab said:
1. Don't need the "max" constants.
2. <fstream>, not <fstream.h>.
3. Use std::string instead of raw char arrays.
4. Use std::vector instead of other arrays.
5. Your "default constructor" isn't a default constructor.
A default constructor needs no arguments.
6. There's no need to define an empty, non-virtual destructor.
7. You don't need to pass ios::nocreate to std::ifstream.
8. Print error messages to cerr, not cout.
9. You might consider handling errors using "exceptions." If you're
just not at that point yet, it's okay. :)
10. Don't use std::endl when a plain newline will do.
11. When you do use std::endl, it generally goes after the string
you're printing, not before it.
12. I think you want std::getline, not std::cin.getline.
13. main() always returns int, never void. You don't need a return
statement if the return value is 0.
14. An ifstream will close itself at the end of its scope.
15. You don't need to label every function with "Function." Just
list the function's purpose.

Hmmm... made a few newbie mistakes there, did I? LOL. Number 5, 6, and 13
above were just silly mistakes that I shouldn't have made... just got too
into the other stuff and blew right by 'em. On the other stuff I'll have to
do some research as I haven't seen a lot of it. I've tried researching in
the MSDN stuff that came with my Visual C++ 6.0 copy, but it's a @#$@
nightmare trying to find anything useful to a newbie in there. Oh, and on
number 7 above, I put that in (ios::nocreate) because when I didn't have it,
and the file didn't exist, an empty file was being created. I tossed that
in and it fixed it. Why? Dunno. By the by, I'm sure your code was banged
out quickly... but it's definitely way more elegant than mine! I appreciate
the example.
 
B

Buster

Jeff Schwab said:
while( theFile )
{
getline( theFile, line );
lineItems.push_back( line );
}

With this you'll call getline once too often (there is an
explanation in the FAQ).Try the following instead:

while (getline (theFile, line)) lineItems.push_back (line);

Regards,
Buster.
 
S

Some Clown

Jeff Schwab said:
Here are a few words of supposed wisdom. I hope they will be of use.
I've taken the liberty of applying some of them to your program.

1. Don't need the "max" constants.
2. <fstream>, not <fstream.h>.
3. Use std::string instead of raw char arrays.
4. Use std::vector instead of other arrays.
5. Your "default constructor" isn't a default constructor.
A default constructor needs no arguments.
6. There's no need to define an empty, non-virtual destructor.
7. You don't need to pass ios::nocreate to std::ifstream.
8. Print error messages to cerr, not cout.
9. You might consider handling errors using "exceptions." If you're
just not at that point yet, it's okay. :)
10. Don't use std::endl when a plain newline will do.
11. When you do use std::endl, it generally goes after the string
you're printing, not before it.
12. I think you want std::getline, not std::cin.getline.
13. main() always returns int, never void. You don't need a return
statement if the return value is 0.
14. An ifstream will close itself at the end of its scope.
15. You don't need to label every function with "Function." Just
list the function's purpose.

While I haven't fixed all of the above (see other posts) I did get my basic
problem solved. There is still the business of using std::string vs. char
arrays... but I need to research that some more as I haven't read much on
that yet. I believe that the book I'm using is a little dated (another
poster clued me into that). Anyhoo... below is my "fixed" code so far
(minus std::string changes).

---------- snip -------------------------
// Playlist Edit - Version 0.1
// Copyright 2004 by Some Clown


#include <fstream>
#include <iostream>
#include <iomanip>

using namespace std;

const int MAX = 80; // Maximum number of characters in filename
const int MAX2 = 80; // Maximum number of songs in a playlist
const int maxPath = 200; // Maximum length of path in playlist file

class CPlaylist
{
private:
char* pfileName; // Our filename as passed from main()
char lineItems[MAX2][maxPath];
int j; // Position count in array loops
public:

// Constructor
CPlaylist(char* pfn): pfileName(pfn){}

// Open playlist file and read it into an array
void getFile()
{
j=0; // Number of items read
ifstream theFile(pfileName);
if(!theFile)
{
cerr << "Error opening file!\n";
exit(1);
}

for(int i = 0; ((i < MAX2) && (!theFile.eof())); i++)
{
theFile.getline(lineItems, maxPath);
CPlaylist::j++;
}
theFile.close(); // Might need to move this somewhere else once all of the
other
// functions are complete. Or put in some error checking to see
// if file is already closed or not.
}


// Edit a playlist file
void editFile()
{
}

// Print contents of array containing playlist
void printFile()
{
for(int i = 0; i < CPlaylist::j; i++)
{
cout << lineItems << "\n";
}

}

};


int main()
{
char fileName[MAX];

cout << endl
<< "Please enter a playlist name: ";
cin.getline(fileName, MAX);
CPlaylist test(fileName);
test.getFile();
test.printFile();
return 0;
}
 
J

Jon Bell

I am picking up Bjorne Strousup's book this week, but I'd be interested in
any suggestions you or the group has for a good, thorough introduction to
C++ (doesn't have to be Visual C++ oriented.)

Assuming you already know something about programming from some other
language (what a variable is, etc.), check out Koenig and Moo's
"Accelerated C++". It's the most modern introduction to C++ I've seen.
It gets going very quickly with strings, vectors, and other goodies from
the standard library.
 
J

Jeff Schwab

Buster said:
With this you'll call getline once too often (there is an
explanation in the FAQ).Try the following instead:

while (getline (theFile, line)) lineItems.push_back (line);

Regards,
Buster.

Whoops! Thanks, you're absolutely right. I'm not sure why I did that.

This is the first time I've been FAQ'd. :(
 
D

David Harmon

I didn't realize the fstreams set perror!

Magic eight ball says: Answer murky.

However, most behavior if fstreams is defined in the standard in terms
of stdio behavior. And, to at least some of us, that implies that
fstreams will set errno when the corresponding stdio function would.

Of course it's "Implementation Defined" for the most part with regard to
stdio too.

In practice I find it works out to be very useful.
 
J

jeffc

Some Clown said:
Greetings,

I am very, very new to C++ and am working my way through a book entitled,
"Beginning Visual C++" by Ivor Horton. ...
I've gotten through the first few chapters (9 or so) and am in the middle of
learning 'classes' right now. I thought I'd take a slight pause and try to
apply some of what I've learned (or not as the case may be) to a silly
little program.

Always a good idea.
So my question might be, "How to do figure out how much of my array is
filled up and either truncate or get a count of items, so that I don't run
past the end?"

Well, on the one hand, it's not a bad idea to learn this. This is kind of
part of programming 101 and every decent programmer knows how to do it. On
the other hand, no decent programmer would probably waste his time with it
on a real program. I suggest you also pick up a copy of "Accelerated C++"
and start using some of the power of the C++ standard library. Sorry, I
don't have time to go through your actual array problem right now :)
 
J

jeffc

Some Clown said:
Hmmm... made a few newbie mistakes there, did I? LOL. Number 5, 6, and 13
above were just silly mistakes that I shouldn't have made... just got too
into the other stuff and blew right by 'em. On the other stuff I'll have to
do some research as I haven't seen a lot of it. I've tried researching in
the MSDN stuff that came with my Visual C++ 6.0 copy, but it's a @#$@
nightmare trying to find anything useful to a newbie in there.

Clown, please keep in mind that there are many different flavors of C++ out
there. Visual C++ is definitely a flavor and does not necessarily adhere
strictly to the current standard. This newsgroup is only supposed to talk
about the standard. That doesn't mean that anothe way won't work in Visual
C++, and it also doesn't mean that everything you read here will work
correctly in Visual C++. Fair warning.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top