代码之家  ›  专栏  ›  技术社区  ›  inyourmind

通过带指针的strcat()停止程序工作

  •  -2
  • inyourmind  · 技术社区  · 10 年前

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

    #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 回复  |  直到 10 年前
        1
  •  2
  •   Christian Hackl    10 年前

    你不使用 strcat() 在C++中,如果您不一定需要(例如,在维护遗留代码和尽可能少接触内容时)。

    使用 std::string 其成员功能如下 find substr 对于简单的任务, string streams Boost libraries 用于更复杂的字符串拆分。

    无论如何,远离 字符串() .

        2
  •  1
  •   Flovdis    10 年前

    方法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
  •   CiaPan    10 年前

    这条线

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

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

    数组的大小来自初始值设定项

    {"ciao "}
    

    这意味着数组将只有一个元素,该元素用指向字符串第一个字符的值初始化 "ciao " 。但是,字符串 “ciao” 被放置在内存的某个完全不同的区域中-它位于静态块中,由编译器使用程序代码中的值进行初始化。编译器不知道如何使用这些值,特别是它不知道 延伸 它与 strcat ,因此它不会在字符串后保留任何额外的空间。

    因此,当您连接 "mondo" “ciao” ,您覆盖 一些 内存中的数据,可能是一些重要数据。。。

    我建议你申报 地方的 字符串的变量,具有显式大小:

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

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

    然后可以安全地连接

    strcat( cambia, c);
    

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

    cout <<"cambia: "<<cambia<<endl;
    
        4
  •  1
  •   Vlad from Moscow    10 年前

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

    这些声明:

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

    声明两个数组,每个数组 常量字符串成员 这个 "ciao " "mondo" 位于只读存储器中。

    所以当你打电话的时候 strcat(*cambia, *c) ,你正在尝试写 “蒙多” 到…的末尾 “ciao” 。这不仅写入只读内存,而且还写入字符串指定的内存空间之外的内容-只有6个空间 char “ciao” 字符串,并且您正在尝试在该字符串的末尾添加另一个5。

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

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

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

    char cambia[20] = "ciao ";
    char c[] = "mondo";
    
    strcat(cambia, c); 
    

    将获得正确的结果。

        5
  •  0
  •   Vlad from Moscow    10 年前

    首先,您不需要页眉

    #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"};
    

    这两个语句定义了字符串文本的常量指针数组。如果试图更改程序中的字符串文字,这是未定义的行为。允许程序在 只读存储器 .

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

    strcat( *cambia, *c );
    

    作用 strcat 将一个字符数组附加到另一个字符阵列的末尾。因此,第二个cjaracter数组必须保留足够的内存来容纳附加的字符数组。如果您将数组cambia正确定义为

    char cambia[] = {"ciao "};
    

    它没有足够的内存来存储数组c的字符。 所以在使用之前 字符串连接函数 您需要在放置连接结果数组的位置保留足够的内存。

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

    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 );