这是一个非常简单的问题,我很确定,但我很感激帮助。 :)
这是.h文件中的变量:
map<int, map<int, map<int, CString>*>*> batch;
这是我尝试分配值:
((*((*(batch[atoi(transnum)]))[1]))[atoi(*docnum)]) = page;
我在尝试解决这个问题时添加了一些额外的括号,以确保以正确的顺序处理derefs - 不幸的是,它仍然不起作用。我的应用程序在运行此行时崩溃了。我把它包装在try {} catch {}中,但似乎没有异常抛出。我不经常使用C ++,并且想知道是否有人可以告诉我我做错了什么。
以下是我正在尝试建模的关系:
交易号(整数)列表,需要按键排序。
对于每个交易编号,我有两个类型的文档,付款和发票(在我的数据结构中分别用0和1表示的桶)
在每个类型的存储桶中,可以有一个或多个文档,这些文档需要按ID排序(docid)
每个docid链接到一个字符串,该字符串由文件系统上用于处理的逗号分隔文件列表组成。
如果您认为有更好的数据结构可供使用,我很想听听它。
编辑:我知道有很多更好的方法可以做到这一点。情节是我被交给了一堆可怕的MFC-riddled C ++代码,并告诉我昨天要完成一些事情。它基本上归结为在那里获取数据结构,加载它然后在其他地方输出它。当我问这个问题时,我只是想快速地把它敲出来。我很欣赏这些设计建议。
答案 0 :(得分:17)
std::map
的工作方式是,如果它尚不存在,它将分配您尝试引用的节点。这意味着除非您分配子图并将它们插入到您的超图中,否则您将获得指向您不拥有的内存的指针。此时,当您尝试写入该内存时,您将崩溃。
地图是否需要堆分配?如果没有,您可以将类型更改为:
map<int, map<int, map<int, CString> > > batch; // don't forget the spaces
您的电话可以是:
batch[atoi(transnum)][1][atoi(*docnum)] = page;
答案 1 :(得分:13)
首先,typedef
这些事情变得更加容易:
typedef std::map<int, CString> page_map;
typedef std::map<int, page_map> document_map;
typedef std::map<int, document_map> batch_map;
batch_map batch;
请注意,您几乎总是喜欢堆叠以动态分配。其次,你在一条线上做得太多了!
int transNumber = atoi(transnum);
int docNumber = atoi(*docnum); // why is docnum a pointer?
batch[transNumber ][1][docNumber] = page;
现在,如果你需要调试,你可以轻松检查这些值,并且更容易看出你犯错的地方。
我认为通过更多信息,我们可以更简单地完成这项工作。我想不出为什么在地球上你需要这样的东西。
答案 2 :(得分:11)
该行方式过于复杂。
你需要把它分成小块,把每一块都变成一个命名变量。
答案 3 :(得分:5)
如果你宣布:
map<int, map<int, map<int, CString> > > batch;//no asterisks!
你应该能够做到这一点:
batch[atoi(transnum)][1][atoi(*docnum)] = page;
答案 4 :(得分:2)
只是为了好玩: 为什么不收集这些?
typedef int transaction_key;
typedef int doc_id;
class Transaction
{
public:
Transaction(transaction_key key) : m_key(key) {}
AddPaymentDoc(doc_id, const std::string&);
AddInvoiceDoc(doc_id, const std::string&);
// I'd probably have these methods return a unique ID actually, rather than
// create it yourself... or they can return void and you pass in the doc id.
// exception handling/other handling for attempting to reference using a bad id
std::string GetPayment(doc_id);
std::string GetInvoice(doc_id);
std::map <doc_id, std::string> GetPayments() {return Payments;}
std::map <doc_id, std::string> GetInvoices() {return Invoices;}
private:
transaction_key m_key;
std::map <doc_id, std::string> Payments;
std::map <doc_id, std::string> Invoices;
};
答案 5 :(得分:1)
您可能在该怪物的某个点处取消引用NULL或Wild指针。这种事情不会引发异常,它只会导致分段错误(或者你的平台等同于它)。
答案 6 :(得分:1)
直接阅读你想要建模的简单数据结构,我最终得到了这个。
std::map
是一个有序的容器,因此您最终得到了所需的订单。通过避免明确使用指针并允许容器管理动态内存,模型使用起来更简单,更不容易出错。
如果您有可能获得更多文档类型而不仅仅是付款和发票,那么我可能会将文档类型设为枚举,并将事务从文档类型映射到DocumentMap
。
#include <map>
#include <string>
// Map of docid to comma separated string of files
typedef std::map<int, std::string> DocumentMap;
struct Transaction
{
DocumentMap payments;
DocumentMap invoices;
};
// map of transaction id to transaction contents
typedef std::map<int, Transaction> TransactionMap;
TransactionMap batch;
void foo(TransactionMap& batch)
{
// ...
batch[transno].invoices[docno] = page;
// ...
}