puelo
puelo

Reputation: 5977

Extracting values from a string c++

i have a problem and i think the solution might be pretty easy but im kinda stuck. I have some kind of config file wich im trying to parse in c++ to get some important values.

It looks like this:

info size=32 bold=0 italic=0 unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0
common lineHeight=32 base=27 scaleW=1024 scaleH=28 pages=1 packed=0 alphaChnl=1
chars count=74
char id=32 x=837 y=15 width=3 height=1 xoffset=-1 yoffset=31 xadvance=8 page=0 chnl=15
char id=33 x=802 y=0 width=4 height=19 xoffset=2 yoffset=8 xadvance=8 page=0 chnl=15
char id=35 x=292 y=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 page=0 chnl=15
char id=38 x=216 y=0 width=18 height=19 xoffset=0 yoffset=8 xadvance=18 page=0 chnl=15

Info, common and chars a basic/global values. Every char line should be saved in an array (or vector) of structs with a similar format (x, y, height, offsetX, offsetY ...)

Now i've tried getline() for example to get every line one by one and then make an istringstream with these lines to "search" those lines for the values i need. Its worth noticing that iam not needing all those values i need a way to just save the one i need for every line.

Thanks in advance for any help here!

Upvotes: 1

Views: 2273

Answers (3)

Loki Astari
Loki Astari

Reputation: 264401

Each line is prefixed by the type of object.
So your reader should read the first word off and then decide what object to read.

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);}
}

For each type of object you need to define a structure to hold the data.

// 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;
};

Now you have to define a method to read the data. In C++ we use operator>> to read data from a stream.

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;
}

Repeat the processes for the other types you need to read. Then writting the read commands becomes simple:

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.
}

Repeat the processes for the other types.

Upvotes: 2

Gir
Gir

Reputation: 849

Try using strtok or a c++ regex library

Upvotes: 0

huseyin tugrul buyukisik
huseyin tugrul buyukisik

Reputation: 11920

There is

important_value=str_from_getline.find(what_to_find);

important_value is a size_t and has the starting point of what you seek in getline() string

Upvotes: 0

Related Questions