返回信息流刚学C++不久,就看了C++primer,李学明老师布置了个压缩BMP图片的作业,自己写的代码,运行提示:map/set iterator not dereferencable。调了好久找到在哪出错了但是不知道为什么错了,请求牛人指导,谢谢。程序我上传了。
附件(2.1KB) practice.cpp
这是一条镜像帖。来源:北邮人论坛 / cpp / #45547同步于 2010/11/2
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
C++新手,编了个压缩BMP图片的程序,有错误求改正
laksjd88
2010/11/2镜像同步6 回复
订阅后,新回复会通过你的通知中心匿名送达。
6 条回复
没太明白你的意思,既然是压缩,怎么没有输出啊?
改了几行,没有运行错误了.
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <map>
using namespace std;
int main(int argc,char **argv)
{
//以二进制打开BMP图片,并将流置位于文件末尾
/*
if (argc < 2)
{
cerr << "no input" << endl;
return EXIT_FAILURE;
}
*/
ifstream infile;
infile.open("capture.bmp", ifstream::binary|fstream::ate);
if (!infile)
{
cerr<<"can no open"<<endl;
return EXIT_FAILURE;
}
//用multimap保存图片数据区,每个key值对应4字节
//multimap<size_t,int> xiangliang;
multimap<size_t, char> xiangliang; //这里不是char?
char yuansu;
ifstream::pos_type end_mark = infile.tellg(); //返回末尾下一个位置
infile.seekg(1078, fstream::beg);//1078是BMP图片文件头相对数据区的偏移量
size_t cishu=0;
while (infile && (infile.tellg() != end_mark))
{
//一个key四个字节
for (int j = 0; j != 4; j++)
{
infile.get(yuansu);
xiangliang.insert(make_pair(cishu,yuansu));
}
++cishu;
}
//infile.clear();
infile.close(); //是close?
//取前100个key值为初始码书,从第101个key值开始与原始码书逐元素做比较,求绝对值差的和
typedef multimap<size_t, char>::iterator xiangliang_it;
for(int i = 101; i != cishu; ++i)
{
xiangliang_it beg=xiangliang.lower_bound(i);
xiangliang_it end=xiangliang.upper_bound(i);
while (beg != end)
{
for (int j = 0; j != 100; ++j)
{
//遍历100个原始码书
xiangliang_it com_beg = xiangliang.lower_bound(j);
xiangliang_it com_end = xiangliang.upper_bound(j);
int sum=0;
while (com_beg != com_end)
{
sum += abs(beg->second - com_beg->second);//与key值i的码字逐元素做比较,求绝对值差的和
++com_beg;
++beg;
}
//恢复beg与com_beg初值,为下面使用
for (int time = 0; time != 4; ++time)
{
--beg;
--com_beg;
}
int min_value;
min_value=sum;
//运行到此处无错
if (sum < min_value)
{
//若当前值小于前一个和,则将当前key值原始码书赋予key值为i的码字
min_value=sum;
//system("pause");
while(com_beg!=com_end)
{
beg->second = com_beg->second;
++com_beg;
++beg;
}
}
else
{
for(int T = 0; T != 4; ++T)
{
++beg;
}
}
}
//for(int T = 0; T != 3; ++T) //这里不是4?
for(int T = 0; T != 4; ++T)
{
//恢复beg,为下面使用
--beg;
}
}
}
return 0;
}
【 在 kmplayer 的大作中提到: 】
: 没太明白你的意思,既然是压缩,怎么没有输出啊?
: 改了几行,没有运行错误了.
: #include <vector>
: ...................
哦对,我对multimap做的更改,并没有体现在图片上,我编译的时候没有错误,可以通过,但是用windows的运行调试程序的时候就出错误了。
谢谢你,你能不能提示我一下或者大体给我个框架,怎么把修改后的multimap再复制回图片的数据区?
非常感谢。
又帮你找到了一些逻辑上的错误, 你先看看我说的对不对.
至于修改, 新建了文件,把头和修改后的value一次写进去即可吧.
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <map>
using namespace std;
int main(int argc,char **argv)
{
//以二进制打开BMP图片,并将流置位于文件末尾
/*
if (argc < 2)
{
cerr << "no input" << endl;
return EXIT_FAILURE;
}
*/
ifstream infile;
infile.open("capture.bmp", ifstream::binary|fstream::ate);
if (!infile)
{
cerr<<"can no open"<<endl;
return EXIT_FAILURE;
}
//用multimap保存图片数据区,每个key值对应4字节
//multimap<size_t,int> xiangliang;
multimap<size_t, char> xiangliang; //这里不是char?
char yuansu;
ifstream::pos_type end_mark = infile.tellg(); //返回末尾下一个位置
infile.seekg(1078, fstream::beg);//1078是BMP图片文件头相对数据区的偏移量
size_t cishu=0;
while (infile && (infile.tellg() != end_mark))
{
//一个key四个字节
for (int j = 0; j != 4; j++)
{
infile.get(yuansu);
xiangliang.insert(make_pair(cishu,yuansu));
}
++cishu;
}
cout << cishu << endl;
//infile.clear();
infile.close(); //是close?
//取前100个key值为初始码书,从第101个key值开始与原始码书逐元素做比较,求绝对值差的和
typedef multimap<size_t, char>::iterator xiangliang_it;
for(int i = 101; i != cishu; ++i)
{
cout << i << endl; //加个标志
xiangliang_it beg=xiangliang.lower_bound(i);
xiangliang_it end=xiangliang.upper_bound(i);
//while (beg != end) //这个是死循环啊!!!!!!!!!!!! 貌似一次处理一个key的4个value,while多余吧?
//{
int min_value = -1; //放到这里了
for (int j = 0; j != 100; ++j)
{
//遍历100个原始码书
xiangliang_it com_beg = xiangliang.lower_bound(j);
xiangliang_it com_end = xiangliang.upper_bound(j);
int sum=0;
while (com_beg != com_end)
{
sum += abs(beg->second - com_beg->second);//与key值i的码字逐元素做比较,求绝对值差的和
++com_beg;
++beg;
}
//恢复beg与com_beg初值,为下面使用
for (int time = 0; time != 4; ++time)
{
--beg;
--com_beg;
}
//这里逻辑有问题吧???
//int min_value = sum;
//运行到此处无错
if (sum < min_value) //永远一样啊.
{
//若当前值小于前一个和,则将当前key值原始码书赋予key值为i的码字
min_value=sum;
//system("pause");
while (com_beg != com_end)
{
beg->second = com_beg->second;
++com_beg;
++beg;
}
}
else
{
for(int T = 0; T != 4; ++T)
{
++beg;
}
}
}
//for(int T = 0; T != 3; ++T) //这里不是4?
for(int T = 0; T != 4; ++T)
{
//恢复beg,为下面使用
--beg;
}
// }
}
return 0;
}
【 在 kmplayer 的大作中提到: 】
: 又帮你找到了一些逻辑上的错误, 你先看看我说的对不对.
: 至于修改, 新建了文件,把头和修改后的value一次写进去即可吧.
: #include <vector>
: ...................
关于死循环:
m.lower_bound(k) 返回一个迭代器,指向键不小于k的第一个元素
m.upper_bound(k) 返回一个迭代器,指向键大于k的第一个元素
我在C++ primer上看到如下代码:
typedef multimap<string string>::iterator authors_it;
authors_it beg=authors.lower_bound(search_item),
end=authors.upper_bound(search_item);
while(beg!=end){
cout<<beg->second<<endl;
++beg;
}
所以我觉得不会有死循环。
关于逻辑有问题:
那个if语句永远为真吗?是不是sum在跳出while后就又变为0了?
谢谢指导啊。
你仔细看看你的beg 先加4,减4,又加4,又减4, 根本就没变.
【 在 laksjd88 的大作中提到: 】
: : 又帮你找到了一些逻辑上的错误, 你先看看我说的对不对.
: : 至于修改, 新建了文件,把头和修改后的value一次写进去即可吧.
: : #include <vector>
: ...................
帮你弄了个输出,ms没有体现出压缩啊,你自己参考着改改吧.
bless,解决问题的过程就是学习的最好途径.
加油!
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <map>
using namespace std;
int main(int argc,char **argv)
{
//以二进制打开BMP图片,并将流置位于文件末尾
/*
if (argc < 2)
{
cerr << "no input" << endl;
return EXIT_FAILURE;
}
*/
ifstream infile;
infile.open("capture.bmp");
if (!infile)
{
cerr<<"can no open"<<endl;
return EXIT_FAILURE;
}
ofstream outfile("cap2.bmp");
//用multimap保存图片数据区,每个key值对应4字节
//multimap<size_t,int> xiangliang;
multimap<size_t, char> xiangliang; //这里不是char?
char yuansu;
ifstream::pos_type end_mark = infile.tellg(); //返回末尾下一个位置
for (int i = 0; i != 1078; i++)
{
infile.get(yuansu);
outfile.put(yuansu);
}
infile.seekg(1078, fstream::beg);//1078是BMP图片文件头相对数据区的偏移量
size_t cishu=0;
for (int i = 0; i != 1078; i++)
{
infile.get(yuansu);
outfile.put(yuansu);
}
while (infile && (infile.tellg() != end_mark))
{
//一个key四个字节
for (int j = 0; j != 4; j++)
{
infile.get(yuansu);
xiangliang.insert(make_pair(cishu,yuansu));
}
++cishu;
}
cout << cishu << endl;
//infile.clear();
infile.close(); //是close?
//取前100个key值为初始码书,从第101个key值开始与原始码书逐元素做比较,求绝对值差的和
typedef multimap<size_t, char>::iterator xiangliang_it;
for (int i = 0; i != 100; i++)
{
xiangliang_it beg=xiangliang.lower_bound(i);
xiangliang_it end=xiangliang.upper_bound(i);
while (beg != end)
{
outfile.put(beg->second);
++beg;
}
}
for(int i = 101; i != cishu; ++i)
{
cout << i << endl; //加个标志
xiangliang_it beg=xiangliang.lower_bound(i);
xiangliang_it tmp = beg;
xiangliang_it end=xiangliang.upper_bound(i);
//while (beg != end) //这个是死循环啊!!!!!!!!!!!! 貌似一次处理一个key的4个value,while多余吧?
//{
int min_value = -1; //放到这里了
for (int j = 0; j != 100; ++j)
{
//遍历100个原始码书
xiangliang_it com_beg = xiangliang.lower_bound(j);
xiangliang_it com_end = xiangliang.upper_bound(j);
int sum=0;
while (com_beg != com_end)
{
sum += abs(beg->second - com_beg->second);//与key值i的码字逐元素做比较,求绝对值差的和
++com_beg;
++beg;
}
//恢复beg与com_beg初值,为下面使用
for (int time = 0; time != 4; ++time)
{
--beg;
--com_beg;
}
//这里逻辑有问题吧???
//int min_value = sum;
//运行到此处无错
if (sum < min_value) //永远一样啊.
{
//若当前值小于前一个和,则将当前key值原始码书赋予key值为i的码字
min_value=sum;
//system("pause");
while (com_beg != com_end)
{
beg->second = com_beg->second;
++com_beg;
++beg;
}
}
/*
else
{
for(int T = 0; T != 4; ++T)
{
++beg;
}
}
*/
}
while (tmp != end)
{
outfile.put(tmp->second);
++tmp;
}
/*
//for(int T = 0; T != 3; ++T) //这里不是4?
for(int T = 0; T != 4; ++T)
{
//恢复beg,为下面使用
--beg;
}
*/
// }
}
return 0;
}
【 在 kmplayer 的大作中提到: 】
: 你仔细看看你的beg 先加4,减4,又加4,又减4, 根本就没变.
: 【 在 laksjd88 的大作中提到: 】
: : : 又帮你找到了一些逻辑上的错误, 你先看看我说的对不对.
: ...................
OK,谢谢,我根据你说的我再自己研究研究。