我正在尝试附加两个字符,但由于某种原因,我遇到了分段错误。
我的代码是这样的;
#include <string.h>
char *one = (char*)("one");
char *two = (char*)("two");
strcat(one, two);
而且我似乎遇到了分段错误strcat(one, two)
,这是为什么呢?
我正在尝试附加两个字符,但由于某种原因,我遇到了分段错误。
我的代码是这样的;
#include <string.h>
char *one = (char*)("one");
char *two = (char*)("two");
strcat(one, two);
而且我似乎遇到了分段错误strcat(one, two)
,这是为什么呢?
http://www.cplusplus.com/reference/clibrary/cstring/strcat/
strcat 的第一个参数必须足够大以容纳结果字符串
尝试:
//assuming a,b are char*
char* sum = new char[strlen(a) +strlen(b)+1];
strcpy(sum,a);
strcat(sum,b);
应该有足够的合法内存来保存整个字符串。
char *one = new char[128]; //allocating enough memory!
const char *two = "two"; //"two" is const char*
strcpy(one, "one");
strcat(one, two); //now the variable "one" has enough memory to hold the entire string
顺便说一句,如果你更喜欢在 C++ 中使用std::string
over char*
,这样的事情会更容易处理:
#include<string>
std::string one = "one";
std::string two = "two";
one = one + two; //Concatenate
std::cout << one;
输出:
onetwo
段错误是因为您尝试写入只读内存。strcat 的第一个动作是将“t”从两个的第一个条目复制到“一个”末尾的空值中。所以严格来说,seg 错误并不是由于缺乏存储空间——我们从来没有走到那一步。事实上,这段代码也可能会给你一个段错误:
char* one = "one";
char* two = "";
strcat(one, two);
所有这一切都试图做的是在一个空值上复制一个空值,但在只读内存中。我想优化器可能会在某些平台上阻止这种情况。
奇怪的是,以下(不正确的)代码(可能)不会给你一个段错误,甚至给出“正确”的答案:
char one[] = "one";
char two[] = "two";
strcat(one, two);
printf("%s\n", one);
这成功地将“onetwo”写入我机器上的标准输出。我们得到一个堆栈涂鸦,我们碰巧逃脱了。
另一方面,这确实有段错误:
char* one = "one "; // Plenty of storage, but not writable.
char two[] = "two";
strcat(one,two);
因此解决方案:
const unsigned enoughSpace = 32;
char one[enoughSpace] = "one";
char two[] = "two";
strcat(one,two);
printf("%s\n", one);
这个问题当然是,为了存储即将到来的东西,要制造足够大的空间吗?
因此函数 strncat 或 strcat_s 或更简单的 std::string。
故事的寓意:在 C++ 中,就像 C 一样,你真的需要知道你的内存布局是什么。
有两个原因。
如果您将指针初始化为字符串文字,则该内存是只读的,修改它会导致未定义的行为。在这种情况下,如果您尝试将字符串附加到字符串文字,您将修改这种内存,这将导致问题。
使用 strcat 时,您需要保证在您指定的位置存在用于连接字符串的空间。在这种情况下,您不能保证这一点,因为字符串文字只能保证有足够的空间来保存文字本身。
要解决此问题,您需要显式分配一个足够大的缓冲区来容纳两个字符串的连接,包括空终止符。这是一种方法:
char* buffer = malloc(strlen(one) + strlen(two) + 1);
strcpy(buffer, one);
strcat(buffer, two);
希望这可以帮助!
你从来没有为你的字符串保留一些空间。
#include <string.h>
#include <stdio.h>
int main(void){
char str[20] = "";
strcat(str, "one");
strcat(str, "two");
printf("%s", str);
}
将是一种正确的方法来做到这一点。另一个(更好的方式)是使用std::string
类。
#include <string>
#include <cstdio>
int main(void){
std::string str;
str += "one";
str += "two";
std::printf("%s", str.c_str());
}
您的目标字符串应该足够大以容纳目标字符串和源字符串。所以一个例子是
char one[10] = "one";
char two[4] = "two";
strcat(one,two);
strcat
需要一个“可写”缓冲区作为目标。在您的示例中,它是指向您无法写入的字符串常量(或文字)的指针,因此会导致异常。目标缓冲区可以是堆栈上的缓冲区或动态分配的缓冲区(例如,使用 malloc)。
这不是“空间不够”的问题。
char *a = "str";
看上面的代码,指针a是指向“静态内存”的。字符串“str”存储在PCB中的静态位置,这意味着它不能被覆盖。
所以,下面的代码会更好:
#include <string>
using std::string;
string a = "stra";
string b = "strb";
a += b;