字符串在转换为char* c++时被切碎

String gets chopped when converted to char* c++

本文关键字:c++ 转换 char 字符串      更新时间:2023-10-16

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

首先让我澄清我需要这样做的原因,因为如果我的方法是错误的,我很乐意采取不同的方法。(虽然我更希望答案能直接集中在手头的问题上)

我有一个有几行的文件。每行的格式为

b 12 3 4

d 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 stringn";
converted = line.data();
converted[line.size()] = '';
//sentence no longer complete!
cout << converted << " -printed char arrayn";

尝试#2 .c_str()

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

try #3 copy()

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

前面的代码可能有一些语法错误。我从记忆中这样做,因为我在尝试不同的方法时擦除了代码。关键是,使用。data(), copy()和。c_str()它们都被编译了,并且都给出了相同的输出:

b 12 3 4 -print string

b -print字符数组

现在我已经做了我的功课,显然这不是一个完整的第一次。我想我在什么地方读到过,可能发生的事情是所有这些方法都在解释空白空间";作为"",所以它在刚刚阅读"b"后停止。解决这个问题的方法之一是使用boost库。

不幸的是,这不是我的选择。我正在开发一个不能依赖外部库的可交付产品。如果你能帮忙,我将不胜感激。

提前感谢。

编辑

代码:

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

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

代替

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

strcpy(converted, line.c_str());

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

也许您应该研究一下与std::string一起工作的标记方法,这样您就不会有这些麻烦了。

既然你的代码的问题被指出了

如果你要用空格分隔字符串(行),那么你可能需要使用格式化的输入而不是标记化。类似于(未测试)

#include <sstream>
#include <string>
while (std::getline(infile, line))
{
    std::istringstream iss(line);
    string token;
    while(iss >> token) { 
       // Do your thing on token
    }
}

根据你的需要修改它。

尝试#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函数