简体   繁体   English

我的串联函数mystrcat(char *,char *,char *)有什么问题?

[英]What is wrong in my concatenation function mystrcat(char*, char*, char*)?

I was interviewed recently and asked to write mystrcat(*s1, *s2, *s3) where s1 and s2 are source string and the concatenated results are given by s3 . 我最近接受了采访并要求编写mystrcat(*s1, *s2, *s3) ,其中s1s2是源字符串,连接结果由s3给出。 I was told, don't worry about memory allocation of s3 and assume s1 and s2 are not null / invalid strings. 我被告知,不要担心s3内存分配,并假设s1s2不是空/无效字符串。 So I wrote the following lame (crude) program. 所以我写了下面的蹩脚(粗)程序。 I was told there is something wrong with s3 or something can go wrong with s3 . 有人告诉我有什么毛病s3或东西可以去错了s3 Could you please tell what it is/ could that be? 你能告诉它它是什么/可能是什么?

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';
}

Could you please tell me what is wrong here? 你能告诉我这里有什么问题吗? What would be more professional way of doing it? 做什么会更专业呢?

if (! (s1 || s2 || s3) return; // one/more pointers are invalid

应该

if ((!s1) || (!s2) || (!s3)) return;

Two possible points 两个可能的点

First, you were told that the inputs and the otput pointed to valid strings, so the test for validity is arguably not needed. 首先,您被告知输入和输出指向有效字符串,因此可以说不需要测试有效性。 And if it were needed you should have failed noisily. 如果需要,你应该吵闹失败。 Better would have been: 更好的是:

 void mystrcat(char *s1, char *s2, char *s3)
    {
        ASSERT( s1 );
        ASSERT( s2 );
        ASSERT( s3 );
        ....

Then you basically wrote strcat/strcpy when you could have reused them: 然后你基本上写了strcat / strcpy,你可以重用它们:

void mystrcat(char *s1, char *s2, char *s3)
{
    strcpy( s3, s1 );
    strcat( s3, s2 );
}

And if I were interviewing you for anything other than a junior post, I would have eexpected you to point out to me that the mystrcat interface as specified is very pporly designed and given details of how you would improve it. 如果我正在采访你以外的其他任何事情,我会特别指出你指出我指定的mystrcat界面是非常精心设计的,并提供了如何改进它的细节。

Here would be my comments 这是我的评论

  • Both s1 and s2 should be typed to const char* since you have no intention of modifying them. s1和s2都应该输入const char*因为你无意修改它们。
  • You did not verify s3 had enough allocated space to contain s1 and s2's combined length 你没有验证s3有足够的分配空间来包含s1和s2的组合长度
  • You are failing silently when the user passed in bad data (NULL values). 当用户传入错误数据(NULL值)时,您将无声地失败。 This is not good because there is no way for a caller to differentiate between a successful and a failing call 这并不好,因为呼叫者无法区分成功和失败的呼叫
  • Your method of verifying s1,s2 and s3 are not null is incorrect (Igor has it right) 验证s1,s2和s3的方法不为null是不正确的(Igor没错)

Questions I would have liked you to ask or self answered during the interview 我希望你在面试中问我或自己回答的问题

  • How should I express failure to copy the string? 我应该如何表达未能复制字符串?
  • Do you want an exact clone of strcat or one that is more modern and does better argument validation? 你想要一个精确的strcat克隆还是更现代的一个并且做更好的参数验证?
  • Can I use other standard str functions to complete the answer? 我可以使用其他标准str函数来完成答案吗?

In addition to the previous answers, one more thing that could go wrong: s3 could point to the middle of s1 or s2 strings. 除了之前的答案,还有一件事可能出错:s3可能指向s1或s2字符串的中间位置。 If this is a legit condition, then you need a bit more sophisticated implementation. 如果这是一个合法的条件,那么你需要更复杂的实现。

There are several criticisms that could be made about your function definition, but within the constraints of the problem statement your function will produce the correct answer. 关于你的函数定义有几个批评,但在问题陈述的约束下你的函数会产生正确的答案。 It isn't technically wrong. 这在技术上并不错误。

My guess is that the problem wasn't effectively communicated, or the interviewer's criticism wasn't effectively communicated. 我的猜测是问题没有得到有效沟通,或者访谈员的批评没有得到有效沟通。 Maybe clarifying these was part of the test, eh? 也许澄清这些是测试的一部分,是吗?

Here's a quick summary of possible complaints... 以下是可能投诉的快速摘要......

  • This line has a logical error... 这条线有逻辑错误......

    if (! (s1 || s2 || s3)) return; if(!(s1 || s2 || s3))返回;

...because it will return if all are null, but you probably want to return if any are null. ...因为它会返回,如果所有都为空,但你可能要返回如果有任何空。 This cannot cause failure because the problem statement says none can be null. 这不会导致失败,因为问题语句说none都不能为null。

  • The same line mentioned above fails silently. 上面提到的同一行无声地失败了。 It would be better to return an error code, throw an exception, or assert. 最好返回错误代码,抛出异常或断言。 Silent failure is bad practice, but still technically correct because the function cannot fail given the domain of the problem. 无声故障是不好的做法,但技术上仍然正确,因为在给定问题域的情况下,函数不会失败。
  • s1 and s2 could be type const char* for better readability and efficiency (const helps some compilers optimize). s1和s2可以是const char *类型,以提高可读性和效率(const有助于某些编译器优化)。
  • Modifying parameter variables is often considered bad practice. 修改参数变量通常被认为是不好的做法。 Another matter of readability. 另一个可读性问题。
  • You could use existing functions strcpy and strcat. 您可以使用现有函数strcpy和strcat。 Another matter of readability and efficiency. 另一个可读性和效率的问题。

A great programmer should strive beyond technical correctness for readability, efficiency, and robust error-handling, but these are mostly subjective and situational. 一个伟大的程序员应该超越技术的正确性,以提高可读性,效率和强大的错误处理能力,但这些主要是主观的和情境性的。 Anyhow, disregarding the error in your first if-statement, I think your function reads well enough and gets the job done. 无论如何,忽略你的第一个if语句中的错误,我认为你的函数读得很好并完成了工作。 :) :)

  1. invalid check 检查无效

    if (! (s1 || s2 || s3)) return; if(!(s1 || s2 || s3))返回; // one/more pointers are invalid //一个/多个指针无效

    It actually checks if at least one pointer is not 0, eg at least one pointer is valid. 它实际上检查至少一个指针是否不为0,例如至少一个指针有效。 It should be 它应该是

    if (!s1 || !s2 || !s3) return; if(!s1 ||!s2 ||!s3)返回;

  2. You fail to check if s3 is big enough or if your're writing outside (but the assumption was s3 is big enougn right? - but still it would not work in real worl) 你没有检查s3是否足够大,或者你是否在外面写作(但假设是s3很大的权利? - 但它仍然不适用于真正的世界)

  3. You fail to skip over the null which gets copied from the end of the s1 into s3. 您无法跳过从s1的末尾复制到s3的null。 You attach s2 after 0 in s3 so it will end up " s1stringvalueNULLs2stringvalue " (NULL here means value 0 or null or nil in real code, this is for illustration). 你在s3中的0之后附加s2所以它将结束“ s1stringvalueNULLs2stringvalue ”(这里的NULL表示值0或null或实际代码中的nil,这是为了说明)。 Any C method that expects null terminated string will only see the " s1stringvaluepart " and will stop at null. 任何期望以null结尾的字符串的C方法只会看到“ s1stringvaluepart ”并且将在null处停止。

Here's a solution: 这是一个解决方案:

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

You can test it with: 你可以测试它:

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

}

Please correct me if I'm wrong. 如果我错了,请纠正我。 Wouldn't the last character of s3 be '\\0' after copying s1? 复制s1后,s3的最后一个字符不是'\\ 0'吗? So the remaining characters from s2 could never be read in some cases? 那么在某些情况下,s2中的剩余字符永远无法读取?

From my understanding 从我的理解

while(*s3++ = *s1++);

will copy the characters until NULL is reached and '\\0' isn't NULL, or is it treated as such? 将复制字符,直到达到NULL并且'\\ 0'不是NULL,或者它是否被视为? If I can assume that s1 = "Hello" and s2 = " world!" 如果我可以假设s1 =“你好”而s2 =“世界!” then after copying s1, s3 would look like: Hello\\0 and then copying the " world!" 然后在复制s1之后,s3看起来像:Hello \\ 0然后复制“世界!” bit would result in s3 looking like: Hello\\0 world!\\0 bit会导致s3看起来像:Hello \\ 0 world!\\ 0

Does it make any sense? 它有意义吗? Is my understanding correct? 我的理解是否正确?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM