【プログラミング練習問題】面接常考C言語ライブラリ関数-atoi.itoa.atof.strcmp.strcpy.memset.memcpy
5842 ワード
これらの関数のコードは短いですが、面接官はあなたのいくつかの短いコードに高い期待を持っています.
まず、正確性!実現が正しくないのに、それはまだ毛が生えているんだよ.他の小さな問題はもう話さないに違いない.直接out!正確性に注意しなければならない点は、各関数の機能が少なくとも(memmoveなど)理解され、境界の検査が間違ってはいけないことである.戻り値も注意すべき点です.
次に、assertは少なくできません!ポインタの有効性のチェックは非常に必要であり、特にmemcpyでは、ポインタの有効性とメモリが重複しているかどうかをそれぞれチェックする2つのassertが存在する.2番目のassertには必要な注釈を付けます(コードのメンテナンス者はこのassertの意味を一目で見ることができるわけではないので、メンテナンスコードの中でこのような重要なassertチェックを直接削除することはできません).
次に注意したいのは、ポインタの有効性検査で、NULLと比較したほうがいいということです.最後に、空の文(strcpy)、括弧は1つも少なくできません.
どのように考えるか:
私たちがプログラミングをしているとき、私たちの頭の中で本当に考えているのは手で叩いたコードですか?私たちが関数やクラスを実現しているとき、私たちは本当にそれがどのように実現されるべきかを真剣に考えていますか?これらの小さな関数(もちろん、大きな関数はもっと同じです)に対して、パラメータの有効性検査はalwaysに必要です(入力を信じないでください!)、境界の有効性チェックは間違いやすい!どの行のコードもどうしてこのように実現するのかをはっきり考えなければなりません.私は、あなたの頭が考えていることがあなたの手でしなければならない限り、私の手が私の心を「書く」ことは、もちろん間違いではありません.少なくとも、自分がどこに間違っているのかを知っていなければなりません.今度修正すればいいと思います.
「マイクロソフトCプログラミングエッセンス」の最後の一言は、間違いのないコードを書くことに成功する鍵は、同じエラーが2回も発生することを許さないという全体的な原則にまとめることができます.
-------------------------------------------------------atoi----------------------------------------------------------
-------------------------------------------------atof------------------------------------------------------------
---------------------------------------------itoa--------------------------------------------------------------------
以下はstrxxxとmemxxxシリーズです
-------------------------------------------------------strcmp------------------------------------------------------
-------------------------------------------strcpy--------------------------------------------------------------------
--------------------------------------memcpy---------------------------------------------------------------------
--------------------------------------memmove------------------------------------------------------------------
--------------------------------------memset---------------------------------------------------------------------
まず、正確性!実現が正しくないのに、それはまだ毛が生えているんだよ.他の小さな問題はもう話さないに違いない.直接out!正確性に注意しなければならない点は、各関数の機能が少なくとも(memmoveなど)理解され、境界の検査が間違ってはいけないことである.戻り値も注意すべき点です.
次に、assertは少なくできません!ポインタの有効性のチェックは非常に必要であり、特にmemcpyでは、ポインタの有効性とメモリが重複しているかどうかをそれぞれチェックする2つのassertが存在する.2番目のassertには必要な注釈を付けます(コードのメンテナンス者はこのassertの意味を一目で見ることができるわけではないので、メンテナンスコードの中でこのような重要なassertチェックを直接削除することはできません).
次に注意したいのは、ポインタの有効性検査で、NULLと比較したほうがいいということです.最後に、空の文(strcpy)、括弧は1つも少なくできません.
どのように考えるか:
私たちがプログラミングをしているとき、私たちの頭の中で本当に考えているのは手で叩いたコードですか?私たちが関数やクラスを実現しているとき、私たちは本当にそれがどのように実現されるべきかを真剣に考えていますか?これらの小さな関数(もちろん、大きな関数はもっと同じです)に対して、パラメータの有効性検査はalwaysに必要です(入力を信じないでください!)、境界の有効性チェックは間違いやすい!どの行のコードもどうしてこのように実現するのかをはっきり考えなければなりません.私は、あなたの頭が考えていることがあなたの手でしなければならない限り、私の手が私の心を「書く」ことは、もちろん間違いではありません.少なくとも、自分がどこに間違っているのかを知っていなければなりません.今度修正すればいいと思います.
「マイクロソフトCプログラミングエッセンス」の最後の一言は、間違いのないコードを書くことに成功する鍵は、同じエラーが2回も発生することを許さないという全体的な原則にまとめることができます.
-------------------------------------------------------atoi----------------------------------------------------------
int atoi(const char* str)
{
int sign = 0,num = 0;
assert(NULL != str);
while (*str == ' ')
{
str++;
}
if ('-' == *str)
{
sign = 1; str++;
}
while ((*str >= '0') && (*str <= '9'))
{
num = num*10 + (*str - '0'); // ,
str++;
}
if(sign == 1)
return -num;
else
return num;
}
-------------------------------------------------atof------------------------------------------------------------
double atof(const char* str)
{
double val = 0.0,power = 0.0;
int sign = 0;
assert(NULL != str);
while (*str == ' ')
{
str++;
}
sign = (*str == '-')? -1 : 1;
if ('-' == *str || '+' == *str)
{
str++;
}
while ((*str >= '0')&&(*str <= '9'))
{
val = val* 10.0 + (*str - '0'); str++;
}
if ('.' == *str)
{
str++;
}
power = 1.0;
while ((*str >= '0')&&(*str <= '9'))
{
val = val* 10.0 + (*str - '0');
power *= 10; str++;
}
return sign*val/power;
}
---------------------------------------------itoa--------------------------------------------------------------------
char* itoa(int val,char* buf,unsigned int radix)
{
char *bufptr;
char *firstdig;
char temp;
unsigned int digval;
assert(buf != NULL);
bufptr = buf;
if (val < 0)
{
*bufptr++ = '-'; val = (unsigned int)(-(int)val);
}
firstdig = bufptr;
do
{
digval =(unsigned int) val % radix; val /= radix;
if (digval > 9)
{
*bufptr++ = (char)(digval - 10 + 'a');
}
else
{
*bufptr++ = (char)(digval + '0');
}
} while(val > 0);
*bufptr-- = '\0';// ,
do //
{
temp = *bufptr; *bufptr = *firstdig; *firstdig = temp;
--bufptr; ++firstdig;
} while(firstdig < bufptr);
return buf;
}
以下はstrxxxとmemxxxシリーズです
-------------------------------------------------------strcmp------------------------------------------------------
int strcmp(const char* src,const char* dst)
{
int ret = 0;
if (src == dst)
{
return 0;
}
assert(NULL != src);//
if (dst == NULL)
{
return -1;
}
while (!(ret = *(unsigned char*)src - *(unsigned char*)dst)&& *dst)
{
++src,++dst;
}
if (ret < 0)
{
ret = -1;
}
else if (ret > 0)
{
ret = 1;
}
return ret;
}
-------------------------------------------strcpy--------------------------------------------------------------------
char* strcpy(char* dst,const char* src)
{
char* strDst = dst;
assert(src != NULL && dst != NULL);// , assert
while ((*dst++ = *src++) != '\0')
{
NULL;
}
return strDst;
}
--------------------------------------memcpy---------------------------------------------------------------------
void* memcpy(void* dst,const void* src,size_t count)
{
char* pbTo = (char*)dst; // dst
char* pbFrom = (char*)src;
assert(dst!= NULL && src != NULL);
assert(pbTo >= pbFrom+count || pbFrom >= pbTo + count);// (overlap)
while (count-- > 0)
{
*pbTo++ = *pbFrom++;
}
return dst;
}
--------------------------------------memmove------------------------------------------------------------------
void* memmove(void* dst,const void* src,size_t count)
{
char* pbTo = (char*)dst;
char* pbFrom = (char*)src;
assert(dst != NULL && src != NULL);
if (dst <= src || pbTo >= pbFrom + count)// overlap ,
{
while (count-- > 0)
{
*pbTo++ = *pbFrom++;
}
}
else
{
pbTo = pbTo + count -1;//overlap ,
pbFrom = pbFrom + count -1;
while (count-- > 0)
{
*pbTo-- = *pbFrom--;
}
}
return dst;
}
--------------------------------------memset---------------------------------------------------------------------
void* memset(void* buf,int c,size_t count)
{
char* pvTo = (char*)buf;
assert(buf != NULL);
while (count-- >0)
{
*pvTo++ = (char)c;
}
return buf;
}