库函数strcpy/strlen的工作方式
2015-10-27 17:07
218 查看
库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案:
2分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
4分
void strcpy( char *strDest, const char *strSrc )
//将源字符串加const,表明其为输入参数,加2分
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
7分
void strcpy(char *strDest, const char *strSrc)
{
//对源地址和目的地址加非0断言,加3分
assert( (strDest != NULL) && (strSrc != NULL) );
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
10分
//为了实现链式操作,将目的地址返回,加3分!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ );
return address;
}
从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!
读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为:
int strlen( const char *str ) //输入参数const
{
assert( strt != NULL ); //断言字符串地址非0
int len;
while( (*str++) != '\0' )
{
len++;
}
return len;
}
strcpy得到了很多面试人员的偏爱,其很大的体现出了C语言基本功.
下面是strcpy原函数
char *strcpy(char *strDest, const char *strSrc);
{
assert((strDest!=NULL)&& (strSrc !=NULL));
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ )
NULL ;
return address ;
}
有几个问题值得思考并注意:
1.用指针作为形参,在程序开始前应判断指针变量的合法性,利用断言assert
2.只作为输入参数,为了防止被编程人员恶意修改,应加入常量声明const
3.函数返回类型为,char *,其目的是为了方便实现链表表达式.在调用函数的过程中已经实现了把strSrc的内容复制到strDest
4.应注意对原始位置的保留.
5.该函数调用完成时是遇到'\0'结束符
下面是几个找错题:
试题1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
试题2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1[i] = 'a';
}
strcpy( string, str1 );
}
试题3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
试题1字符串str1需要11个字节才能存放下(包括末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界;从第5条可以看出,函数调用完成时已经将'\0'一同赋给了目的地址.
试题2,问题很严重,对string[10]数组的赋值本身没有错误,但很明显程序期望对string按字符串操作,这就需要额外的赋给一个'\0'结束符;另外如果没有'\0'结束标志,调用strcpy将不会结束,造成程序的不确定性,很危险.
试题3,一定要注意strlen(pstr),它和strcpy不同,遇到'\0'时结束,但并不计算\0'在内.所以应改为if( strlen( str1 ) <=10 ),另外要注意字符串首地址,数组,各种类型的指针作为形参,都退化为指针.即
void test3(char* str1)
{
sizeof(str1)只和编译器和CPU类型有关,32位CPU为4
2分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
4分
void strcpy( char *strDest, const char *strSrc )
//将源字符串加const,表明其为输入参数,加2分
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
7分
void strcpy(char *strDest, const char *strSrc)
{
//对源地址和目的地址加非0断言,加3分
assert( (strDest != NULL) && (strSrc != NULL) );
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
10分
//为了实现链式操作,将目的地址返回,加3分!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ );
return address;
}
从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!
读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为:
int strlen( const char *str ) //输入参数const
{
assert( strt != NULL ); //断言字符串地址非0
int len;
while( (*str++) != '\0' )
{
len++;
}
return len;
}
strcpy得到了很多面试人员的偏爱,其很大的体现出了C语言基本功.
下面是strcpy原函数
char *strcpy(char *strDest, const char *strSrc);
{
assert((strDest!=NULL)&& (strSrc !=NULL));
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ )
NULL ;
return address ;
}
有几个问题值得思考并注意:
1.用指针作为形参,在程序开始前应判断指针变量的合法性,利用断言assert
2.只作为输入参数,为了防止被编程人员恶意修改,应加入常量声明const
3.函数返回类型为,char *,其目的是为了方便实现链表表达式.在调用函数的过程中已经实现了把strSrc的内容复制到strDest
4.应注意对原始位置的保留.
5.该函数调用完成时是遇到'\0'结束符
下面是几个找错题:
试题1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
试题2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1[i] = 'a';
}
strcpy( string, str1 );
}
试题3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
试题1字符串str1需要11个字节才能存放下(包括末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界;从第5条可以看出,函数调用完成时已经将'\0'一同赋给了目的地址.
试题2,问题很严重,对string[10]数组的赋值本身没有错误,但很明显程序期望对string按字符串操作,这就需要额外的赋给一个'\0'结束符;另外如果没有'\0'结束标志,调用strcpy将不会结束,造成程序的不确定性,很危险.
试题3,一定要注意strlen(pstr),它和strcpy不同,遇到'\0'时结束,但并不计算\0'在内.所以应改为if( strlen( str1 ) <=10 ),另外要注意字符串首地址,数组,各种类型的指针作为形参,都退化为指针.即
void test3(char* str1)
{
sizeof(str1)只和编译器和CPU类型有关,32位CPU为4
相关文章推荐
- (转)使用MAT比较多个heap dump文件
- 用友--扩展插件要怎么做
- lintcode 中等题:Max Points on a Line 最多有多少个点在一条直线上
- shell脚本判断文件类型
- Java点滴-List<Integer> list; 中尖括号的意思
- Andriod ListView 滑动到指定项,顶部,底部
- 最简单的观察者模式--转载
- Unity3D的四种坐标系
- 数据库知识点笔记
- 动态设置label的高度
- uboot中,nfs挂载的bootargs
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- 表单按回车自动提交(转)
- iOS开发UI篇—Quartz2D使用(绘图路径)
- 牛逼的ios在github上的库
- 3.14
- 变更管理、配置管理及风险管理的重点
- HTML5+CSS3学习(-)创建HTML5
- <input type=button> 跳转页面
- 保持优势的16字箴言