帮助进行半复杂的C ++赋值

时间:2009-09-01 18:43:35

标签: c++

这是一个非常简单的问题,我很确定,但我很感激帮助。 :)

这是.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 ++代码,并告诉我昨天要完成一些事情。它基本上归结为在那里获取数据结构,加载它然后在其他地方输出它。当我问这个问题时,我只是想快速地把它敲出来。我很欣赏这些设计建议。

7 个答案:

答案 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;

    // ...
}