程序停止使用指针strcat()

时间:2014-03-02 10:55:28

标签: c++ dev-c++ strcat

我有一个问题,不要编译这段代码,而是执行这个程序。当我在终端中运行它打印前2 cout然后程序停止工作,窗口上的屏幕告诉你,我认为问题是strcat。 我使用的是DEVC ++,我有Windows 7专业版。

#include <iostream>
#include <string>
#include <cstdlib>
#include <string.h>

using namespace std;

int main() {

    char* cambia[] = {"ciao "};
    char* c[] = {"mondo"};

    cout << "*c: " << *c << endl;
    cout << "*cambia: " << *cambia << endl;

    strcat( *cambia, *c );
    cout << "*cambia: " << *cambia << endl;
}

5 个答案:

答案 0 :(得分:2)

如果你不是必须的话,你不会在C ++中使用strcat()(例如,在维护遗留代码和触摸尽可能少的东西时)。

使用std::string及其成员函数(如findsubstr)执行简单任务,string streamsBoost libraries进行更复杂的字符串拆分。

无论如何,请远离strcat()

答案 1 :(得分:1)

这里的问题是您正在尝试写入只读字符串存储。

这些声明:

char* cambia[] = {"ciao "};
char* c[] = {"mondo"};

声明两个数组,每个数组都有一个常量字符串成员"ciao ""mondo"位于只读内存中。

因此,当您致电strcat(*cambia, *c)时,您正试图将"mondo"写入"ciao "的末尾。这不仅写入只读内存,而且还写入为字符串给出的内存空间 - char字符串中只有6 "ciao "的空格,并且您正在尝试添加另外5到结束。

解决方案是为每个字符串保留一些空间。有多种方法可以做到这一点。这是一个简单的:

char acambia[20] = "ciao ";     // Space for 20 characters. 
char* cambia[] = { acambia };

对于coruse,不使用额外的间接级别会使其更简单:

char cambia[20] = "ciao ";
char c[] = "mondo";

strcat(cambia, c); 

会达到正确的结果。

答案 2 :(得分:1)

方法strcat()将第二个参数的字符串添加到您提交给第一个参数的缓冲区

首先,缓冲区必须是可写的。在您的示例中,您将字符串文字作为缓冲区传递。当然,字符串文字是只读的。但即使这样,字符串文字也没有可以添加新字符串的空余空间。

不是修复代码,而是让我向您展示一些如何在C ++和C中连接字符串的正确示例。

此示例向您展示如何连接两个C ++字符串:

#include <iostream>
#include <string>

int main(int argc, const char * argv[])
{
    // Create a new C++ string with an initial text.
    std::string result = "First string part ";
    std::cout << "Result: " << result << std::endl;

    // Add some text
    std::string textToAppend = "and the second part";
    result.append(textToAppend);
    std::cout << "Result: " << result << std::endl;

    return 0;
}

以下示例向您展示如何在C中连接两个字符串:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(int argc, const char * argv[])
{
    // The two texts to concat
    const char *firstText = "This is the first text ";
    const char *secondText = "and this is the second one";

    // A buffer which is large enough for the operation.
    const int bufferSize = 1024;
    char buffer[bufferSize];

    // Copy the initial text into the buffer.
    strncpy(buffer, firstText, bufferSize);

    // Add the secon string
    strncat(buffer, secondText, bufferSize-strlen(buffer));

    // Output the string
    printf("Result: %s\n", buffer);

    return 0;
}

我建议,如果可能的话,你应该使用C ++字符串。它们会自动管理内存,从而防止许多与C字符串相关的内存问题。

答案 3 :(得分:1)

这一行

 char* cambia[] = {"ciao "};

在动态创建的内存部分中创建名为cambia的变量,称为“堆栈”。变量是一个没有声明大小的数组,该数组的元素是指向字符的指针。

数组的大小来自初始化程序

{"ciao "}

表示数组只有一个元素,并且该元素使用指向字符串"ciao "的第一个字符的值进行初始化。但是,字符串"ciao "放置在一些完全不同的内存区域中 - 它位于静态块中,由编译器使用程序代码中的值进行初始化。编译器不知道你如何使用这些值,特别是它不知道你会用strcat 扩展它,所以它不会在字符串之后保留任何额外的空格。

因此,当您将"mondo"连接到"ciao "时,会覆盖内存中的某些数据,可能是一些重要的数据......

我建议您为字符串声明 local 变量,并使用显式大小:

char cambia[ 20] = "ciao ";
char c[] = "mondo";

这将使cambia变量足够长以保持19个字符的字符串(加上隐式终止零字节'\ 0',ASCII NUL)并用字母'c','i'初始化其前6个字节,'a','o',空格''和NUL。变量c的隐式大小为6(初始化字符串长度5加1以终止NUL)。

然后你可以安全地连接

strcat( cambia, c);

获取11个字符的字符串“ciao mondo”并将其打印出来

cout <<"cambia: "<<cambia<<endl;

答案 4 :(得分:0)

首先,您不需要标题

#include <string>
#include <cstdlib>

因为没有使用它们的声明。

Aslo标题

#include <string.h>

应该替代

#include <cstring>

在这些陈述中

char* cambia[] = {"ciao "};
char* c[] = {"mondo"};

你定义了两个数组,每个数组都有一个const char *类型的元素。编译器应发出错误或警告,因为这些定义不正确。按以下方式定义数组是正确的

const char* cambia[] = {"ciao "};
const char* c[] = {"mondo"};

这两个语句定义了指向字符串文字的const指针数组。如果尝试更改程序中的字符串文字,则它是未定义的行为。允许程序将字符串文字放在只读内存中。

你说得对,主要问题在于陈述

strcat( *cambia, *c );

函数strcat将一个字符数组附加到另​​一个字符数组的末尾。因此第二个cjaracter数组必须保留足够的内存以容纳附加的字符数组。如果你甚至将数组正确的cambia定义为

char cambia[] = {"ciao "};

它没有足够的内存来存储数组c的字符。 因此,在使用strcat之前,您需要为连接结果数组放置足够的内存。

您可以通过以下方式执行此操作

char s[11];

strcpy( s, *cambia );
strcat( s, c );
cout << "s: " << s << endl;

考虑到您可以使用标准类std::string

的对象而不是字符数组

在这种情况下,将一个字符串附加到另一个字符串非常简单。例如

std::string cambia = "ciao ";
std::string c = "mondo";

cambia += c;

或者

cambia.append( c );