我最近接受了采访,并要求撰写mystrcat(*s1, *s2, *s3)
,其中s1
和s2
是源字符串,连结结果由s3
给出。有人告诉我,不要担心s3
的内存分配,并假设s1
和s2
不是空/无效字符串。所以我写了下面的蹩脚(粗)程序。我被告知s3
出现了问题,或s3
可能出错。你能告诉我这是什么/可能吗?
void mystrcat(char *s1, char *s2, char *s3)
{
if (! (s1 || s2 || s3)) return; // one/more pointers are invalid
// copy string s1 into s3
while(*s1) {
*s3 = *s1;
s1++;
s3++;
}
// concatenate string s2 into s3
while(*s2) {
*s3 = *s2;
s2++;
s3++;
}
*s3 = '\0';
}
你可以告诉我这里有什么问题吗?什么是更专业的做法?
答案 0 :(得分:7)
if (! (s1 || s2 || s3) return; // one/more pointers are invalid
应该是
if ((!s1) || (!s2) || (!s3)) return;
答案 1 :(得分:7)
两个可能的点
首先,您被告知输入和输出指向有效字符串,因此可以说不需要测试有效性。如果需要,你应该吵闹失败。更好的是:
void mystrcat(char *s1, char *s2, char *s3)
{
ASSERT( s1 );
ASSERT( s2 );
ASSERT( s3 );
....
然后,当你可以重用它们时,你基本上写了strcat / strcpy:
void mystrcat(char *s1, char *s2, char *s3)
{
strcpy( s3, s1 );
strcat( s3, s2 );
}
如果我正在采访你以外的其他任何事情,我会特别想到你指出我指定的mystrcat界面设计得非常好,并详细介绍了如何改进它。
答案 2 :(得分:5)
这是我的评论
const char*
,因为您无意修改它们。 在采访中我希望你提出或自我回答的问题
答案 3 :(得分:2)
除了之前的答案,还有一件事可能出错: s3可以指向s1或s2字符串的中间位置。如果这是一个合法的条件,那么你需要更复杂的实现。
答案 4 :(得分:1)
对于您的函数定义可能会有一些批评,但在问题语句的约束下,您的函数将产生正确的答案。这在技术上并不错误。
我的猜测是问题没有得到有效沟通,或者访谈员的批评没有得到有效沟通。也许澄清这些是测试的一部分,嗯?
以下是可能投诉的快速摘要......
此行有逻辑错误...
if(!(s1 || s2 || s3))return;
...因为如果 all 为null,它将返回,但如果任何为null,您可能希望返回。这不会导致失败,因为问题语句说none都不能为空。
优秀的程序员应该在技术正确性方面超越可读性,效率和强大的错误处理,但这些主要是主观的和情境性的。无论如何,忽略你的第一个if语句中的错误,我认为你的函数读得很好并完成了工作。 :)
答案 5 :(得分:1)
无效检查
if(!(s1 || s2 || s3))返回; //一个/多个指针无效
它实际上检查至少一个指针是否不为0,例如至少有一个指针有效。 它应该是
if(!s1 ||!s2 ||!s3)返回;
您无法检查s3是否很大 足够或如果你在外面写作 (但假设是s3很大 对吗? - 但它仍然会 不适合真正的工作)
您无法跳过null
从s1的末尾复制
进入s3。在s3中将0附加到s2之后
所以它最终会结束
“s1stringvalueNULLs2stringvalue
”
(这里的NULL表示值0或null或
在实际代码中为零,这是为了
插图)。任何C方法
期望以null结尾的字符串
只能看到“s1stringvaluepart
”和
将停在null。
这是一个解决方案:
void mystrcat(char *s1, char *s2, char *s3)
{
if (!s1 || !s2 || !s3) return;
while (*s3++ = *s1++);
if (!*(s3-1)) --s3; // reverse over null in s1
while (*s3++ = *s2++);
*s3 = 0;
}
您可以使用以下方法进行测试:
#include <iostream>
using namespace std;
int main()
{
char s1[] = "short";
char s2[] = "longer";
char s3[20];
memset(s3, 0, sizeof(s3));
mystrcat(0,s2,s3);
cout << "2: " << s3 << endl;
memset(s3, 0, sizeof(s3));
mystrcat(s1,0,s3);
cout << "3: " << s3 << endl;
memset(s3, 0, sizeof(s3));
mystrcat(s1,s2,0);
cout << "4: " << s3 << endl;
memset(s3, 0, sizeof(s3));
mystrcat(s1,s2,s3);
cout << "1: " << s3 << endl;
}
答案 6 :(得分:0)
如果我错了,请纠正我。复制s1后,s3的最后一个字符不是'\ 0'吗?那么在某些情况下,s2中的剩余字符永远无法读取?
从我的理解
while(*s3++ = *s1++);
将复制字符,直到达到NULL并且'\ 0'不是NULL,或者它是否被视为?如果我可以假设s1 =“你好”而s2 =“世界!”然后在复制s1之后,s3看起来像:Hello \ 0然后复制“世界!” bit会导致s3看起来像:Hello \ 0 world!\ 0
它有意义吗?我的理解是否正确?