转换为char * c ++时,字符串会被切断

时间:2013-03-24 11:34:16

标签: c++ string char type-conversion tokenize

正如标题所示,我在将字符串转换为字符数组时遇到了一些麻烦。

首先让我明白为什么我需要这样做,因为如果我的做法错了,我会很乐意采取不同的做法。 (虽然我更喜欢答案可以直接关注手头的问题)

我有一个包含多行的文件。每行的格式为

  

b 12 3 4

     

d 4 1 5.71

     

...

我要做的是读取每一行(使用getLine并将其保存在字符串变量上)并将它们拆分为空格,以便将每个字母/数字分开。

为了实现这一点,我采用了strtok方法,该方法将char *作为参数

这种转换是出错的地方。

我采取了几种方法,但总是以同样的方式结束:

尝试#1 - .data()

const char *converted = new char[(line.size()+1)];
//The sentence is complete in this cout!
cout << line << " -printed string\n";
converted = line.data();
converted[line.size()] = '\0';
//sentence no longer complete!
cout << converted << " -printed char array\n";

尝试#2 .c_str()

char *converted;
//The sentence is complete in this cout!
cout << line << " -printed string\n";
converted = (char*)line.c_str();
//sentence no longer complete!
cout << converted << " -printed char array\n";

尝试#3 copy()

char *converted = new char[(line.size()+1)];
//The sentence is complete in this cout!
cout << line << " -printed string\n";
copy(line.begin(), line.end(), converted);
//sentence no longer complete!
cout << converted << " -printed char array\n";

我可能在前面的代码中有一些语法错误。因为我尝试了不同的方法,因此我擦除了代码,因此我从内存中执行此操作。关键是,使用.data(),copy()和.c_str()编译它们,并且都给出了相同的输出:

  

b 12 3 4 -printed string

     

b -printed char array

现在我完成了我的作业,显然这不是一个完整的第一个。我想我已经读过一些可能发生的事情,就是所有这些方法都将空格“”解释为“\ 0”,所以它在读完“b”后就会停止。修复它的方法之一是使用boost库。

不幸的是,这不是我的选择。我正在研究一种不能依赖外部库的可交付成果。一些帮助将非常感激。

提前致谢。

修改

代码:

(...)
if (fh.is_open()){
    while (fh.good()){
        getline(fh,line);
        char *converted = new char[(line.size()+1)];
        cout << line << " -printed string\n";
        strcpy(converted, line.c_str());

        cout << converted << " -printed char array\n";
(...)

3 个答案:

答案 0 :(得分:2)

#1和#2中的错误,你必须复制字符,你所做的只是复制指针。

替换

converted = line.data();
converted[line.size()] = '\0';

strcpy(converted, line.c_str());

尝试#3更好但忘记添加空终止符。

也许你应该研究使用std :: string进行标记化的方法,然后你就不会把这一切搞得一团糟。

答案 1 :(得分:1)

现在指出了代码的问题

如果要将字符串(行)拆分为空格,则可能需要使用格式化输入而不是标记化。类似的东西(这没有经过测试)

#include <sstream>
#include <string>
while (std::getline(infile, line))
{
    std::istringstream iss(line);
    string token;
    while(iss >> token) { 

       // Do your thing on token

    }
}

根据您的需要进行修改。

答案 2 :(得分:0)

尝试#1中的问题例如:

  • 内存泄漏:首先将指针设置为新分配的内存块,然后将指针重置为line.data()

  • 未定义的行为:您不能修改std::string::data()std::string::c_str()指向的指针所指向的内容。它可能是字符串对象保存的实际缓冲区的内部副本。

为了将字符串拆分为由空格分隔的部分,您可以尝试以下方法:

split(const std::string &line, char &letter, std::vector<double> &numbers) {
    typedef std::string::size_t size_t;
    size_t n = line.find(' ');
    if (n == std::string::npos || n > 1) {
        // there aren't any spaces or the first part contains
        // more than one letter!
        // bad case? throw something or return an error code
    }
    letter = line[0];
    size_t n2 = line.find(' ', n);
    while (n2 != std::string::npos) {
        numbers.push_back(str2double(line.substr(n, n2 - n)));
        n = n2;
        n2 = line.find(' ', n);
    }
}

我没有测试代码。可能是您必须将n + 1写入find的电话或类似的内容。你必须自己编写str2double函数。