我是一名学习C ++的Java / PHP程序员。
我创建了一个名为UserAccount
的类和一个名为Database
的类。
我有一个包含五个名字的输入文件:
Bob
Sam
Jane
Mark
Ann
我有以下(伪)代码:
UserAccount *ua;
while (reading through the list of names, line by line) {
ua = new UserAccount(name); // Create a new user based on this name
Database->add(ua); // Add the user to the database
}
Database->listAllUsers();
输出应该镜像输入文件。相反,我得到:
Ann
Ann
Ann
Ann
Ann
我认为这与指针有关,但我无法弄明白。我想我已经提供了足够的信息来识别问题,但如果上面的(伪)代码看起来是正确的,我可以提供更多。
答案 0 :(得分:2)
您能举例说明正确的实施吗?
这将是一个开始:
#include <string>
#include <vector>
class UserAccount {
public:
UserAccount(const std::string& name) : d_name(name) {}
...
private:
std::string d_name;
};
class Database {
public:
Database() : d_accounts() {}
void add(const UserAccount& account) {
this->d_accounts.push_back(account);
}
...
private:
std::vector<UserAccount> d_accounts;
};
void zb() {
Database db;
db.add(UserAccount("Bob"));
...
}
它与您发布的内容不同,因为向量存储了UserAccounts的值。无论如何 - 更多代码会有所帮助。我最终会删除它,因为它不是一个真正的答案(好吧,一旦问题的定义更好,可能会更新)。
答案 1 :(得分:1)
跟进我的评论。您可能会遇到指针,std::string
类会给您的行为更类似于Java。
最简单的解决方案是使用字符串strdup()
调用。
#include <cstring> // provides C string interface
UserAccount::UserAccount(char *n) {
name = strdup(n);
}
UserAccount::~UserAcount() {
// This is older C style, cleanup. Need or the memory will "leak".
free(name);
// You could also use: delete[] name;
}
或者您可以使用std::string
,但我会将其留给您的学习过程。关于指针的信息有很多,它将帮助您学习如何理解指针。
// e.g.
char *str1 = "ann";
char *str2 = "bob";
str1 = str2;
// Both equal "bob".
str1 = "carol";
// Both equal "carol"!
祝你好运。
答案 2 :(得分:1)
在C ++中,与其他语言不同,您必须明确考虑事物存储在内存中的位置。指针告诉你在内存中查找内容的位置。打个比方就是告诉你看一本书第124页第5行的第三个字母。如果我的书是用铅笔写的,我可以擦掉那个页面上的文字并用其他文字替换它们,而指针保持不变(也就是说,我看着书中的同一个位置),指向的是什么会改变。
这是您的代码中发生的事情。每次读取名称时,都会删除以前的名称并将新名称写入同一内存位置。因此,当您在构造函数中传入指针时,您将面临指向更改的内存的危险。
要解决此问题,您需要制作该名称的本地副本。这可以通过使用字符串类来完成,如@Justin的响应。但是,出于教学目的(这段代码有点复杂),这就是你可以在内部分配新内存的方法(字符串类就是为你做的):
class UserAccount {
public:
UserAccount(const char *name)
{
m_name = new char[strlen(name)+1];
strcpy(m_name, name);
}
~UserAccount()
{
delete [] m_name;
}
private:
char * m_name;
};
请注意,我们现在正在使用析构函数,因为我们已经分配了内存,并且在删除类时需要再次释放它。另请注意,我没有检查传入的名称是否为null,应该这样做。最后要注意的是,字符串是隐式空终止的,以告诉您何时到达字符串的末尾。这就是为什么我们必须分配一个大的 - 在字符串的末尾保存null。
正如@Marc指出的那样,你也可以使用strdup,但我认为更长的解释并显示内存的显式分配对于更好地了解正在发生的事情是有用的。
答案 3 :(得分:1)
您需要一个useraccount类来存储单个用户和数据库类的详细信息,以存储所有useraccount的详细信息。
使用string,stl,算法来提高效率。
针对您的需求的示例菜单驱动程序:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class useraccount
{
string name;
//other details
public:
void get(string str)
{
name=str;
}
void display()
{
cout<<name<<endl;
}
};
void display_db(useraccount & e)
{
e.display();
}
void main()
{
vector<useraccount> database;
useraccount *ptr;
int choice;
string name;
do
{
cout<<"\n\n1.Insert \n2.Delete\n3.Display\n4.Exit \nEnter your choice: \n";
cin>>choice;
switch(choice)
{
case 1:
ptr=new useraccount;
cout<<"Enter name:\n";
cin>>name;
ptr->get(name);
database.push_back(*ptr);
break;
case 2:
database.pop_back();
break;
case 3:
for_each(database.begin(),database.end(),display_db);
break;
case 4:
cout<<"Quiting";
break;
default:
cout<<"wrong choice";
}
}while(choice!=4);
}