I wrote a programe in C++ but in debugging I encountered a problem, I'll be glad if you can help me in this Code,The Source of the code and the error has been declaired in the following :
The error is:
Unhandled exception at 0x011019d6 in 33.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
The Code is:
#include <iostream>
#include <string>
using namespace std;
const int maxCard =100;
//enum Boll {false, true};
class Contact
{
public:
Contact (const char *name, const char *address, const char *tell);
//~ Contact(void);
const char* Name (void) const {return name;}
const char* Address (void) const {return address;}
const char* Tell (void) const {return tell;}
friend ostream& operator<< (ostream&, Contact&);
private:
char *name;
char *address;
char *tell;
};
class ContactDir
{
public:
ContactDir(const int maxSize);
//~ContactDir(void);
void Insert(const Contact &);
void Delete(const char *name);
Contact* Find(const char *name);
friend ostream& operator <<(ostream&, ContactDir&);
private:
int Lookup (const char *name);
Contact **contacts;
int dirSize;
int maxSize;
};
Contact::Contact(const char *name, const char *address, const char *tell)
{
Contact::name= new char [strlen(name)+1];
Contact::address= new char [strlen(address)+1];
Contact::tell= new char [strlen(tell)+1];
strcpy(Contact::name, name);
strcpy(Contact::address, address);
strcpy(Contact::tell,tell);
}
/*Contact::~Contact (void)
{
delete name;
delete address;
delete tell;
}*/
ostream &operator<<(ostream &os, Contact &c)
{
os<<"("<<c.name<<","<<c.address<<","<<c.tell<< ")";
return os;
}
ContactDir::ContactDir (const int max)
{
typedef Contact *ContactPtr;
dirSize=0;
maxSize=max;
contacts= new ContactPtr[maxSize];
};
/*ContactDir::~ContactDir (void)
{
for(register int i=0; i<dirSize; ++i)
delete contacts[i];
delete []contacts;
}*/
void ContactDir::Insert (const Contact& c)
{
if (dirSize<maxSize)
{
int idx= Lookup(c.Name());
if(idx>0 &&strcmp(c.Name(), contacts[idx]->Name())==0)
{
delete contacts [idx];
}
else
{
for (register int i=dirSize; i>idx; --i)
contacts[i]=contacts[i-1];
++dirSize;
}
contacts[idx]=new Contact (c.Name(),c.Address(),c.Tell());
}
}
void ContactDir::Delete (const char *name)
{
int idx=Lookup(name);
if(idx<dirSize)
{
delete contacts[idx];
--dirSize;
for (register int i=idx; i<dirSize; i++)
contacts[i]=contacts[i+1];
}
}
Contact *ContactDir::Find (const char *name)
{
int idx= Lookup (name);
return (idx< dirSize && strcmp (contacts[idx]->Name(), name)==0)? contacts[idx]:0;
}
int ContactDir:: Lookup (const char *name)
{
for (register int i=0; i<dirSize; ++i)
if (strcmp (contacts[i]->Name(), name)==0)
return i;
return dirSize;
}
ostream &operator << (ostream &os, ContactDir &c)
{
for (register int i=0; i<c.dirSize; ++i)
os<< *(c.contacts[i]) << '\n';
return os;
}
int main (void)
{
ContactDir dir (10);
dir.Insert(Contact ("JACK","NORWAY", "999999"));
dir.Insert(Contact ("JIMMY",开发者_开发技巧"FRANCE", "313131"));
cout<<dir;
}
I agree with the rest of the recommendations regarding the implementation, but as for your specific problem: you Lookup
function returns the size of dir if it doesn't find what it was looking for. Your second insert then uses that value in contacts[idx]->Name()
, as an index. idx
is 1, but at that point there's no value in the second cell of the array. So, when you call Name()
, you call it on an invalid pointer. You've missed the difference between a 1-based size and a 0-based index.
In general, 0xcdcdcdcd is a common pattern, set by VS on uninitialized pointers in debug builds.
Firstly, since you are using c-style strings and the associated functions (strlen
, etc.), you should #include <cstring>
, not <string>
- on my system, your code does not compile. As vines says in the comments, you would be better off with std::string
anyway. To find your problem, you should run your code in a debugger as sth says. If you still can't work out where the error is, try repeatedly removing functionality from your code and running it to narrow down the source of the problem.
First of all, why don't you use C++ classes for strings, such as the std::string
lokated in <string>
? You could avoid ugly code like this:
Contact::name= new char [strlen(name)+1];
Contact::address= new char [strlen(address)+1];
Contact::tell= new char [strlen(tell)+1];
strcpy(Contact::name, name);
strcpy(Contact::address, address);
strcpy(Contact::tell,tell);
by just typing
Contact::Contact(const char *name, const char *address, const char *tell) : name(name), address(address), tell(tell)
where these are defined in the class like this:
std::string name, address, tell;
Secondly, why do you invent the wheel again? Instead of creating your own ContactDir
class, you could simply use the std::map
located in <map>
. Here is the documentation for it.
The following code instantiates a map, inserts objects and retrieves them:
std::map<std::string, Contact> dir;
dir["JACK"] = Contact("JACK","NORWAY", "999999"));
dir["JIMMY"] = Contact ("JIMMY","FRANCE", "313131"));
Object jimmy = dir["JIMMY"];
I know, I did not locate the exact spot where the segfault occurs, but I think this approach will help you more.
EDIT: Also I think I found your problem. In Insert
you make a Lookup
call, which returns, if the element was not found, the size of the dir. But in Insert
you never check if the value was correct. I think so...
精彩评论