【问题标题】:After calling strcpy, the second char array becomes empty调用strcpy后,第二个char数组为空
【发布时间】:2018-08-20 06:08:58
【问题描述】:

这是我程序中的函数原型:
void FindRepStr(char str[], const char findStr[], const char replaceStr[]);

它在str[] 中找到findStr[] 并将其替换为replaceStr[]

这是我的代码:

void FindRepStr(char str[], const char findStr[], const char replaceStr[])
{
  char *s = nullptr;
  s = strstr(str,findStr); //s points to the first-time appear in str

  char tmp[] ="";

  //length equal
  if(strlen(findStr)==strlen(replaceStr))
  {
    for(int i=0;i<strlen(findStr);i++)
    {
        if(replaceStr[i]=='\0' || s[i] =='\0')
         break;
        else
            s[i] = replaceStr[i];
    }

    cout<<str<<endl;
  }

  else
  {
  //find shorter than replace
    if(strlen(findStr)<strlen(replaceStr))
    {
        //!!!problem here!!!
        strncpy(tmp,s,strlen(s)+1); // store the left part

        for(int i=0;i<=strlen(replaceStr);i++)
        {
            if(replaceStr[i]=='\0') //if end of replace
            {
                s[i]='\0';    //make s(str) end here
                break;
            }
            else
                s[i] = replaceStr[i];   //if not end, give the value
        }

    }

    //finder longer than replace
    else
    {
        //...not finished yet
    }
  }
}

我还没有完成这个,但是在 strncpy 之后,我打印了 s 和 tmp 进行测试,我发现 tmp 被正确复制,但是 s 打印出来是空的:

cout<<"s before strncpy:"<<s<<endl;
strncpy(tmp,s,strlen(s)+1);
cout<<"tmp after strncpy:"<<tmp<<endl;
cout<<"s after strncpy:"<<s<<endl;

输出:

但是在我写的简单测试程序中,我发现它不会被清空:

#include<iostream>
#include<cstring>
using namespace std;

int main()
{
  char a[]="abc";
  char b[]="defgh";

  cout<<"a before:"<<a<<endl;
  cout<<"b before:"<<b<<endl;

  strncpy(a,b,strlen(b)+1);

  cout<<"a after:"<<a<<endl;
  cout<<"b after:"<<b<<endl;

  return 0;
}

输出:

我的程序出了什么问题?

【问题讨论】:

  • 1) 不要将明显是 C 的问题标记为 C++。在 C++ 中,您应该使用std::string,而不是编写所有这些低级操作代码。 2)for(int i=0;i&lt;strlen(findStr);i++)不要这样做。这是非常低效的。在某些情况下,编译器可以拯救你,但在这个特定的情况下,它实际上不能。它必须在循环的每次迭代中调用strlen(时间与字符串的长度呈线性关系)。
  • 你总是可以通过在进入循环之前调用一次strlen(findStr)来优化,在一个临时变量中获取长度并在循环中使用它而不是for(int i=0;i&lt;strlen(findStr);i++)
  • 但有 cout 语句,编译器是 C++,所以它是 C++ C 风格,但它是 C++:meta.stackoverflow.com/questions/360709/…
  • 请提供 MCVE stackoverflow.com/help/mcve 。此外,你如何调用你的函数?因为我没有看到任何检查 s 是否为 NULL。
  • 不要使用strncpy。它不会像你想的那样。

标签: c++ strcpy strncpy


【解决方案1】:
char tmp[] ="";

这声明了一个包含一个字符的本地数组(它只包含'\x0' 终止符)。

将多个字符复制到此数组中会导致未定义的行为:在这种情况下,它会破坏存储局部变量的堆栈帧。

如果你想要一个指针,声明char *tmp。更好的是,只需使用 std::string 即可。

【讨论】:

    【解决方案2】:
    char tmp[] ="";
    

    在这里,您正在创建一个具有足够空间来保存字符串文字的字符数组,包括终止的 nul。由于字符串字面量为空,因此该字符数组仅包含一个字符。

    如果你写的不止这些(而且你确实写了),你就进入了未定义行为的领域。基本上,您将字符串转储到堆栈中的所有随机位置;可以预见的是,这不会有好的结局。

    你需要确保你的字符数组有足够的空间来做你想做的事情。

    此外,您的程序逻辑看起来完全被破坏了。我看不出该代码应该如何执行函数名称所暗示的那样。

    【讨论】:

      猜你喜欢
      • 2013-04-05
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      相关资源
      最近更新 更多