I am very confused on how to parse multiple delimiters using getline and strtok in c++

守給你的承諾、 提交于 2019-12-11 13:11:35

问题


My code is posted below. I want to be able to parse using the delimiters " ()," and convert the strings into integers in cpp.

while(getline(fin, line))
{
    x  = atoi((strtok(line.c_str(),'(,)'));
    xx = atoi((strtok(NULL,"(),"));
    xxx = atoi((strtok(NULL,"(),")));
    cout << x << "    " << xx << "    " << xxx << "\n";
}

but for some reason I get the following errors

GraphTest.cpp:134: error: invalid conversion from ‘const char*’ to ‘char*’

GraphTest.cpp:134: error: initializing argument 1 of ‘char* strtok(char*, const char*)’

The .c_str should convert my string into a c type string allowing me to use the atoi and strtok functions. I am very confused and would appreciate any help.


回答1:


I had a similar problem with needing to parse with multiple delimiters and could not find a good solution anywhere so I ended up just making a function.

string getlineMultDelimiter(istream &is, string dlm, bool includeDelimiter)
{
    string str;
    char c;
    bool found = false;

    while (!found && is)
    {
        for (size_t i = 0; i < dlm.length() && !found; ++i)
            found = dlm[i] == is.peek();

        if (!found || includeDelimiter)
        {
            is.get(c);
            str += c;
        }
    }
    return str;
}

It will use all chars in the dlm string as a delimiter and you can choose whether to include the delimiter or not in the returned string.




回答2:


It doesn't compile because c_str() returns a const char*, it's supposed to be a constant pointer to not modifiable internal string buffer. On the other hand strtok() accepts a char* because it modifies its input string.

Now you have two options: get a C string usable from strtok() or rewrite everything to be C++.

Create a new modifiable C string from your C++ string:

char* modifiableLine = strdup(line.c_str());

x  = atoi((strtok(modifiableLine, "(,)"));
// Other processing

free(modifiableLine);

You can do it if you have to keep a big amount of C code wrapped inside a C++ function/class. A better solution is to use what C++ Standard Library offers (also dropping atoi() C function if C++ 11). Let's first write an helper function:

int readNextInt(istringstream& is, const string& delimiters) {
    string token;

    if (getline(is, token, delimiters))
        return stoi(token);

    return 0; // End of stream?
}

Used like this:

istringstream is(line)
x = readNextInt(is, "(),");
xx = readNextInt(is, "(),");
xxx = readNextInt(is, "(),");

Please note that standard C++ function getline() doesn't accept a string for delimiters parameter but a single char only then you have to write your own overloaded version. Take a look to this post for good and nice possible implementation (you may also simply replace getline() with is >> token after is.imbue(), see given example).

Well...if you're already using Boost then you may simply use boost::tokenizer.



来源:https://stackoverflow.com/questions/27249617/i-am-very-confused-on-how-to-parse-multiple-delimiters-using-getline-and-strtok

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!