【问题标题】:Program stop working by strcat() with pointer程序通过带有指针的 strcat() 停止工作
【发布时间】:2014-03-02 10:55:28
【问题描述】:

我有一个问题,不要编译这段代码,而是执行这个程序。当我在终端中运行它时,它会打印前 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;
}

【问题讨论】:

  • 你看过strcat的文档吗?
  • 不要使用 devc++ ,它很古老。
  • 您没有为strcat() 的结果保留足够的空间,*cambia 也是错误的。试试……比如char cambia[100] = "ciao ";strcat( cambia, *c );
  • 在此处查看 strcat 的实际操作(对于 C 编程语言):en.cppreference.com/w/c/string/byte/strcat
  • 你会推荐我什么ide?​​span>

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


【解决方案1】:

如果不是绝对必要,则不要在 C++ 中使用 strcat()(例如,在维护遗留代码和尽可能少接触内容时)。

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

无论如何,远离strcat()

【讨论】:

    【解决方案2】:

    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】:

      这一行

       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】:

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

        这些声明:

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

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

        因此,当您调用strcat(*cambia, *c) 时,您正在尝试将"mondo" 写入"ciao " 的末尾。这不仅会写入只读内存,还会写入为字符串指定的内存空间之外——"ciao " 字符串中只有 6 个char 的空间,而您正试图将另外 5 个添加到结束。

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

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

        当然,不使用额外的间接级别会使其更简单:

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

        会达到正确的结果。

        【讨论】:

          【解决方案5】:

          首先你不需要标题

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

          【讨论】:

            猜你喜欢
            • 2014-01-21
            • 1970-01-01
            • 1970-01-01
            • 2011-04-19
            • 2020-09-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-01-15
            相关资源
            最近更新 更多