2012-08-12 242 views
1

我有一个问题,我认为解决方案可能很简单,但即时卡住。我有一些配置文件,即时通讯设法解析在c + +获得一些重要的价值。从字符串中提取值C++

它看起来像这样:

信息大小= 32粗体= 0斜体= 0的unicode = 1 stretchH = 100光滑= 1节AA = 1个填充= 0,0,0,0
共同 lineHeight是= 32碱= 27 scaleW = 1024 scaleH = 28页= 1填充= 0 alphaChnl = 1
字符计数= 74
ID = 32 X = 837 Y = 15宽度= 3高度= 1 xoffset = -1 yoffset = 31 xadvance = 8 page = 0 CHNL = 15
ID = 33 X = 802 Y = 0宽度= 4高度= 19 X偏移= 2 Y偏移= 8 xadvance = 8页= 0 CHNL = 15
ID = 35 X = 292ÿ = 0 width = 17 height = 19 xoffset = 0 yoffset = 8 xadvance = 16 page = 0 chnl = 15
char id = 37 x = 177 y = 0 width = 19 height = 19 xoffset = -1 yoffset = 8 xadvance = 17页= 0 CHNL = 15
ID = 38×216 = y = 0的宽度= 18高度= 19 X偏移= 0 Y偏移= 8 xadvance = 18页= 0 CHNL = 15

信息,通用和字符的基本/全球值。每个字符行应该保存在一个类似格式(x,y,height,offsetX,offsetY ...)的结构的数组(或向量)中。

现在我试过getline()一行一行,然后用这些行做一个istringstream来“搜索”这些行以获取我需要的值。 值得注意的是,IAM不需要所有这些值,我需要一种方法来保存我需要的每一行。

在此先感谢您的帮助!

回答

2

每一行都是以对象的类型为前缀。
所以你的读者应该读第一个字,然后决定要读取什么对象。

std::ifstream file("data.txt"); 
std::string type; 
while(file >> type) 
{ 
     if (type == "info") { readInfo(file);} 
    else if (type == "common") { readCommon(file);} 
    else if (type == "chars") { readChars(file);} 
    else if (type == "char") { readChar(file);} 
} 

对于每种类型的对象,您需要定义一个结构来保存数据。

// char id=32 x=837 y=15 width=3 height=1 xoffset=-1 yoffset=31 xadvance=8 page=0 chnl=15 
struct CharData 
{ 
    int id; 
    int x; 
    int y; 
    int width; 
    int height; 
    int xoffset; 
    int yoffset; 
    int xadvance; 
    int page; 
    int chnl; 
}; 

现在你必须定义一个读取数据的方法。在C++中,我们使用operator>>来从流中读取数据。

std::istream& operator>>(std::istream& stream, CharData& data) 
{ 
    // All the data is on one line. 
    // So read the whole line (including the '\n') 
    std::string  line; 
    std::getline(stream, line); 

    // convert the single line into a stream for parsing. 
    // One line one object just makes it easier to handle errors this way. 
    std::stringstream linestream(line); 

    // Assume the prefix type information has already been read (now looks like this) 
    // id=32 x=837 y=15 width=3 height=1 xoffset=-1 yoffset=31 xadvance=8 page=0 chnl=15 
    std::string command; 
    while(linestream >> command) // This reads one space separated command from the line. 
    { 
      if (command.substr(0,3) == "id=")  {data.id  = atoi(&command[3]);} 
     else if (command.substr(0,2) == "x=")   {data.x  = atoi(&command[2]);} 
     else if (command.substr(0,2) == "y=")   {data.y  = atoi(&command[2]);} 
     else if (command.substr(0,6) == "width=")  {data.width = atoi(&command[6]);} 
     else if (command.substr(0,7) == "height=") {data.height = atoi(&command[7]);} 
     else if (command.substr(0,8) == "xoffset=") {data.xoffset = atoi(&command[8]);} 
     else if (command.substr(0,8) == "yoffset=") {data.yoffset = atoi(&command[8]);} 
     else if (command.substr(0,9) == "xadvance=") {data.xadvance = atoi(&command[9]);} 
     else if (command.substr(0,5) == "page=")  {data.page  = atoi(&command[5]);} 
     else if (command.substr(0,5) == "chnl=")  {data.chnl  = atoi(&command[5]);} 
    } 
    return stream; 
} 

重复您需要阅读的其他类型的过程。然后写入读取命令变得简单:

std::vector<CharData> charVector; 
void readChar(std::istream& stream) 
{ 
    CharData  data; 
    stream >> data;    // read the object from the stream 
            // This uses the `operator>>` we just defined above. 

    charVector.push_back(data); // put the data item into a vector. 
} 

重复其他类型的过程。

+0

不应该操作员只读取类型?其余的变量应该在依赖于类型的函数中读取 – Gir 2012-08-12 16:00:18

+0

感谢您的扩展代码! – puelo 2012-08-12 20:10:43

+0

轻微明显的错字:除非我误解了某些内容,否则上面所有'itoa'的实例都是“atoi”。 – 2012-08-12 20:42:17

0

important_value=str_from_getline.find(what_to_find); 

important_value是size_t,并且有你在函数getline所追求的()字符串的起点

0

尝试使用的strtok或C++的正则表达式库

+0

不,不。 strtok()是C的憎恶。在C++中有更好的技术。 – 2012-08-12 15:58:06

+0

你能解释为什么吗? – Gir 2012-08-12 16:01:02

+0

那么它使用C-Strings的最糟糕的事情。接下来它改变字符串(所以它不是一个真正的函数)。接下来,这取决于每次调用它时继续工作的突变。 – 2012-08-12 16:05:06