您的位置:首页 > 其它

程序笔试题-strcpy,swap,指针数组和数组指针

2016-07-04 08:51 225 查看
notes: strcpy论述的目录,层次,标注和例子都非常好

阅读目录
1.strcpy的实现代码
2.为什么要返回char
*?
3.假如考虑dst和src内存重叠的情况,strcpy该怎么实现

一. strcpy
代码实现



#include <iostream>
#include <assert.h>
#include <iostream>
//#include <string.h>
using namespace std;
int strlen(const char *src)
{
assert(src != NULL);
int lens = 0;
while (*src++ != '\0')
lens++;
return lens;
}

char *memcpy(char *dst, const char *src, int cnt)
{
assert(dst != NULL && src != NULL);
char *ret = dst;
if (dst >= src && dst <= src + cnt - 1)
{
src += cnt - 1;
dst += cnt - 1;
while (cnt--)
*dst-- = *src--;
}
else
{
while (cnt--)
*dst++ = *src++;
}
return ret;
}

char *strcpy(char *dst, const char *src)
{
assert(dst != NULL);
assert(src != NULL);
char *ret = dst;
memcpy(dst, src, strlen(src)+1);
return ret;
}

int main()
{
char a[] = "hello";
char b[] = "b1";
//strcpy(a, b);
strcpy(a, a+1);
char *f = strcpy(a, a+1);
cout << a << endl;
cout << f << endl;
int m = 0;
int n = 5;
int c = (m=n++);
cout << "c:" << c << endl;
cout << "n:" << n << endl;
return 0;
}


已知strcpy函数的原型是:
char *strcpy(char *dst, const char *src);
实现strcpy函数
解释为什么要返回char *
假如考虑dst和src内存重叠的情况,strcpy该怎么实现
回到顶部

1.strcpy的实现代码

char * strcpy(char *dst,const char *src)   //[1]
{
assert(dst != NULL && src != NULL);    //[2]

char *ret = dst;  //[3]

while ((*dst++=*src++)!='\0'); //[4]

return ret;
}


[1]const修饰
源字符串参数用const修饰,防止修改源字符串。
[2]空指针检查
不检查指针的有效性,说明答题者不注重代码的健壮性。
检查指针的有效性时使用assert(!dst && !src);char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。
检查指针的有效性时使用assert(dst != 0 && src != 0);直接使用常量(如本例中的0)会减少程序的可维护性。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。
[3]返回目标地址
忘记保存原始的strdstt值。
[4]'\0'
循环写成while (*dst++=*src++);明显是错误的。
循环写成while (*src!='\0') *dst++=*src++;
循环体结束后,dst字符串的末尾没有正确地加上'\0'。
回到顶部

2.为什么要返回char *?

返回dst的原始值使函数能够支持链式表达式。
链式表达式的形式如:
int l=strlen(strcpy(strA,strB));
又如:
char * strA=strcpy(new char[10],strB);
返回strSrc的原始值是错误的。
其一,源字符串肯定是已知的,返回它没有意义。
其二,不能支持形如第二例的表达式。
其三,把const char *作为char *返回,类型不符,编译报错。
回到顶部

3.假如考虑dst和src内存重叠的情况,strcpy该怎么实现

char s[10]="hello";
strcpy(s, s+1); //应返回ello,
//strcpy(s+1, s); //应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了
所谓重叠,就是src未处理的部分已经被dst给覆盖了,只有一种情况:src<=dst<=src+strlen(src)
C函数memcpy自带内存重叠检测功能,下面给出memcpy的实现my_memcpy。

char * strcpy(char *dst,const char *src)
{
assert(dst != NULL && src != NULL);

char *ret = dst;

my_memcpy(dst, src, strlen(src)+1);

return ret;
}


my_memcpy的实现如下

char *my_memcpy(char *dst, const char* src, int cnt)
{
assert(dst != NULL && src != NULL);

char *ret = dst;

if (dst >= src && dst <= src+cnt-1) //内存重叠,从高地址开始复制
{
dst = dst+cnt-1;
src = src+cnt-1;
while (cnt--)
*dst-- = *src--;
}
else    //正常情况,从低地址开始复制
{
while (cnt--)
*dst++ = *src++;
}

return ret;
}


二. strstr实现
strstr这个程序不全面,如果是123abc45abc将会返回 abc45abc
char * strstr(const char *s1, const char *s2)
{
if (s2 != NULL)
{
while (*s1 != '\0')
{
for (int i = 0; *(s1 + i) == *(s2 + i); ++i)
{
if (*(s2 + i + 1) == '\0')
return (char *)s1;
}
s1++;
}
return NULL;
}
else
return (char *)s1;
}
int main()
{
char str[] = "12345abc";
char *p = strstr(str, "abc");
printf ("%s\n", p);
}


14. 数组指针

复制代码
#include <iostream>
using namespace std;
int main()
{
int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int*)(&a+1);
cout << *(ptr-1) << "\t" << *(ptr-2) << endl; // 5 4
cout << "----------------" << endl;
int *p = (int *)(a+1);                        //2
cout << *p << endl;
}
复制代码
15. const int *a  和 int * const a 区别

复制代码
int main()
{
int b = 3;
int c = 4;
const int *p =  &b;    //等价于 int const *p = &b;
p = &c;                //修饰值,指针可变
//*p = 5;//error 修饰值,值不可变
cout << *p << endl;

int a = 5;
int * const q = &a;     //修饰指针
//p = &c;//error修饰指针,指针不可变
*p = 5;               //修饰指针,值可变
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: