-1

我有一个函数string_to_char(),它试图给我一个字符串的形式,我可以将它传递到我正在使用的库中,它想要char *(但我认为可以与. 一起使用const char *,所以我一直在尝试两者)。

我为测试我的实现而编写的代码string_to_char()如下:

#include <iostream>

const std::string endl = "\n";

char * string_to_char(std::string str)
{
    return (char*) str.c_str();
}

int main()
{
    std::string test1 = "Some test strin";
    std::string test2 = "Some test string";

    char * result1 = string_to_char(test1);
    char * result2 = string_to_char(test2);

    std::cout << "part1" << endl;
    std::cout << result1 << endl;
    std::cout << string_to_char(test1) << endl;

    std::cout << "part2" << endl;
    std::cout << result2 << endl;
    std::cout << string_to_char(test2) << endl;

    std::cout << "done" << endl;

    return 0;
}

这是我得到的输出:

part1
Some test strin
Some test strin
part2

Some test string
done

因此,出于某种原因,string_to_char()仅适用于 15 个字符或更短的字符串,并且从函数直接输出到 std::cout,但似乎无法将其存储到 16 个字符或更长的变量中。

我对 C++ 比较陌生,所以下面的一些代码对于更有经验的程序员来说可能有点奇怪,但这是我尝试过的代码return (char*) str.c_str();

#include <vector>
#include <string.h>

char * string_to_char(std::string str)
{
    return (char*) str.c_str();
    
    return const_cast<char*>(str.c_str());
    
    std::vector<char> vec(str.begin(), str.end());
    char * chr;
    vec.push_back('\0');
    chr = (char*) &vec[0];
    //chr = & (*vec.begin());
    return chr; //all outputs from both are empty with this both versions of chr
    
    return &str[0]; //this makes the output from the 15 character string also be empty when put in a
    //variable, but the function going directly to std::cout is fine

    return strcpy((char *) malloc(str.length() + 1), str.c_str()); //this one works with everything, but 
    //it looks like it leaks memory without further changes

    std::vector<char> copied(str.c_str(), str.c_str() + str.size() + 1);
    return copied.data(); //returns "random" characters/undefined behaviour for both outputs in test1 and is empty for both
    //outputs in test2
}

改为使用const并更改char * result1 = string_to_char(test1);const char * result1 = string_to_char(test1);(与 一样result2),以查看这是否适用于这些其他解决方案:

#include <vector>
#include <string.h>

const char * string_to_char(std::string str)
{
    return (char*) str.c_str();

    return str.c_str();

    return (const char*) str.c_str();

    return str.data();

    return const_cast<char*>(str.c_str()); 

    std::vector<char> vec(str.begin(), str.end());
    char * chr;
    vec.push_back('\0');
    chr = (char*) &vec[0];
    //chr = & (*vec.begin());
    return chr; //completely breaks both

    return &str[0]; //both appear empty when given to a variable, but works fine when taken straight to std::cout
 
    return strcpy((char *) malloc(str.length() + 1), str.c_str()); //memory leak, as when not using const

    std::vector<char> copied(str.c_str(), str.c_str() + str.size() + 1);
    return copied.data(); //same as when not using const
}

我从以下方面得到了很多给定的方法:

std::string 到 char*

string.c_str() 是常量吗?

如何将 std::string 转换为 const char* 或 char*?

在 C++ 中从 std::string 转换为 char *

https://www.cplusplus.com/reference/https://en.cppreference.com/w/上阅读一些关于字符串和向量的主题

4

3 回答 3

5

从返回的指针c_str()仅在字符串处于活动状态时才有效。传递参考时会得到预期的输出:

auto string_to_char(std::string& str)
{
    return str.c_str();
}

因为现在返回的指针进入了调用者字符串的缓冲区。在您的代码中,调用者获取指向函数本地字符串的指针(因为您传递了一个副本)。

不过,您可以直接调用c_str(). 这也减轻了在字符串到达​​一定范围后保持指针的问题。

于 2021-03-29T16:45:16.927 回答
2

你想多了。不需要两个自己写这个函数。std::string::data已经存在并返回一个指向字符串的以 null 结尾的内部缓冲区的指针。假设您使用的是 C++17 或更高版本,const char*如果std::string对象是const- 限定的(即只读),则此指针将是,否则将是可修改的char*.

std::string test1 = "string";
const std::string test2 = "const string";

char* result1 = test1.data();
const char* result2 = test2.data();

只要std::string它来自的对象是活动的并且没有被修改(修改单个元素除外),这个指针就有效。

另请注意,强制转换指针和抛弃const-ness 是一种在不知情的情况下导致未定义行为的非常简单的方法。一般来说,您应该避免使用 C 风格的强制转换(例如(char*)str.c_str()),因为它们非常不安全。有关更多信息,请参阅有关正确使用 C++ 强制转换的 Q/A

现场演示

文档

于 2021-03-29T17:07:26.070 回答
1

string_to_char()正在str按值获取其参数,因此制作了调用者输入字符串的副本。当函数退出时,复制的std::string将被销毁。因此,返回的char*指针将悬空,指向已释放的内存,并且任何使用该指针访问数据的行为都是未定义的行为

而是通过str引用传入参数:

char* string_to_char(std::string &str)
{
    return const_cast<char*>(str.c_str());
}

或者,在 C++17 及更高版本中,您可以使用它来代替:

char* string_to_char(std::string &str)
{
    return str.data();
}

这就引出了一个问题,即为什么你需要string_to_char()并且不data()直接使用,除非你没有使用现代版本的 C++。

于 2021-03-29T16:43:31.737 回答