错误的指针:解析令牌时无法计算表达式

时间:2013-12-05 09:43:21

标签: c++ c string pointers tokenize

在解析令牌时,我的所有令牌指针都变坏了,当我在调试器中检查它表示无法评估表达式。 错误:CX0030:错误:无法计算表达式 并且令牌的值为0x00000000

我在这里遗漏了一些东西,我尝试了但是无法纠正它。我知道它与const等的指针分离有关,但是做出改变并没有帮助。

Windows + visual studio 2010和正在解析的文件是unicode UTF16

代码段------

    const wchar_t* const DELIMITER = L"\"";
wchar_t buf[MAX_CHARS_PER_LINE];
fin.getline(buf, MAX_CHARS_PER_LINE);
wchar_t* token[MAX_TOKENS_PER_LINE] = {};
token[0] = wcstok(buf, DELIMITER);
if (token[0]) // zero if line is blank
    {
    int n = 0; 
         for (n = 0; n < MAX_TOKENS_PER_LINE; n++)   
        {
            token[n] = wcstok(0, DELIMITER); // subsequent tokens   --> error ,pointer becomes bad

            if (!token[n]) break; // no more tokens  -------------> code does not go beyond this

buf有整个文件(这是另一个问题,当我尝试读取行时会得到整个文件),有人可以帮我指出我在这里犯的错误吗?

2 个答案:

答案 0 :(得分:0)

你正在丢失第一个令牌,因为n从0开始。对于其余部分我唯一可以想到的是这个代码可以从多个线程运行,这样wcstok中的静态缓冲区会被后续的wcstok调用覆盖(buf,分隔符)。这工作正常(来自单线程应用程序):

char buf[] = "1;2;3;4";

char *tok[10] ={};

tok[0] = strtok(buf, ";");

if (tok[0])
{
    int n = 1;

    while ((tok[n] = strtok(0, ";")) != 0)
    {
        n++;
    }
}

答案 1 :(得分:0)

如果没有发现的分隔符,则token[0] = wcstok(buf, DELIMITER);将为NULL的假设不正确。将有一个令牌;字符串的内容,很容易在下面证明:

#include <iostream>
#include <cwchar>

int main()
{
    wchar_t data[] = L"NoDelimiter";
    wchar_t *ctx = nullptr, *token = wcstok(data, L"\"", &ctx);

    if (token != nullptr)
        std::wcout << token << std::endl;

    return 0;
}

<强>输出

NoDelimiter

因此,这段代码:

token[0] = wcstok(buf, DELIMITER);
if (token[0]) // zero if line is blank

...只有在它确实是一个真正的空白输入时才是正确的(即空为NO字符)。如果甚至有一个字符(例如讨厌的换行符),则该eval将为true并且您将进入for循环。但是你可以通过这样做轻松测试它是否真的是一个空白行:

if (buff[0]) // true if line is not blank

继续前进,因为你故意跳过带我们的第一个令牌:

for (n = 0; n < MAX_TOKENS_PER_LINE; n++)   
{
    token[n] = wcstok(0, DELIMITER); // will save NULL if original line had no delimiters
    if (!token[n]) 
        break;  // will break here since token[n] is NULL

总之,你的逻辑循环是有缺陷的。在您跳过令牌之前,最好确保您实际上读取一个用您认为存在的内容分隔的令牌。如果没有别的建议你测试以确保字符串有一个'"',然后再假设返回的数据是非空的原因是因为存在一个。如上所示,这不是wcstok()返回令牌的唯一方式。


替代方法

有很多选择可以做我认为你想做的事情。这只是其中之一,您可以根据需要调整它。

#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>

int main()
{
    wchar_t data[] = L"\"Test1\", \"Test2\", \"Test3\"";
    std::wistringstream iss(data);

    std::vector<std::wstring> tokens;
    std::wstring token;
    if (std::getline(iss, token, L'"') && std::getline(iss, token, L'"'))
    {
        while (iss)
        {
            // output the real token
            tokens.push_back(token);
            std::wcout << token << std::endl;
            std::getline(iss, token, L'"'); // skip separator to next "
            std::getline(iss, token, L'"'); // read through next "
        }
    }

    // tokens now has your "data" delimited tokens

    return 0;
}