【问题标题】:How to convert a `const char *` to simply `char *`?如何将`const char *`转换为简单的`char *`?
【发布时间】:2011-08-26 20:15:35
【问题描述】:

我正在使用 pdCurses 库,我的目标是只在我的 C++ 控制台游戏中真正使用字符串,但 curses mvinstr() 函数或任何插入函数需要非常量 char * 作为参数。

  • 我最初对这个问题的解决方案是简单地输入string.c_str(),但返回的const char *显然不适用于该函数。
  • 接下来我输入(char *)string.c_str(),但这只会导致未处理的异常。
  • 最后我只是尝试了char *test = string.c_str(),但这与const 也不兼容。

我该怎么做才能解决这个问题?

K 我刚刚尝试了 const_cast() ,但仍然抛出异常并中断.... 我不知道为什么 PDcurses 只接受非常量字符指针.... =(

好吧,当我使用此代码时,制作 char* 缓冲区不起作用(time_s 是刺痛):

size_t length; 
    char buffer[12]; 
    length=time_s.copy(buffer,5,0); 
    buffer[length]='\0';
mvinstr(time_loc_y, time_loc_x, buffer);

我什至在 mvinstr() 之前停止并检查缓冲区的内容是“00 / 0” 正是我想要的。

但我得到一个指向“xutility”的访问冲突点......

【问题讨论】:

  • 考虑到通常不建议删除 constness,这与设计缺陷有关。
  • 违规访问什么代码和在哪里?
  • 你有没有想过这个问题?

标签: c++ constants


【解决方案1】:

mvinstr(x,y,str) 和其他“从窗口中的当前或指定位置获取字符(或宽字符),并将它们作为字符串返回到str(或wstr)中。”

该函数实际上会修改字符串,因此您不能安全地将const 强制转换掉,尤其是因为c_str 指定您不应修改返回的字符串。

你需要一些类似的东西:

const MAX = 100;
char buf[MAX];
mvinnstr(x, y, buf, MAX);
...error checking...
string s = buf;

请注意,我避免使用mvinstr 而是使用mvinnstr 以避免缓冲区溢出的可能性。

【讨论】:

  • @Griffin,听起来像是缓冲区溢出,我特别展示了如何避免这种情况。注意:目前尚不清楚您是否应该将 MAX 或 MAX-1 传递给mvinnstr,但这可以通过测试确定。
【解决方案2】:

怎么样

char* buffer = &str[0];
int fetched_len = mvinnstr(time_loc_y, time_loc_x, buffer, str.size());
str.resize(fetched_len);

不过,一般来说,您应该创建一个可写缓冲区,而不是从拥有它的指针中删除 const。例如

vector<char> charvec(MAX_LENGTH);
str = string(&charvec[0], mvinnstr(time_loc_y, time_loc_x, &charvec[0], charvec.size());

【讨论】:

  • C++03 试图保证你的第一个 sn-p 可以工作(但失败了),但它保证在 C++0x 中工作。在这两种情况下,请确保字符串中有足够的保留内存。
  • @GMan:我试图避免查找特定的 API,以便提供更通用的答案,但我刚刚对其进行了编辑以防止溢出。
  • 嗯...刚刚意识到这与我的答案相似,但添加了resize 呼叫...您可能想更明确地显示您对&amp;str[0] 呼叫所做的事情吗? OP不会迷路。 +1。
  • @Billy:这就是我在早期版本中的内容,......我会看看我能做些什么来强调这一点。
【解决方案3】:

小心 - 如果使用 was-const 数据的代码试图修改它,任何事情都可能发生。

简而言之:

const std::string str = "...";
char *caution = const_cast<char *>(str.c_str());

但是,鉴于您遇到未处理的异常,您可能需要在调用 mvinstr() 之前制作常量字符串的可修改副本。也许:

const std::string str = "...";
char *caution = new char[str.length()+1];
str.copy(caution, str.length()+1);
...call to mvinstr()...
delete[] caution;

【讨论】:

  • 这不是std::stringstd::string 的内容是可变的。
  • const_cast> 的行为是否与 '(char)'aConst_char_pointer 不同?
  • @Griffin:使用反引号保护代码 sn-ps 免受将星号解释为格式化代码。
  • @Griffin:是的。 C 风格的转换不能删除 const —— 只有 const_cast 可以做到这一点。 (无论如何,您都应该使用 C++ 样式转换)
  • @Billy:你可以仔细检查一下,因为我很确定 C 风格的演员表确实可以删除 cv-qualfiers
【解决方案4】:

由于mvinstr 实际上将数据存储到char* 指向的数组中,因此您不能在那里使用string。您需要分配一个字符数组,将其传递给mvinstr,然后根据需要将字符传递给string

如果您使用的函数可以用 const char * 声明(即它实际上并没有修改数组),那么您可以使用 const_cast&lt;&gt; 删除 const

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

但这不是你在这里做的。 const_cast 如果您尝试过它可能会起作用,但这只是偶然,而不是因为它应该起作用,并且新的编译器或库版本可能随时破坏它。

【讨论】:

  • @Ben:不,我的意思是一个数组。我们在这里与 C 代码交互。
  • 是的,向量很容易给你一个C代码可以理解的指针,并且自动释放内存。
【解决方案5】:

尝试以下类似操作,然后在需要char* 的任何地方使用buffer。正如 Ben 提到的,您需要非常小心地保持缓冲区大于字符串加上空终止符。

const int BUFFER_SIZE = 255;

string str ("Your string");
char buffer[BUFFER_SIZE];
if (str.length() < BUFFER_SIZE)
{
    size_t copy_length;
    copy_length=str.copy(buffer,str.length(),0);
    buffer[copy_length]='\0';
}

【讨论】:

  • 这只是要求成为意外的缓冲区溢出。
  • 尝试使用mvinnstr(time_loc_y, time_loc_x, buffer, size);,其中size 不大于缓冲区的大小 - 1. 12 个字符的缓冲区可能太小了。
【解决方案6】:

可以使用const_cast 删除 const,有时对于使用用 C 编写且不使用 const 的遗留接口是必要的。在这种情况下,您可以这样做:

char* ptr = const_cast<char*> (str.c_str());

但是,来自c_str() 上的 cplusplus 参考页:

返回的数组指向一个内部位置,该位置具有该字符序列所需的存储空间以及它的终止空字符,但该数组中的值不应在程序中修改,并且只允许保持不变,直到下一次调用字符串对象的非常量成员函数。

这意味着您有责任确保ptr用于修改字符串,并且您必须适当地处理ptr 的生命周期。即,在str 超出范围之后,或者在您对str 调用任何非常量方法之后,您不能继续使用ptr。如果这样做,您将进入未定义行为,并且可能会崩溃。

如果您正在寻找一种与采用char* 的旧界面进行交互的安全方式,您可以制作自己的可写副本:

char* ptr = new char[ str.size() + 1 ];
strcpy(ptr, str.c_str());
ptr[str.size()] = '\0';
// ... use ptr as much as you want...
delete [] ptr;

【讨论】:

  • new []delete []?只需使用std::vector
  • @Ben,vector&lt;char&gt; 应该如何帮助使用期望 char* 作为输入参数的旧接口? boost::scoped_array 在这里会更好。
  • vector&lt;char&gt; vec = FillMeWithData(); legacy_c_function(&amp;vec[0]); 不是这样说boost::scoped_array 也不是一个选项。只要周围没有原始指针。
  • @Dennis:虽然,数据来自遗留的 c 函数。所以vector&lt;char&gt; vec(str.size() + 1); legacy_c_function(&amp;vec[0]);
【解决方案7】:

if (string.empty()) foo(const_cast&lt;char*&gt;(string.c_str());

删除 const 的更好但仍然是邪恶的方法是 const_cast(const_string); (最好通过 grep/search 找到)

你遇到过女巫异常吗? 您只是阅读 char* 还是更改值?如果你改变了,你应该重新设计你的代码。

const char* test = string.c_str(); 不创建字符串的深拷贝,只创建一个指向 string.data() 内部数据表示的指针。

=>(建议)找一本 C++ 书籍,您可以在其中更深入地了解 C++。或者类似 C++ 的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    相关资源
    最近更新 更多