[英]What is wrong in my concatenation function mystrcat(char*, char*, char*)?
我最近接受了采訪並要求編寫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';
}
你能告訴我這里有什么問題嗎? 做什么會更專業呢?
if (! (s1 || s2 || s3) return; // one/more pointers are invalid
應該
if ((!s1) || (!s2) || (!s3)) return;
兩個可能的點
首先,您被告知輸入和輸出指向有效字符串,因此可以說不需要測試有效性。 如果需要,你應該吵鬧失敗。 更好的是:
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界面是非常精心設計的,並提供了如何改進它的細節。
這是我的評論
const char*
因為你無意修改它們。 我希望你在面試中問我或自己回答的問題
除了之前的答案,還有一件事可能出錯:s3可能指向s1或s2字符串的中間位置。 如果這是一個合法的條件,那么你需要更復雜的實現。
關於你的函數定義有幾個批評,但在問題陳述的約束下你的函數會產生正確的答案。 這在技術上並不錯誤。
我的猜測是問題沒有得到有效溝通,或者訪談員的批評沒有得到有效溝通。 也許澄清這些是測試的一部分,是嗎?
以下是可能投訴的快速摘要......
這條線有邏輯錯誤......
if(!(s1 || s2 || s3))返回;
...因為它會返回,如果所有都為空,但你可能要返回如果有任何空。 這不會導致失敗,因為問題語句說none都不能為null。
一個偉大的程序員應該超越技術的正確性,以提高可讀性,效率和強大的錯誤處理能力,但這些主要是主觀的和情境性的。 無論如何,忽略你的第一個if語句中的錯誤,我認為你的函數讀得很好並完成了工作。 :)
檢查無效
if(!(s1 || s2 || s3))返回; //一個/多個指針無效
它實際上檢查至少一個指針是否不為0,例如至少一個指針有效。 它應該是
if(!s1 ||!s2 ||!s3)返回;
你沒有檢查s3是否足夠大,或者你是否在外面寫作(但假設是s3很大的權利? - 但它仍然不適用於真正的世界)
您無法跳過從s1的末尾復制到s3的null。 你在s3中的0之后附加s2所以它將結束“ s1stringvalueNULLs2stringvalue
”(這里的NULL表示值0或null或實際代碼中的nil,這是為了說明)。 任何期望以null結尾的字符串的C方法只會看到“ 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;
}
如果我錯了,請糾正我。 復制s1后,s3的最后一個字符不是'\\ 0'嗎? 那么在某些情況下,s2中的剩余字符永遠無法讀取?
從我的理解
while(*s3++ = *s1++);
將復制字符,直到達到NULL並且'\\ 0'不是NULL,或者它是否被視為? 如果我可以假設s1 =“你好”而s2 =“世界!” 然后在復制s1之后,s3看起來像:Hello \\ 0然后復制“世界!” bit會導致s3看起來像:Hello \\ 0 world!\\ 0
它有意義嗎? 我的理解是否正確?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.