遇到麻烦,帮我看看代码!

Veeve 2003-06-11 10:14:00
//下面的程序的目的是为了求得两个元素为自定义类型的集合的差,
//其中TRecord为自定义类型,保存一条数据记录的字段名/字段值映射,
//以及其中的关键字段,在把该记录插入到set集合和求集合差的时候
//根据这些关键字段的值排序。
//现在的问题是最后并没有求得正确的集合差,而是把recordSet1中
//的记录全部拷贝到diffRecordSet中去了,不知道问题出在何处请高
//手相助!
//项目进度被几个算法问题卡了几天了,急死了!
//注:虽然是测试程序,但下面的代码是可用的,可以直接拷贝去调试

//***** test.cpp *****//

#include <vcl>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <string>
#include <iostream>

using namespace std;

typedef vector<AnsiString> TStrVec;
typedef map<AnsiString,AnsiString,less<AnsiString> > TStrMap;

class TRecord
{
public:
TRecord();
TRecord(const TRecord &);
const TRecord &operator=(const TRecord &);
bool operator==(const TRecord &) const;
bool operator<(const TRecord &) const;
TStrMap fieldsMap; //保存字段名和字段值的映射
TStrVec keyFields; //保存该记录的关键字段,用于根据这些字段的值判断记录的大小
private:
void mcopy(const TRecord &otherRecord);
};

TRecord::TRecord()
{
}
TRecord::TRecord(const TRecord &otherRecord)
{
mcopy(otherRecord);
}

const TRecord & TRecord::operator=(const TRecord &otherRecord)
{
if (&otherRecord!=this)
mcopy(otherRecord);
return *this;
}

bool TRecord::operator==(const TRecord &otherRecord) const
{
if (fieldsMap.empty() || otherRecord.fieldsMap.empty()) return false;
TStrVec::const_iterator p_key;
TStrMap::const_iterator p_this;
TStrMap::const_iterator p_that;
if (keyFields.size()!=0 && otherRecord.keyFields.size()!=0)
{
for (p_key=keyFields.begin();p_key!=keyFields.end();p_key++)
{
p_this=fieldsMap.find((*p_key));
if (p_this==fieldsMap.end()) return false;
p_that=otherRecord.fieldsMap.find((*p_key));
if (p_that==otherRecord.fieldsMap.end()) return false;
if ((*p_this).second != (*p_that).second) return false;
}
}
else
{
if (fieldsMap.size() != otherRecord.fieldsMap.size()) return false;
for (p_this=fieldsMap.begin();p_this!=fieldsMap.end();p_this++)
{
p_that=otherRecord.fieldsMap.find((*p_this).first);
if (p_that==otherRecord.fieldsMap.end()) return false;
if ((*p_this).second != (*p_that).second) return false;
}
}
return true;
}

bool TRecord::operator<(const TRecord &otherRecord) const
{
if (fieldsMap.empty()) return true;
TStrVec::const_iterator p_key;
TStrMap::const_iterator p_this;
TStrMap::const_iterator p_that;
if (keyFields.size()!=0 && otherRecord.keyFields.size()!=0)
{
for (p_key=keyFields.begin();p_key!=keyFields.end();p_key++)
{
p_this=fieldsMap.find((*p_key));
if (p_this==fieldsMap.end()) return true;
p_that=otherRecord.fieldsMap.find((*p_key));
if (p_that==fieldsMap.end()) return false;
if ((*p_this).second != (*p_that).second)
{
return ((*p_this).second < (*p_that).second);
}
}
}
else
{
for (p_this=fieldsMap.begin();p_this!=fieldsMap.end();p_this++)
{
p_that=otherRecord.fieldsMap.find((*p_this).first);
if (p_that==otherRecord.fieldsMap.end()) return false;
if ((*p_this).second != (*p_that).second)
return ((*p_this).second < (*p_that).second);
}
}
return true;
}

void TRecord::mcopy(const TRecord &otherRecord)
{
fieldsMap.clear();
keyFields.clear();
copy(otherRecord.fieldsMap.begin(),otherRecord.fieldsMap.end(),inserter(fieldsMap,fieldsMap.begin()));
copy(otherRecord.keyFields.begin(),otherRecord.keyFields.end(),inserter(keyFields,keyFields.begin()));
}

typedef set<TRecord,less<TRecord> > TRecSet;


int main(int argc, char* argv[])
{
TRecSet recordSet1,recordSet2,diffRecordSet; //源记录集合、记录集合差、

TRecord rec1,rec2,rec3;

rec1.keyFields.push_back("field1"); //把field1字段设为rec1的关键字段,根据该字段决定记录值的大小
rec1.fieldsMap.insert(TStrMap::value_type("field1","01")); //插入field1='01'的字段映射,下同
rec1.fieldsMap.insert(TStrMap::value_type("field2","abc"));
rec1.fieldsMap.insert(TStrMap::value_type("field3",""));
recordSet1.insert(TRecSet::value_type(rec1)); //把rec1插入到集合1中

rec2.keyFields.push_back("field1"); //field1字段设为rec1的关键字段
rec2.fieldsMap.insert(TStrMap::value_type("field1","02"));
rec2.fieldsMap.insert(TStrMap::value_type("field2","def"));
rec2.fieldsMap.insert(TStrMap::value_type("field3",""));
recordSet1.insert(TRecSet::value_type(rec2)); //把rec2插入到集合1中

rec3.keyFields.push_back("field1"); //把field1字段设为rec3的关键字段,根据该字段决定记录值的大小
rec3.fieldsMap.insert(TStrMap::value_type("field1","01"));
rec3.fieldsMap.insert(TStrMap::value_type("field2","abc"));
rec3.fieldsMap.insert(TStrMap::value_type("field3",""));
recordSet2.insert(TRecSet::value_type(rec3)); //把rec3插入到集合2中

//求集合1和集合2的差diffRecordSet
set_difference(recordSet1.begin(),recordSet1.end(),
recordSet2.begin(),recordSet2.end(),
inserter(diffRecordSet,diffRecordSet.begin()),
less<TRecord>()
);

//集合1中包含2条记录:
//记录1的值为:
//[keyFields:] "field1"
//[fieldsMap:] "field1"="01"
// "field2"="abc"
// "field3"=""
//记录2的值为:
//[keyFields:] "field1"
//[fieldsMap:] "field1"="01"
// "field2"="def"
// "field3"=""
//*****
//集合2中包含1条记录:
//记录1的值为:
//[keyFields:] "field1"
//[fieldsMap:] "field1"="01"
// "field2"="abc"
// "field3"=""

cout<<"diff size: "<<diffRecordSet.size()<<endl; //

return 0;
}
...全文
27 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
hyifeng 2003-06-16
  • 打赏
  • 举报
回复
呵呵,williamx(稻草人) ,“钱越多就随你搞”是什么意思啊?

下面是set_difference的实现代码:

while (__first1 != __last1 && __first2 != __last2)
if (__comp(*__first1, *__first2)) {
*__result = *__first1;
++__first1;
++__result;
}
else if (__comp(*__first2, *__first1))
++__first2;
else {
++__first1;
++__first2;
}
return copy(__first1, __last1, __result);

fullsail(远航)说的很对,情况正是这样,
我纠正为“operator < 的语义不正确”那里有错了,
“程序最后的返回不应该是return true;而应该是return false”错了??
还请williamx(稻草人)指教。
Veeve 2003-06-16
  • 打赏
  • 举报
回复
对不起上面的朋友们!因为太忙我几天没过来,这个问题后来找到原因了,正如:“hyifeng(适当的思维扩展和想象)”所说,就是<函数的最后一句:return true改成return false就可以了。特别隆重的感谢一下:hyifeng(适当的思维扩展和想象)

to: fullsail(远航) :你讲的是对的,==操作符确实没有起作用,而且你的答案其实已经解决问题了。
to: fangrk(加把油,伙计!) :谢谢你的多次帮忙!

这些天碰到了不少麻烦,幸亏CSDN的朋友!
我不知道有没有机会给你们帮助,如果有我会很乐意!

等些时候再结贴,我只是希望上面的朋友们能够看到我说的谢谢
何哀何欢 2003-06-16
  • 打赏
  • 举报
回复
瓦,不是吧?! 楼上的也太敬业了,钱越多就随你搞!
Veeve 2003-06-12
  • 打赏
  • 举报
回复
哪里改?不是已经using namespace std;了吗?
boxban 2003-06-12
  • 打赏
  • 举报
回复
bool TRecord::operator<(const TRecord &otherRecord) const
的比较规则看起来并不是特别清晰,能不能详细解释一下
fangrk 2003-06-12
  • 打赏
  • 举报
回复
Set_difference is an overloaded name; there are actually two set_difference functions.
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator,
class StrictWeakOrdering>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result,
StrictWeakOrdering comp);


For the first version:
[first1, last1) is a valid range.
[first2, last2) is a valid range.
[first1, last1) is ordered in ascending order according to operator<. That is, for every pair of iterators i and j in [first1, last1) such that i precedes j, *j < *i is false.
[first2, last2) is ordered in ascending order according to operator<. That is, for every pair of iterators i and j in [first2, last2) such that i precedes j, *j < *i is false.
There is enough space to hold all of the elements being copied. More formally, the requirement is that [result, result + n) is a valid range, where n is the number of elements in the difference of the two input ranges.
[first1, last1) and [result, result + n) do not overlap.
[first2, last2) and [result, result + n) do not overlap.
For the second version:
[first1, last1) is a valid range.
[first2, last2) is a valid range.
[first1, last1) is ordered in ascending order according to comp. That is, for every pair of iterators i and j in [first1, last1) such that i precedes j, comp(*j, *i) is false.
[first2, last2) is ordered in ascending order according to comp. That is, for every pair of iterators i and j in [first2, last2) such that i precedes j, comp(*j, *i) is false.
There is enough space to hold all of the elements being copied. More formally, the requirement is that [result, result + n) is a valid range, where n is the number of elements in the difference of the two input ranges.
[first1, last1) and [result, result + n) do not overlap.
[first2, last2) and [result, result + n) do not overlap.


的确,你的例子中间,set_difference只有用到了<比较
hyifeng 2003-06-12
  • 打赏
  • 举报
回复
对不起,没有仔细想就胡乱回答了你的问题。
发完贴后才发现根本不是这样。

上面说的当我放屁
下面的我也不敢再说我肯定正确,仅供参考

纠正:

你的operator < 的语义不正确,
程序最后的返回不应该是return true;而应该是return false;

再次道歉
fullsail 2003-06-12
  • 打赏
  • 举报
回复
代码错了:"<"函数错了。
我看了一下set_difference原码,然后编译了一下。
1.set_difference没有使用==操作符号,这个函数根本没有用,在BCB编译的时候就可以发现。(旁边没有蓝色点。)
2.你可能要疑问那它靠什么比较。这有一点技巧。
a == b 相等于!(a < b) && !( b > a) ,就是a等于b 等效于 a不大于b而且b不大于a.这个在C++的STL中很常见。
但我测试如下代码没有任何输出。
if(!(rec1 < rec3) && !(rec3 < rec1))
{
cout<<"TTTTT1"<<endl;
}
if(!(rec2 < rec3) && !(rec3 < rec2))
{
cout<<"TTTTT2"<<endl;
}
按照你的意思应该输出TTTTT1。但没有。

我看了一下你的代码,但我不理解你的编写思路。但测试发现!(rec1 < rec3) 和 !(rec3 < rec1)都不成立。每次在你函数最后一行代码都return true.可能写错了。

天色不早,我要睡觉了。
hyifeng 2003-06-12
  • 打赏
  • 举报
回复
set_difference(recordSet1.begin(),recordSet1.end(),
recordSet2.begin(),recordSet2.end(),
inserter(diffRecordSet,diffRecordSet.begin()),
less<TRecord>()
);

改为:

set_difference(recordSet1.begin(),recordSet1.end(),
recordSet2.begin(),recordSet2.end(),
inserter(diffRecordSet,diffRecordSet.begin()),
not_equal_to<TRecord>()
);

你的TRecord类需要提供operator!=,
可以这样写:
bool TRecord::operator!=(const TRecord &otherRecord) const
{
return !this->operator ==(otherRecord);
}

结果就会正确。
Wendydd 2003-06-11
  • 打赏
  • 举报
回复
换成
std::vector<Record&> data;
或者
std::vector<Record*> data;

24,860

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧