免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6171 | 回复: 11
打印 上一主题 下一主题

请教在map容器中使用string的c_str()方法的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-05-18 12:12 |只看该作者 |倒序浏览
希望通过map对象将配置文件保存在内存中并方便调用
首先我定义了这样一个容器
map<string,string> config_file;
然后通过ifstream读取配置文件并进行解析,然后保存到config_file容器中
类似下面这样
config_file["datafile"] = "config.ini";

接着再次调用ifstream并传入参数config_file["datafile"].c_str()

  1. ifstream sdata(config_file["datafile"].c_str());
复制代码
结果是使用sdata什么也读不出来,就是说无法读出文件内容,和
  1. ifstream sdata("")
复制代码
效果一样,好象config_file["datafile"].c_str()没有值或者值不是"config.ini"似的
然而我在后面
  1. cout<<config_file["datafile"].c_str()<<endl;
复制代码
确明白无误的输出了"config.ini"

而如果是普通的字符串指针则完全没有问题,如
char *file = "config.ini"
ifstream sdata(file);

或者普通的string对象也正常
string abc = "config.ini";
const char* newabc = abc.c_str();
ifstream sdata(newabc);


所以就有三个疑问:
1,以map作为容器的string对象是不是有些特殊? ifstream sdata(config_file["datafile"].c_str());这种使用方式是不是不正确?
不知道是不是跟我定义map容器方式有关系? 我是这样对其元素赋值的

将上述的config_file作为指针传入一个解析配置文件的函数
parse(&config_file){
//在其中这样赋值
string var = "datafile";
string val = "config.ini";
(*config_file)[var] = val;
}
2,另外查了一下资料,听说c_str()好象有只能使用一次的说法?
但我测试
const char* abc = config_file["datafile"].c_str();
cout<<abc<<endl;
cout<<abc<<endl;
cout<<abc<<endl;
连续输出几变都没什么问题,不知具体是怎么回事?

3,想问一下linux下gdb针对这种情况有没有什么调试的方法?
用linux时间不短了,gdb基本没用过..还请大家不吝赐教,比如如何断在ifstream sdata(newabc);这里并查看newabc的值和其对应地址的内存?

非常感谢!!

[ 本帖最后由 deadcat 于 2007-5-18 12:15 编辑 ]

论坛徽章:
24
狮子座
日期:2013-12-31 10:48:0015-16赛季CBA联赛之吉林
日期:2016-04-18 14:43:1015-16赛季CBA联赛之北控
日期:2016-05-18 15:01:4415-16赛季CBA联赛之上海
日期:2016-06-22 18:00:1315-16赛季CBA联赛之八一
日期:2016-06-25 11:02:2215-16赛季CBA联赛之佛山
日期:2016-08-17 22:48:2615-16赛季CBA联赛之福建
日期:2016-12-27 22:39:272016科比退役纪念章
日期:2017-02-08 23:49:4315-16赛季CBA联赛之八一
日期:2017-02-16 01:05:3415-16赛季CBA联赛之山东
日期:2017-02-22 15:34:5615-16赛季CBA联赛之上海
日期:2017-11-25 16:17:5015-16赛季CBA联赛之四川
日期:2016-01-17 18:38:37
2 [报告]
发表于 2007-05-18 14:23 |只看该作者
原帖由 deadcat 于 2007-5-18 12:12 发表
希望通过map对象将配置文件保存在内存中并方便调用
首先我定义了这样一个容器
map<string,string> config_file;
然后通过ifstream读取配置文件并进行解析,然后保存到config_file容器中
类似下面这样
c ...


是不是像这个:

  1. #include <iostream>
  2. #include <fstream>
  3. #include <map>

  4. std::map<std::string, std::string> config_file;

  5. char     buf[4096];

  6. int main(int argc, char *argv[])
  7. {
  8.         config_file["datafile"] = "test01.cc";

  9.         std::ifstream   myfile(config_file["datafile"].c_str());

  10.         myfile.read(buf, 1024);

  11.         buf[myfile.gcount()] = '\0';

  12.         std::cout << buf << std::endl;

  13.         return 0;
  14. }

复制代码


没问题呀。

论坛徽章:
0
3 [报告]
发表于 2007-05-25 10:21 |只看该作者
抱歉这么晚才回复,我试了几天还是不知道怎么回事,但出问题的位置应该能确定就是在前面所说的赋值的地方


  1. string var = "datafile";
  2. string val = "config.ini";
  3. (*config_file)[var] = val;
复制代码

上面这种方式是没有问题的
但是下面的

  1. string abc="aadddaabc";
  2. string var =  abc.substr(0,5);
  3. string val =  abc.substr(6,string::npos);
  4. (*config_file)[var] = val;
复制代码

就会出问题,但很奇怪的是我用cout<<var<<val<<endl;输出内容都正常,不知道怎么回事加到map容器就不行了。。。
恳请大虾指教调式方法,我可以自己调一下看看,谢谢

[ 本帖最后由 deadcat 于 2007-5-25 10:22 编辑 ]

论坛徽章:
24
狮子座
日期:2013-12-31 10:48:0015-16赛季CBA联赛之吉林
日期:2016-04-18 14:43:1015-16赛季CBA联赛之北控
日期:2016-05-18 15:01:4415-16赛季CBA联赛之上海
日期:2016-06-22 18:00:1315-16赛季CBA联赛之八一
日期:2016-06-25 11:02:2215-16赛季CBA联赛之佛山
日期:2016-08-17 22:48:2615-16赛季CBA联赛之福建
日期:2016-12-27 22:39:272016科比退役纪念章
日期:2017-02-08 23:49:4315-16赛季CBA联赛之八一
日期:2017-02-16 01:05:3415-16赛季CBA联赛之山东
日期:2017-02-22 15:34:5615-16赛季CBA联赛之上海
日期:2017-11-25 16:17:5015-16赛季CBA联赛之四川
日期:2016-01-17 18:38:37
4 [报告]
发表于 2007-05-25 11:03 |只看该作者

回复 3楼 deadcat 的帖子

关于 gdb 说来话长, google 一下,很多的。

论坛徽章:
0
5 [报告]
发表于 2007-05-26 18:24 |只看该作者
ifstream sdata(config_file["datafile"].c_str()); 这种方式没问题,
parse(&config_file) 这里有问题, 对 config_file 做 & 运算,你想干什么?
如果需要用类似指针的方式操作config_file的成员,用iterator

2,另外查了一下资料,听说c_str()好象有只能使用一次的说法?

参考的什么资料?

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
6 [报告]
发表于 2007-05-26 22:03 |只看该作者
c_str()的值建议只用一次

  1.     string a = "hello123";
  2.     string b = a;
  3.     const char* ptr = b.c_str();
  4.     cout << ptr << endl;
  5.     b = "change value";
  6.     cout << ptr << endl;
复制代码

象这样,ptr指向的内容会不会跟着b变应该与具体的实现相关(在COW的情况下是不变的)
不知道楼主是怎么做的,能把代码贴一下吗?

论坛徽章:
0
7 [报告]
发表于 2007-05-28 14:35 |只看该作者
感谢大家的热心帮助,我尽快将出问题的代码直接帖出来
to antonym55 : c_str只用一次是从搜索引擎上搜的。。。
to zhujiang73 : gdb的用法博大精深,搜索引擎的确提供了很多的资料,各种命令参数一大堆,我想其实大家常用的也就其中的一小部分, 就好像VC中我们一般用的就是查看一些变量运行时的值和值的变化,或者一段内存区域中的变化等等,以及各种进制的转换,不知道哪位大虾总结一下? 感激不尽!

论坛徽章:
0
8 [报告]
发表于 2007-05-28 17:13 |只看该作者
下面就是出问题的代码


  1. void getconfig(char* config_file, map<string,string>* config_map){

  2.         char *ch = new char[100];
  3.         int sep = 0;
  4.         string tmpstr;

  5.         basic_ifstream<char> cfg(config_file);
  6.         while(cfg.getline(ch,100)){
  7.                 tmpstr = ch;
  8.                 sep = tmpstr.find("=");
  9.                 if(sep<=0){
  10.                         continue;
  11.                 }
  12.                         
  13.                string var = tmpstr.substr(0,sep);        // 如果这一行用         string var = "aa"; 代替后面就可以正常使用
  14.                string val = tmpstr.substr(sep+1,string::npos);
  15.        

  16.                 (*config_map)[var] = val;
  17.                
  18.         //(*config_map)["filename"] = "config.ini"; 这也没问题
  19.         }
  20.         cfg.close();
  21.         delete [] ch;
  22. }

复制代码


config.ini文件如下:

  1. [system]
  2. filename=pack.txt
  3. interval=2000
  4. [connection]
  5. ipaddr=192.168.1.2
  6. port=6000

复制代码

论坛徽章:
0
9 [报告]
发表于 2007-05-29 00:49 |只看该作者
看来楼主还是没明白,唉。只想提醒下楼主,

1. 访问STL 容器的时候最好是用 Iterator
2. 使用STL 提供的成员函数

我写了个例子你参考下

  1. #include<iostream>
  2. #include<map>
  3. #include<string>
  4. #include<fstream>

  5. using namespace std;

  6. typedef map<string, string> TConfigMap;
  7. typedef TConfigMap::iterator TConfigMapIt;

  8. //这里用了引用,用Iterator没有直接的好处
  9. //因为要修改里面的容,所以不是const 引用
  10. //实在不习惯一边用string, 一边用c-string,
  11. //所以第一个参数就没用char *
  12. //
  13. bool foo(string config_file, TConfigMap &config_map);

  14. int main ( int argc, char *argv[] )
  15. {
  16.     string config_file = "config.ini";
  17.     TConfigMap config_map;

  18.     config_map["datafile"] = config_file;

  19.     bool ret = foo(config_file, config_map);

  20.     if (!ret)
  21.     {
  22.         cerr << "read data file faild" << endl;
  23.         return -1;
  24.     }

  25.     TConfigMapIt it = config_map.begin();
  26.     for (; it != config_map.end(); ++it)
  27.     {
  28.         cout << it->first << " = " << it->second << endl;
  29.     }

  30.     return 0;
  31. }                       

  32. bool foo(string filename, TConfigMap &config_map)
  33. {
  34.     ifstream inifile(filename.c_str());
  35.     //
  36.     //这里用下面这种方法也是可以的,不存在楼主所说的问题
  37.     //ifstream inifile(config["datafile"].c_str());
  38.     //

  39.     if (!inifile)
  40.     {
  41.         cerr << "open config file faild" << endl;
  42.         return false;
  43.     }

  44.     string temp;

  45.     while (getline(inifile, temp))
  46.     {
  47.         string::size_type idx = string::npos;

  48.         idx = temp.find("=");
  49.         if (idx == string::npos)
  50.         {
  51.             continue;
  52.         }
  53.         //这里仅举一下例子,没处理 = 前后有空格的情况
  54.         string var = temp.substr(0, idx);
  55.         string val = temp.substr(idx + 1);
  56.         config_map[var] = val;
  57.     }

  58.     inifile.close();
  59.     return true;
  60. }
复制代码


config.ini文件内容与你的相同

论坛徽章:
0
10 [报告]
发表于 2007-05-29 11:19 |只看该作者
多谢关于c-string的提醒, 我的C的大脑还没转变过来:P

不过我说的有问题其实不是第一次读取config.ini的问题,是config.ini里包含的变量filename,即赋值给config_map["filename"]的值pack.txt,然后再用fstream读取的时候会出问题,而不是下面第一次读取的时候

  1. //
  2.     //这里用下面这种方法也是可以的,不存在楼主所说的问题
  3.     //ifstream inifile(config["datafile"].c_str());
  4.     //

复制代码

  1.         string var = temp.substr(0, idx);
  2.         string val = temp.substr(idx + 1);
  3.         config_map[var] = val;  // 这里应该是(*config_map)[var]? 我看见传进来的好像是引用?
复制代码

关于iterator,我主要是希望能够通过使用索引变量的方式在特定地方使用其中的某一个,比如只用config_map["port"],iterator貌似是用来遍历的?


原帖由 antonym55 于 2007-5-29 00:49 发表
看来楼主还是没明白,唉。只想提醒下楼主,

1. 访问STL 容器的时候最好是用 Iterator
2. 使用STL 提供的成员函数

我写了个例子你参考下
[code]
#include<iostream>
#include<map>
#includ ...

[ 本帖最后由 deadcat 于 2007-5-29 11:23 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP