Reading custom (.ndev) Json-like file structure
From a practical point of view, there is no reason to store your structure in that format. There are simpler ways.
Anyhow, here's a starting point (demo):
#include <iostream>
#include <string>
#include <map>
#include <iomanip>
#include <fstream>
using namespace std;
// your structure
struct person
{
string name, pass, role, mail;
};
// the tokens your format is using
enum class token : char
{
lb = '{',
rb = '}',
sc = ':',
comma = ',',
str,
end
};
token tk; // current token
string str; // if the current token is token::str, str is its value
// get_token breaks the input stream into tokens - this is the lexer, or tokenizer, or scanner
token get_token(istream& is)
{
char c;
if (!(is >> c))
return tk = token::end;
switch (c)
{
case '{':
case '}':
case ':':
case ',':
return tk = token(c);
case '"':
is.unget();
is >> quoted(str);
return tk = token::str;
default: throw "unexpected char";
}
}
// throws if the current token is not the expected one
void expect(istream& is, token expected, const char* error)
{
if (tk != expected)
throw error;
get_token(is);
}
// throws if the current token is not a string
string expect_str(istream& is, const char* error)
{
if (tk != token::str)
throw error;
string s = str;
get_token(is);
return s;
}
// the actual parser; it extracts the tokens one by oneand compares them with the expected order.
// if the order is not what it expects, it throws an exception.
void read(istream& is, person& p)
{
get_token(is); // prepare the first token
expect(is, token::lb, "'{' expected");
map<string, string> m; // key/values storage
while (tk == token::str)
{
string k = expect_str(is, "key expected");
expect(is, token::sc, "':' expected");
string v = expect_str(is, "value expected");
if (m.find(k) == m.end())
m[k] = v;
else
throw "duplicated key";
if (tk == token::comma)
get_token(is);
else
break; // end of of key/value pairs
}
expect(is, token::rb, "'}' expected");
expect(is, token::end, "eof expected");
// check the size of m & the keys & copy from m to p
// ...
}
int main()
{
ifstream is{ "c:/temp/test.txt" };
if (!is)
return -1;
try
{
person p;
read(is, p);
}
catch (const char* e)
{
cout << e;
}
}