Problem with Accessors

J

Jordan Tiona

Here is my code.

main.cpp:

#include "cddb.h"

CDData* head;
CDData* curData;

int main(){

head = new CDData();
curData = head;

EnterInfo();
Print();
return 0;
}

void EnterInfo(){
CDData* temp;
char* input = new char();
int ipInt;

system("cls");

temp = new CDData();
curData->SetNext(temp);
curData = temp;

cout << "Please enter information about your new CD.\n";
cout << "\nAlbum name: ";
cin.getline(input, 25);
curData->SetAlbumName(input);
cout << "\nArtist name: ";
cin.getline(input, 25);
curData->SetArtistName(input);
cout << "\nYear Released: ";
cin >> ipInt;
curData->SetYear(ipInt);
}

void Print(){
int i = 1;
curData = head;

while(true){
curData = curData->GetNext();
if(curData = NULL)
break;

cout << "CD #" << i << endl;
cout << "Album Name: " << curData->GetAlbumName() << endl;
cout << "Artist Name: " << curData->GetArtistName() << endl;
cout << "Year Released: " << curData->GetYear() << endl;
cout << "-------------------------------------------\n\n";

i++;
}
}

cddb.h:

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

void EnterInfo();
void Save();
void Load();
void Print();

class CDData {
private:
CDData *next; //For linked list
char* albumName;
char* artistName;
int year;
public:
//Constructor/Destructor
CDData(){ this->SetNext(NULL);}
~CDData(){}
//Accessors
char* GetAlbumName(){return this->albumName;}
char* GetArtistName(){return this->artistName;}
int GetYear(){return year;}
CDData* GetNext(){return next;}

void SetAlbumName(char* newName){albumName = newName;}
void SetArtistName(char* newName){artistName = newName;}
void SetYear(int newYear){year = newYear;}
void SetNext(CDData* newNext){next = newNext;}
};

I'm getting an access violation error during runtime at the print function,
when I'm trying to use the GetXXX accessors.

Unhandled exception at 0x0041fc46 in CDDataBase.exe: 0xC0000005: Access
violation reading location 0x00000004.

What am I doing wrong?
 
T

TB

Jordan Tiona sade:
while(true){
curData = curData->GetNext();
if(curData = NULL)

if(curData == NULL)
I'm getting an access violation error during runtime at the print function,
when I'm trying to use the GetXXX accessors.

Unhandled exception at 0x0041fc46 in CDDataBase.exe: 0xC0000005: Access
violation reading location 0x00000004.

What am I doing wrong?

TB
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

Jordan said:
Here is my code.

main.cpp:

#include "cddb.h"

CDData* head;
CDData* curData;

int main(){

head = new CDData();
curData = head;

EnterInfo();
Print();
return 0;
}

void EnterInfo(){
CDData* temp;
char* input = new char();
int ipInt;

system("cls");

temp = new CDData();
curData->SetNext(temp);
curData = temp;

cout << "Please enter information about your new CD.\n";
cout << "\nAlbum name: ";
cin.getline(input, 25);
curData->SetAlbumName(input);
cout << "\nArtist name: ";
cin.getline(input, 25);
curData->SetArtistName(input);
cout << "\nYear Released: ";
cin >> ipInt;
curData->SetYear(ipInt);
}

void Print(){
int i = 1;
curData = head;

while(true){
curData = curData->GetNext();
if(curData = NULL)
break;

cout << "CD #" << i << endl;
cout << "Album Name: " << curData->GetAlbumName() << endl;
cout << "Artist Name: " << curData->GetArtistName() << endl;
cout << "Year Released: " << curData->GetYear() << endl;
cout << "-------------------------------------------\n\n";

i++;
}
}

cddb.h:

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

void EnterInfo();
void Save();
void Load();
void Print();

class CDData {
private:
CDData *next; //For linked list
char* albumName;
char* artistName;
int year;
public:
//Constructor/Destructor
CDData(){ this->SetNext(NULL);}
~CDData(){}
//Accessors
char* GetAlbumName(){return this->albumName;}
char* GetArtistName(){return this->artistName;}
int GetYear(){return year;}
CDData* GetNext(){return next;}

void SetAlbumName(char* newName){albumName = newName;}
void SetArtistName(char* newName){artistName = newName;}
void SetYear(int newYear){year = newYear;}
void SetNext(CDData* newNext){next = newNext;}
};

I'm getting an access violation error during runtime at the print function,
when I'm trying to use the GetXXX accessors.

Unhandled exception at 0x0041fc46 in CDDataBase.exe: 0xC0000005: Access
violation reading location 0x00000004.

What am I doing wrong?


CDData::albumName and CCData::artistName are never initialized.
If you stick with char*, you must implement the copy constructor,
assignment operator and destructor.

Most of your problems will solve if you use std::string instead of
char*.
Hint: if you want a buffer of 25 characters use
char* buf = new char[25];
and don't forget to delete it later
delete [] buf;

Why do you declare
+ void EnterInfo();
+ void Save();
+ void Load();
+ void Print();
in cddb.h if there are implemented in main.cpp.
Do you really want that every application that uses CDData
has to provide them?

Regards, Stephan
(e-mail address removed)
Open source rating and billing engine for communication networks.
 
J

Jordan Tiona

New problem. I used strings now instead, and I can only input one word or
else it closes immediatly. How do I use cin.getline with strings.
 
T

TB

Jordan Tiona sade:
New problem. I used strings now instead, and I can only input one word or
else it closes immediatly. How do I use cin.getline with strings.

#include <string>
#include <iostream>

int main() {
std::string s;
std::getline(std::cin,s);
std::endl(std::cout);
std::cout<<s;
return 0;
}

TB
 
J

Jordan Tiona

TB said:
Jordan Tiona sade:

#include <string>
#include <iostream>

int main() {
std::string s;
std::getline(std::cin,s);
std::endl(std::cout);
std::cout<<s;
return 0;
}

TB

I tried this:

cout << "Please enter information about your new CD.\n";
cout << "Album name: ";
cin.ignore();
cin.getline(&input, 25);
curData->SetAlbumName(input);
cout << "Artist name: ";
cin.ignore();
cin.getline(&input, 25);
curData->SetArtistName(input);
cout << "Year Released: ";
cin >> ipInt;
curData->SetYear(ipInt);
ignore();

And I'm getting an error:

c:\Documents and Settings\Jordan\My Documents\Visual Studio Projects\C++
Course\Workshop 1\CDDataBase\main.cpp(37): error C2664:
'std::basic_istream<_Elem,_Traits>::_Myt
&std::basic_istream<_Elem,_Traits>::getline(_Elem *,std::streamsize)' :
cannot convert parameter 1 from 'std::string *__w64 ' to 'char *'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]

Are you sure that getline works with strings?
 
T

TB

Jordan Tiona sade:
TB said:
Jordan Tiona sade:
#include <string>
#include <iostream>

int main() {
std::string s;
std::getline(std::cin,s);
std::endl(std::cout);
std::cout<<s;
return 0;
}

TB

I tried this:

cout << "Please enter information about your new CD.\n";
cout << "Album name: ";
cin.ignore();
cin.getline(&input, 25);
curData->SetAlbumName(input);
cout << "Artist name: ";
cin.ignore();
cin.getline(&input, 25);
curData->SetArtistName(input);
cout << "Year Released: ";
cin >> ipInt;
curData->SetYear(ipInt);
ignore();

And I'm getting an error:

c:\Documents and Settings\Jordan\My Documents\Visual Studio Projects\C++
Course\Workshop 1\CDDataBase\main.cpp(37): error C2664:
'std::basic_istream<_Elem,_Traits>::_Myt
&std::basic_istream<_Elem,_Traits>::getline(_Elem *,std::streamsize)' :
cannot convert parameter 1 from 'std::string *__w64 ' to 'char *'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]

Are you sure that getline works with strings?

First: I have no idea what 'input' is unless I read the error messages.
Second: I don't think you actually read my code.

I'm not using 'cin.getline()' but 'std::getline()' found in <string>.

TB
 
J

Jordan Tiona

I'm a bit confused then. Your code is not clear. Please explain it a bit
better.
 
J

Jordan Tiona

Never mind. I've got that figured out. Last problem... how do I check for
end of file?
 
T

TB

Jordan Tiona sade:
Never mind. I've got that figured out. Last problem... how do I check for
end of file?

#include <fstream>

int main() {
std::fstream f(...);
if(f.eof()) {
// end of file
}
return 0;
}

TB
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

Jordan said:
Is there a way to do this with the stdio FILE struct?

Yes of course, but then you'll need a buffer char[<size>] and prevent
potential overflows of the buffer.

Regards, Stephan
 
J

Jordan Tiona

Well, I found how to do it online. But now there is a problem with my
loading function. Could you possibly see what I'm doing? I apologize for
posting so many problems.

void Load(){
FILE* file;
string filename;
CDData* temp;
system("cls");

cout << "Name of file (without extension): ";
getline(cin, filename);
filename += ".dat";
cout << "\nLoading from " << filename;
curData = head;
if((file = fopen(filename.c_str(), "r+b"))!= NULL){
//We need to delete the old list first
//First, go to the last node
while(curData->GetNext()!= NULL)
curData = curData->GetNext();
//Then, we go through and delete each node, until we get to the head
while(curData->GetPrev()!= NULL){ //If it's NULL then this is head
curData = curData->GetPrev();
delete curData->GetNext();
}
//We keep the head node, and reset its next and prev
curData->SetNext(NULL);

//Now that we've deleted the list, we can make a new one.
while(!feof(file)){
temp = new CDData;
curData->SetNext(temp);
fread(temp, sizeof(temp), 1, file);
temp->SetPrev(curData);
curData = temp;
}
}
else
cout << "Error opening file";
}
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

Jordan said:
Well, I found how to do it online. But now there is a problem with my
loading function. Could you possibly see what I'm doing? I apologize for
posting so many problems.

void Load(){
FILE* file;
string filename;
CDData* temp;
system("cls");

cout << "Name of file (without extension): ";
getline(cin, filename);
filename += ".dat";
cout << "\nLoading from " << filename;
curData = head;
if((file = fopen(filename.c_str(), "r+b"))!= NULL){
//We need to delete the old list first
//First, go to the last node
while(curData->GetNext()!= NULL)
curData = curData->GetNext();
//Then, we go through and delete each node, until we get to the head
while(curData->GetPrev()!= NULL){ //If it's NULL then this is head
curData = curData->GetPrev();
delete curData->GetNext();
}
//We keep the head node, and reset its next and prev
curData->SetNext(NULL);

//Now that we've deleted the list, we can make a new one.
while(!feof(file)){

feof(FILE*) returns true only after the EOF was read ...
temp = new CDData;
curData->SetNext(temp);
fread(temp, sizeof(temp), 1, file);

.... so fread will sooner or later fail.
(Even worse, in case of an error in `file' you could get
an endless loop because the "EOF"-flag is never set).

You can't read directly into temp: what is sizeof(temp) if
CDData::name is 1024 bytes long?
You must read/write each member indiviually
(thus my hint char buf[1024]).
temp->SetPrev(curData);
curData = temp;
}
}
else
cout << "Error opening file";
}

Better: provide input/output operator for CDData and use C++ streams.

Regards, Stephan
 
J

Jordan Tiona

Stephan Brönnimann said:
Jordan said:
Well, I found how to do it online. But now there is a problem with my
loading function. Could you possibly see what I'm doing? I apologize for
posting so many problems.

void Load(){
FILE* file;
string filename;
CDData* temp;
system("cls");

cout << "Name of file (without extension): ";
getline(cin, filename);
filename += ".dat";
cout << "\nLoading from " << filename;
curData = head;
if((file = fopen(filename.c_str(), "r+b"))!= NULL){
//We need to delete the old list first
//First, go to the last node
while(curData->GetNext()!= NULL)
curData = curData->GetNext();
//Then, we go through and delete each node, until we get to the head
while(curData->GetPrev()!= NULL){ //If it's NULL then this is head
curData = curData->GetPrev();
delete curData->GetNext();
}
//We keep the head node, and reset its next and prev
curData->SetNext(NULL);

//Now that we've deleted the list, we can make a new one.
while(!feof(file)){

feof(FILE*) returns true only after the EOF was read ...
temp = new CDData;
curData->SetNext(temp);
fread(temp, sizeof(temp), 1, file);

... so fread will sooner or later fail.
(Even worse, in case of an error in `file' you could get
an endless loop because the "EOF"-flag is never set).

You can't read directly into temp: what is sizeof(temp) if
CDData::name is 1024 bytes long?
You must read/write each member indiviually
(thus my hint char buf[1024]).
temp->SetPrev(curData);
curData = temp;
}
}
else
cout << "Error opening file";
}

Better: provide input/output operator for CDData and use C++ streams.

Regards, Stephan

What do you mean I/O operator for CDData? I'm sorry, I guess I'm more of a
newbie than I thought.
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

Jordan said:
What do you mean I/O operator for CDData? I'm sorry, I guess I'm more of a
newbie than I thought.

std::eek:stream& operator>>(std::eek:stream& os, const CDData& cdData);
and similar for the input operator of CDData to write/read CDData
to/from files.

Regards, Stephan
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top