首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

文本解析的程序编写寻求技术支援,该怎么解决

2012-04-19 
文本解析的程序编写寻求技术支援有一个文本文件test.txt,内容如下:[msg_type400][Session_Id1000][Conte

文本解析的程序编写寻求技术支援
有一个文本文件test.txt,内容如下:
[msg_type=400][Session_Id=1000][Context_Id=1024875051][service_id=10][bussiness_id=1][owner_type=1][Cycle_Id=200802][own_id=1029920883][offset=0][Life_type=1][Resource_ID=P0];
[msg_type=400][Session_Id=1001][Context_Id=1024875051][service_id=12][bussiness_id=2][owner_type=2][Cycle_Id=200802][own_id=1029923986][offset=1][Life_type=2][Resource_ID=P1];
[msg_type=400][Session_Id=1002][Context_Id=1024875051][service_id=32][bussiness_id=6][owner_type=3][Cycle_Id=200802][own_id=1029926083][offset=5][Life_type=4][Resource_ID=P2];
[msg_type=401][Session_Id=2000][Context_Id=1024875056][service_id=52][bussiness_id=3][owner_type=4][Cycle_Id=200802][own_id=1029920384][offset=0][Life_type=1][Resource_ID=P4];
[msg_type=401][Session_Id=2001][Context_Id=1024875066][service_id=42][bussiness_id=9][owner_type=5][Cycle_Id=200802][own_id=1029922891][offset=6][Life_type=6][Resource_ID=P7];
[msg_type=401][Session_Id=2002][Context_Id=1024875078][service_id=22][bussiness_id=0][owner_type=6][Cycle_Id=200802][own_id=1029930483][offset=2][Life_type=3][Resource_ID=P3];
............
请问怎样将此文件读取出来;
按[后面就是一个元素属性,遇到=,这个元素属性结束,同时这个值开始,遇到]这个元素值结束;
请问在c++中怎样实现,从打开文件到解析文件,到将取出来的值赋值给变量?
初学C++,时间紧,不懂得很多;高分相送

[解决办法]
这个用sscanf比较容易实现。
[解决办法]
每次读入一行,对每一行进行解析
解析一行的时候,最简单的使用字符串指针,依次判断,读取数据。
[解决办法]
最简单的使用字符串指针:
定义一些指针 指向各个xxx= 然后取到各个值 我也是这么想的 也是笨方法 lx的还有更好的方法了么?
[解决办法]
写一个类,以两个为一个单元(两行内容刚好不同),提供分别读取某个字段值的功能,如msg_type、Resource_ID,实际就是获得一个串,然后进行匹配获取其值。

然后在主方法中,读取一行丢给这个类,然后调用这个类提供获取字段值的方法获取字段值。
[解决办法]
严重同意akirya
[解决办法]
看看《C++ Primer》上面写的很清楚
[解决办法]

C/C++ code
#include "iostream"using namespace std;bool next_section(char* name, char* value, FILE* file){    char c = 0;    if (!name || !value || !file || feof(file))        return false;    while (fgetc(file) != '[');    while ((c = fgetc(file)) != '=')        *name++ = c;    (*name) = 0;    while ((c = fgetc(file)) != ']')        *value++ = c;    (*value) = 0;    return true;}int main(){    FILE* file = 0;    char name[128];    char value[128];    file = fopen("text.txt", "r");    if (!file)        return 1;    while (next_section(name, value, file))        cout<<name<<" = "<<value<<endl;    fclose(file);    return 0;}
[解决办法]
C/C++ code
以你的文件内容为例,text.txt中,运行结果msg_type = 400Session_Id = 1000Context_Id = 1024875051service_id = 10bussiness_id = 1owner_type = 1Cycle_Id = 200802own_id = 1029920883offset = 0Life_type = 1Resource_ID = P0msg_type = 400Session_Id = 1001Context_Id = 1024875051service_id = 12bussiness_id = 2owner_type = 2Cycle_Id = 200802own_id = 1029923986offset = 1Life_type = 2Resource_ID = P1msg_type = 400Session_Id = 1002Context_Id = 1024875051service_id = 32bussiness_id = 6owner_type = 3Cycle_Id = 200802own_id = 1029926083offset = 5Life_type = 4Resource_ID = P2msg_type = 401Session_Id = 2000Context_Id = 1024875056service_id = 52bussiness_id = 3owner_type = 4Cycle_Id = 200802own_id = 1029920384offset = 0Life_type = 1Resource_ID = P4msg_type = 401Session_Id = 2001Context_Id = 1024875066service_id = 42bussiness_id = 9owner_type = 5Cycle_Id = 200802own_id = 1029922891offset = 6Life_type = 6Resource_ID = P7msg_type = 401Session_Id = 2002Context_Id = 1024875078service_id = 22bussiness_id = 0owner_type = 6Cycle_Id = 200802own_id = 1029930483offset = 2Life_type = 3Resource_ID = P3上面的程序把 名字和值都保存为 char*了,如果你要想把值转成别的类型,就使用相关函数转换就可以了,比如char*转 int ,使用 atoi 


[解决办法]
星羽
的代码不错,不过告诉你,最好的方式是用scanf的正则表达式来读。
这样以后可以很方便地扩展。

相关资料:
ANSI C 标准向 scanf() 增加了一种新特性,称为扫描集(scanset)。 扫描集定义一个字符集合,可由 scanf() 读入其中允许的字符并赋给对应字符数组。 扫描集合由一对方括号中的一串字符定义,左方括号前必须缀以百分号。 例如,以下的扫描集使 scanf() 读入字符 A、B 和 C:
%[ABC]

使用扫描集时,scanf() 连续吃进集合中的字符并放入对应的字符数组,直到发现不在集合中的字符为止(即扫描集仅读匹配的字符)。返回时,数组中放置以 null 结尾、由读入字符组成的字符串。

用字符 ^ 可以说明补集。把 ^ 字符放为扫描集的第一字符时,构成其它字符组成的命令的补集合,指示 scanf() 只接受未说明的其它字符。
对于许多实现来说,用连字符可以说明一个范围。 例如,以下扫描集使 scanf() 接受字母 A 到 Z:
%[A-Z]
重要的是要注意扫描集是区分大小写的。因此,希望扫描大、小写字符时,应该分别说明大、小写字母。
scanf() 返回等于成功赋值的域数的值,但由于星号修饰符而读入未赋值的域不计算在内。给第一个域赋值前已出错时,返回 EOF。
[解决办法]
个人也认为使用sscanf的扫描集比较容易实现~ 如果不需要判断属性名称,可以如下:

C/C++ code
#include <cstdio>#include <cstring>#include <iostream>using namespace std;int main(){   const char *line =    "[msg_type=400][Session_Id=1000][Context_Id=1024875051][service_id=10][bussiness_id=1]\   [owner_type=1][Cycle_Id=200802][own_id=1029920883][offset=0][Life_type=1][Resource_ID=P0];";   int msg_type, Session_Id, Context_Id, service_id, bussiness_id;   int owner_type, Cycle_Id, own_id, offset, Life_type;   char Resource_Id[8];   char fmt[256]={0};   for(int i=0; i<10; ++i) strcat(fmt,"%*[^=]=%d");   strcat(fmt, "%*[^=]=%[^]]");   sscanf(line, fmt, &msg_type, &Session_Id, &Context_Id, &service_id, &bussiness_id,          &owner_type, &Cycle_Id, &own_id, &offset, &Life_type, Resource_Id);   cout<<"own_id="<<own_id<<endl;   return 0;} 

热点排行