简体   繁体   English

如何将类型从const char *转换为char *

[英]How convert type from const char * to char *

I'm trying create simple application in C++. 我正在尝试用C ++创建简单的应用程序。 This application has to read from file and displays data. 此应用程序必须从文件中读取并显示数据。 I've written function: 我写的功能:

std::vector <AndroidApplication> AndroidApplication::getAllApp(){
    std::vector<AndroidApplication> allApp;
    std::fstream f;

    f.open("freeApps.txt");
    std::string line;
    if(f.is_open()){
        while(getline(f, line)) {
            std::string myLine = "";
            char * line2 = line.c_str();
            myLine = strtok(line2,"\t");

            AndroidApplication * tmpApp = new AndroidApplication(myLine[1], myLine[2], myLine[4]);
            tmpApp->Developer = myLine[0];
            tmpApp->Pop = myLine[3];
            tmpApp->Type = myLine[5];
            allApp->pushBack(tmpApp);
        }
    }
    return allApp;
}

It throws me an error in line: 它引发了我的错误:

myLine = strtok(line2,"\t");

An error: 一个错误:

cannot convert from 'const char *' to 'char *' 无法从'const char *'转换为'char *'

Could you tell me how can I deal with it? 你能告诉我怎么处理它?

Don't use strtok . 不要使用strtok std::string has its own functions for string-scanning, eg, find . std::string有自己的字符串扫描功能,例如find

To use strtok, you'll need a writeable copy of the string. 要使用strtok,您需要一个可写的字符串副本。 c_str() returns a read-only pointer. c_str()返回一个只读指针。

You can't just "convert it" and forget about it. 你不能只是“转换它”而忘记它。 The pointer you get from .c_str() is to a read-only buffer . .c_str()获得的指针是一个只读缓冲区 You need to copy it into a new buffer to work with: ideally, by avoiding using antiquated functions like strtok in the first place. 你需要将它复制到一个新的缓冲区来处理:理想情况下,首先要避免使用像strtok这样的过时函数。

(I'm not quite sure what you're doing with that tokenisation, actually; you're just indexing into characters in the once-tokenised string, not indexing tokens.) (实际上,我不太确定你在使用这种标记化做什么;你只是在一次标记化的字符串中索引字符,而不是索引标记。)

You're also confusing dynamic and automatic storage. 您还混淆了动态和自动存储。

std::vector<AndroidApplication> AndroidApplication::getAllApp()
{

    std::vector<AndroidApplication> allApp;

    // Your use of fstreams can be simplified
    std::fstream f("freeApps.txt");

    if (!f.is_open())
       return allApp;

    std::string line;
    while (getline(f, line)) {

        // This is how you tokenise a string in C++
        std::istringstream split(line);
        std::vector<std::string> tokens;
        for (std::string each;
             std::getline(split, each, '\t');
             tokens.push_back(each));

        // No need for dynamic allocation here,
        // and I'm assuming you wanted tokens ("words"), not characters.
        AndroidApplication tmpApp(tokens[1], tokens[2], tokens[4]);
        tmpApp.Developer = tokens[0];
        tmpApp.Pop = tokens[3];
        tmpApp.Type = tokens[5];

        // The vector contains objects, not pointers
        allApp.push_back(tmpApp);
    }

    return allApp;
}

I suspect the error is actually on the previous line, 我怀疑错误实际上是在前一行,

char * line2 = line.c_str();

This is because c_str() gives a read-only pointer to the string contents. 这是因为c_str()给出了一个指向字符串内容的只读指针。 There is no standard way to get a modifiable C-style string from a C++ string. 没有标准的方法可以从C ++字符串中获取可修改的C风格字符串。

The easiest option to read space-separated words from a string (assuming that's what you're tying to do) is to use a string stream: 从字符串中读取空格分隔单词的最简单选项(假设您正在做的事情)是使用字符串流:

std::vector<std::string> words;
std::istringstream stream(line);
std::copy(std::istream_iterator<std::string>(stream), 
          std::istream_iterator<std::string>(),
          back_inserter(words));

If you really want to use strtok , then you'll need a writable copy of the string, with a C-style terminator; 如果你真的想使用strtok ,那么你需要一个字符串的可写副本,带有C风格的终结符; one way to do this is to copy it into a vector: 一种方法是将其复制到一个向量中:

std::vector<char> writable(line.c_str(), line.c_str() + line.length() + 1);
std::vector<char *> words;
while (char * word = strtok(words.empty() ? &writable[0] : NULL, " ")) {
    words.push_back(word);
}

Bear in mind that strtok is quite difficult to use correctly; 请记住, strtok很难正确使用; you need to call it once for each token, not once to create an array of tokens, and make sure nothing else (such as another thread) calls it until you've finished with the string. 你需要为每个令牌调用一次,而不是一次创建一个令牌数组,并确保在你完成字符串之前没有其他任何东西(比如另一个线程)调用它。 I'm not sure that my code is entirely correct; 我不确定我的代码是完全正确的; I haven't tried to use this particular form of evil in a long time. 我很久没有尝试过使用这种特殊形式的邪恶了。

Since you asked for it: 既然你要求它:

Theoretically you could use const_cast<char*>(line.c_str()) to get a char* . 从理论上讲,您可以使用const_cast<char*>(line.c_str())来获取char* However giving the result of this to strtok (which modifies its parameter) is IIRC not valid c++ (you may cast away constness, but you may not modify a const object). 但是将结果赋予strtok (修改其参数)是IIRC无效的c ++(你可以抛弃constness,但你可能不会修改const对象)。 So it might work for your specific platform/compiler or not (and even if it works it might break anytime). 所以它可能适用于您的特定平台/编译器(即使它工作,它可能会随时中断)。

The other way is to create a copy, which is filled with the contents of the string (and modifyable): 另一种方法是创建一个副本,其中填充了字符串的内容(和可修改的):

std::vector<char> tmp_str(line.begin(), line.end());
myLine = strtok(&tmp_str[0],"\t");

Of course as the other answers tell you in great detail, you really should avoid using functions like strtok in c++ in favour of functionality working directly on std::string (at least unless you have a firm grasp on c++, high performance requirements and know that using the c-api function is faster in your specific case (through profiling)). 当然,正如其他答案非常详细地告诉你的那样,你真的应该避免在c ++中使用像strtok这样的函数来支持直接在std::string上工作的函数(至少除非你已经牢牢掌握了c ++,高性能要求并且知道使用c-api函数在特定情况下更快(通过分析))。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM