Microsoft面试问题中此功能有哪些错误?

use*_*679 25 c string

我在MS写的访谈中被问到这个问题:

在下面的程序中查找错误,该错误应该返回一个\n附加到其上的新字符串.

char* AddnewlinetoString(char *s)
{
  char buffer[1024];
  strcpy(buffer,s);
  buffer[strlen(s)-1] = '\n';
  return buffer;
}
Run Code Online (Sandbox Code Playgroud)

我试图对自己进行编码,并且能够通过使缓冲区变量全局和具有来实现它buffer[strlen(s)] = '\n'.但不知道还有很多其他的错误.

cod*_*ict 55

我可以看到一些:

未检查输入字符串的长度.

怎么样strlen(s) > 1023?您最多可以1023在缓冲区中输入一串长度.

覆盖最后一个字符 \n

你用换行符覆盖了最后一个字符.你\n应该去的地方\0曾经是,你需要添加一个新的\0\n

变量缓冲区是函数本地的,您将返回其地址.

缓冲区的内存在堆栈上分配,一旦函数返回,该内存就被释放.

我会做:

char* AddnewlinetoString(char *s) {

  size_t buffLen = strlen(s) + 2; // +1 for '\n' +1 for '\0'
  char *buffer = malloc(buffLen); 
  if(!buffer) {
   fprintf(stderr,"Error allocting\n");
   exit(1);
  }
  strcpy(buffer,s);
  buffer[buffLen-2] = '\n';
  buffer[buffLen-1] = 0;
  return buffer;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果使用的话,这将泄漏内存:`str = AddNewlineToString(str);` (6认同)
  • 有趣的是,`\ 0`可能仍然在那里(如果第一个错误没有绊倒它).再看一下,`\ 0`是否被覆盖? (4认同)
  • @ sje397:这不是函数的问题,前提是它已正确记录调用者拥有返回的缓冲区,并负责正确释放它.唯一的选择是使用全局缓冲区,其中存在更严重的问题.*编辑:当然,鉴于你坚持使用类似C的界面. (4认同)
  • 2.`strlen`在长度上不包括终结符.所以最多,代码只是用换行符替换字符串的最后一个字符,但是如果它已经存在则nul将保留. (3认同)
  • @TygerKrash:堆栈保存当前函数的本地值.一旦函数返回,你的指针指向垃圾,即你不知道那里有什么(例如,下一个函数的局部变量可以覆盖指针指向的区域). (3认同)
  • @Dennis Zickefoose:缺乏文档(或评论)可能被视为一个问题.另一种选择是释放输入指针(是的,不好).无论如何,我的观点是,从写签名的那一刻起就注定了;) (2认同)
  • 如果传递null作为参数,则会崩溃. (2认同)

Tom*_*zyk 8

  1. strcpy没有限制,更好的使用strncpy.
  2. 您正在复制到静态缓冲区并返回指针.

  • 当然那不是静态缓冲区? (4认同)
  • 应该确保缓冲区的大小合适,而不是`strncpy`.如果您将输入截断,而不是添加换行符,它究竟有什么好处呢?这应该解决这两个问题. (4认同)
  • 3.缓冲区溢出 (3认同)

fre*_*low 8

这是一个没有错误的C++版本:

std::string AddnewlinetoString(std::string const& s)
{
    return s + "\n";
}
Run Code Online (Sandbox Code Playgroud)

以下是我可能会在C++ 0x中编写的内容:

std::string AddnewlinetoString(std::string s)
{
    return std::move(s += "\n");
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然没有回答这个问题:) (4认同)
  • 是的,但是......我不认为这些练习的目的是提出一个更好的版本*本身*,但要理解错误的复杂性.考虑一下调试平庸同事工作的测试,而不是自己编写新代码的测试. (4认同)

mar*_*ich 6

我还要补充说,方法的名称应该坚持模式,每个单词应该以大写字母开头:

char* AddNewlineToString(char *s)
{
}
Run Code Online (Sandbox Code Playgroud)

PS.感谢Konrad,我已根据您的建议更改了方法名称

  • 但是"换行符"(如"换行符",而不是"新行文本")是**一个**单词.名称应为`AddNewlineToString`. (4认同)