https://www.52pojie.cn/thread-576232-1-1.html
*******前言 *******
我数一下,我发了几个帖子,1、2、3?
哈哈哈,没几个哈,感谢吾爱,让我学到了很多,乐于分享,共同进步!
最近也是在学c语言,也看了少许面试题
指针,数据结构,字符串操作肯定是重点
今天分享出来的是,一些字符串操作函数和一些内存操作函数的手动实现
内容应该不难,如有错误还请朋友们指出,我会认真改正的,希望一起学习进步
******* 目录 *******
字符串常见函数:
strlen、strcmp、strcpy、strlwr、strrev、strset、strstr、strupr、itoa、atoi、atof、ftoa
(希望初学者能够尝试用 下标访问 和 指针访问两种方式实现)
内存操作少许函数:
memccpy、memchr、memcpy、memicmp、memmove、memset
(希望读者能够认真手动实现)
当然实际开发中,这些函数直接调用就行了,
但是面试的时候,这是基础知识,这是考察你的基本功 和 砍你工资的大斧
因为简单,所以代码注释少,有疑惑的请告诉我,乐于交流
*******字符串函数 *******
1.strlen:计算字符串长度(不包含'\0')
实现想法:遍历字符串,直到'\0'结束
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//指针法
unsigned
int
mystrlenaddr(
const
char
* str)
//为什么使用const char,我们只计数不对原数据进行改变
{
int
length = 0;
//长度初始化为0
while
(*str++)
{
length++;
}
return
length;
}
void
main()
{
char
* str =
"fengcong is fucking too handsome"
;
//32个
//printf("%d\n", strlen(str));
printf
(
"%d\n"
, mystrlenaddr(str));
system
(
"pause"
);
}
|
2.strcmp:比较字符串大小(一般用于字符串排序)
实现想法:依次从字符串开始一直找到不同的那个字符进行比较,得出大小
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
//掌握指针法
int
mystrcmp(
char
const
* str1,
const
char
* str2)
{
while
(*str1 == *str2 && *str1 !=
'0'
)
//一直找到两个字符串不同的地方
{
str1++;
str2++;
}
if
(*str1 > *str2)
return
1;
else
if
(*str1 < *str2)
return
-1;
else
return
0;
}
void
main()
{
char
* str =
"feng1"
;
char
* str1 =
"feng2"
;
//printf("%d\n", strcmp(str, str1));
printf
(
"%d\n"
, mystrcmp(str, str1));
system
(
"pause"
);
}
|
3.strcpy:用于字符串复制(复制包含'\0')
实现想法:一直复制到'\0'结束
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//指针法
char
* mystrcpyaddr(
char
* dest,
const
char
* source)
{
if
(dest == NULL || source == NULL)
{
return
NULL;
//如果目的操作或者源为空,那么久直接返回
}
while
(*dest++ = *source++)
//装X写法
;
return
dest;
}
//下标法
char
* mystrcpyindex(
char
* dest,
const
char
* source)
{
if
(dest == NULL || source == NULL)
{
return
NULL;
//如果目的操作或者源为空,那么久直接返回
}
int
i = 0;
while
(source !=
'\0'
)
{
dest = source;
i++;
}
dest = source;
//因为要把最后的\0拷贝过去
return
dest;
}
void
main()
{
char
* str =
"fengcong is fucking too handsome"
;
char
str1[100];
//目的字符数组
//strcpy(str1, str);
//printf("%s\n", str1);
mystrcpyindex(str1, str);
printf
(
"%s\n"
, str1);
system
(
"pause"
);
}
|
4.strlwr:大写转小写
实现想法:遍历字符串,遇到大写转为小写
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char
* mystrlwr(
char
* str)
{
char
* p1 = str;
while
(*p1)
{
if
(*p1 >=
'A'
&& *p1 <=
'Z'
)
{
*p1 += 32;
}
p1++;
}
return
str;
}
void
main()
{
char
str[50] =
"FENGCONG IS FUCKING TOO HANDSOME"
;
//printf("%s\n", _strlwr(str));
printf
(
"%s\n"
, mystrlwr(str));
system
(
"pause"
);
}
|
5.strrev:字符串逆转
实现想法:头首交换,直到中间
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
char
* mystrrev(
char
* str)
{
char
* p2 = str;
char
* p1 = str;
while
(*p1++)
{
;
}
p1 -= 2;
//回到最后一个字符
while
(p1 - p2 >= 1)
{
char
temp = *p1;
*p1 = *p2;
*p2 = temp;
p2++;
p1--;
}
return
str;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
//_strrev(str);
//printf("%s\n", str);
printf
(
"%s\n"
,mystrrev(str));
system
(
"pause"
);
}
|
6.strset:将字符串全部设成某字符
实现想法:遍历字符串,每个字符设置某字符,直至'\0'
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#define _CRT_SECURE_NO_WARNINGS
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
char
* mystrset(
char
* str,
int
value)
{
char
* p1 = str;
while
(*p1)
{
*p1 = value;
p1++;
}
return
str;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
//printf("%s\n", _strset(str, 'A'));
printf
(
"%s\n"
, mystrset(str,
'A'
));
system
(
"pause"
);
}
|
7.strstr:寻找母串中是否存在某个子串(稍难)
实现想法:依次比对
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//下标 法
char
* mystrstrindex(
char
*
const
momstr,
const
char
*
const
sonstr)
//前者指针指向的数据可变,但是指针不可变,后者都不可变
{
int
momlen =
strlen
(momstr);
//母串的长度
int
sonlen =
strlen
(sonstr);
//子串的长度
for
(
int
i = 0; i < (momlen - sonlen); i++)
//从0开始循环母串,到momlen-sonlen停止
{
int
flag = 1;
for
(
int
j = 0; j < sonlen; j++)
{
if
(momstr[i + j] != sonstr[j])
{
flag = 0;
break
;
//如果出现不相等就 退出循环,继续从下面一个寻找
}
}
if
(flag)
{
return
(&momstr);
}
}
return
NULL;
}
//指针法
char
* mystrstraddr(
char
*
const
momstr,
const
char
*
const
sonstr)
{
char
* mstr = momstr;
//母串
while
(*mstr)
{
char
* sstr = sonstr;
//子串
char
* momnowstr = mstr;
//记录现在母串的位置
int
flag = 1;
while
(*sstr != 0)
{
if
(*sstr != *momnowstr || *momnowstr ==
'0'
)
{
flag = 0;
break
;
}
momnowstr++;
sstr++;
}
if
(flag)
{
return
mstr;
}
mstr++;
//母串对比位置+1
}
return
NULL;
}
void
main()
{
char
* str =
"fengcong is too fucking handsome"
;
//printf("%p", strstr(str, "fengcong"));
//printf("%p", mystrstrindex(str, "engcong"));
printf
(
"%p"
, mystrstraddr(str,
"some"
));
system
(
"pause"
);
}
|
8.strupr:小写转大写
实现想法:依次遍历,遇到小写转为大写
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char
* mystrupr(
char
* str)
{
char
* p1 = str;
while
(*p1)
{
if
(*p1 >=
'a'
&& *p1 <=
'z'
)
{
*p1 -= 32;
}
p1++;
}
return
str;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
//printf("%s\n", _strupr(str));
printf
(
"%s\n"
, mystrupr(str));
system
(
"pause"
);
}
|
9.itoa:整数转字符串
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char
* myitoa(
int
value,
char
* str)
{
char
* pstr = str;
//str本身不能改变,一会要返回str
if
(value < 0)
{
*pstr =
'-'
;
pstr++;
value *= -1;
//转变为正数处理
}
int
wei = 1;
//数至少一位
int
ivalue = value;
//用于测试长度
while
((ivalue /= 10) != 0)
{
wei++;
}
pstr += wei-1;
while
(value % 10 != 0)
{
*pstr-- = (value % 10)+
'0'
;
value /= 10;
}
return
str;
}
void
main()
{
int
num = -45644;
char
str[20] = { 0 };
printf
(
"%s"
, myitoa(num, str));
system
(
"pause"
);
}
|
10.atoi:字符串转整数(遇到非数字字符结束)
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int
myatoi(
const
char
* str)
{
if
(str == NULL)
{
return
0;
}
int
num = 0;
//需要返回的值
int
flag = 1;
//记录正负号
if
(*str ==
'-'
)
{
flag = -1;
str++;
}
else
if
(*str ==
'+'
)
{
str++;
}
while
(*str >=
'0'
&& *str <=
'9'
)
{
num= (num * 10 + (*str -
'0'
));
str++;
}
return
num*flag;
}
void
main()
{
char
str[20] =
"-57124"
;
int
num = 0;
printf
(
"%d\n"
,myatoi(str));
system
(
"pause"
);
}
|
11.atof:字符串转浮点数
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
double
myatof(
char
const
* str)
{
if
(str == NULL)
return
0;
//首先判断有无符号位
int
flag = 1;
if
(*str ==
'-'
)
{
flag = -1;
str++;
}
if
(*str ==
'+'
)
{
str++;
}
int
zhengshu = 0;
//存储整数部分
while
(*str >=
'0'
&& *str <=
'9'
)
{
zhengshu = zhengshu * 10 + (*str -
'0'
);
*str++;
}
//整数部分循环完了
double
xiaoshu = 0.0;
//存储小数部分
//因为不明符号停止整数循环
if
(*str !=
'.'
)
{
return
(flag * zhengshu);
}
else
//代表遇到. 结束
{
str++;
//指向小数部分第一位
double
i = 0.1;
while
(*str >=
'0'
&& *str <=
'9'
)
{
xiaoshu = xiaoshu + (*str -
'0'
)*i;
i /= 10;
str++;
}
return
flag *(zhengshu + xiaoshu);
}
}
void
main()
{
char
str[20] =
"2.1554"
;
double
db = 0.0;
printf
(
"%lf\n"
, myatof(str));
system
(
"pause"
);
}
|
12.ftoa:浮点数转字符串(浮点数存储不准确,可能有少许误差)
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char
* myftoa(
double
db,
char
* str)
{
char
* pstr = str;
//先判断 符号位
if
(db < 0)
{
*pstr =
'-'
;
db *= -1;
//转为正数处理
pstr++;
}
//整数部分
int
zhengshu = (
int
)db;
int
izhengshu = zhengshu;
//牺牲于记录整数长度
int
wei = 1;
//整数部分至少一位
while
((izhengshu /= 10) != 0)
{
wei++;
}
pstr += wei - 1;
for
(
int
i = 0; i < wei; i++)
{
*pstr-- = zhengshu % 10 +
'0'
;
zhengshu /= 10;
}
pstr += (wei+1);
*pstr =
'.'
;
pstr++;
//小数部分
double
xiaoshu = db - (
int
)db;
for
(
int
i = 0; i < 6; i++)
{
*pstr++ = (
int
)(xiaoshu * 10) +
'0'
;
xiaoshu = xiaoshu * 10 - (
int
)(xiaoshu * 10);
}
return
str;
}
void
main()
{
double
db = -2.11;
char
str[20] = { 0 };
printf
(
"%s\n"
, myftoa(db,str));
system
(
"pause"
);
}
|
*******内存操作函数 *******
1.memccpy:内存拷贝,直到一个值结束
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
//下标法
void
* mymemccpybyindex(
void
* dest,
const
void
* sor,
int
val,
size_t
len)
{
if
(dest == NULL || sor == NULL)
{
return
NULL;
}
for
(
int
i = 0; i < len; i++)
{
if
( (((
char
*)dest) = ((
char
*)sor)) == val)
return
dest;
}
return
dest;
}
//指针法
void
* mymemccpybyaddr(
void
* dest,
const
void
* sor,
int
val,
size_t
len)
{
if
(dest == NULL || sor == NULL)
{
return
NULL;
}
char
* pdest = dest;
char
* psor = sor;
char
* plast = (
char
*)sor + len;
while
(psor < plast)
{
if
((*pdest++ = *psor++) == val)
return
dest;
}
return
dest;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
char
* pstr = (
char
[50]) { 0 };
//在栈上开辟一段内存
//printf("%s\n", memccpy(pstr,str,'s',32));
printf
(
"%s\n"
, mymemccpybyaddr(pstr, str,
'f'
, 32));
system
(
"pause"
);
}
|
2.memchr:某段内存中寻找某个值
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
void
* mymemchar(
void
* buf,
int
val,
size_t
size)
{
if
(buf == NULL)
{
return
NULL;
}
char
* p = buf;
char
plast = p + size;
while
(p < plast)
{
if
(*p == val)
{
return
p;
}
p++;
}
return
NULL;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
printf
(
"%s\n"
, mymemchar(str,
'g'
, 8));
system
(
"pause"
);
}
|
3.memcpy:拷贝某段内存
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
//下标法
void
* mymemcpybyindex(
void
* dest,
const
void
* sor,
size_t
len)
{
if
(dest == NULL || sor == NULL)
{
return
NULL;
}
for
(
int
i = 0; i < len; i++)
{
((
char
*)dest) = ((
char
*)sor);
}
return
dest;
}
//指针法
void
* mymemcpybyaddr(
void
* dest,
const
void
* sor,
size_t
len)
{
if
(dest == NULL || sor == NULL)
{
return
NULL;
}
char
* pdest = dest;
char
* psor = sor;
char
* plast = (
char
* )sor + len;
while
(psor < plast)
{
*pdest++ = *psor++;
}
return
dest;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
char
* pstr = (
char
[50]) { 0 };
//在栈上开辟一段内存
//printf("%s\n", memcpy(pstr, str, 32));
printf
(
"%s\n"
, mymemcpybyaddr(pstr, str, 31));
system
(
"pause"
);
}
|
4.memicmp:比较某段内存大小(一个字节一个字节比较,像strcmp)
注意:切不可用来比较整数,除非一字节整数,因为整数存储方式是高位高字节
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
int
mymemicmpbyaddr(
const
void
* buf1,
const
void
* buf2,
size_t
size)
{
char
* p1 = buf1;
char
* p2 = buf2;
int
i = 0;
while
(*p1 == *p2 && i < size)
{
p1++;
p2++;
i++;
}
if
(*p1 > *p2)
{
return
1;
}
else
if
(*p1 < *p2)
return
-1;
else
return
0;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
char
str1[50] =
"fengfeng is fucking too handsome"
;
printf
(
"%d\n"
, mymemicmpbyaddr(str, str1, 32));
system
(
"pause"
);
}
|
5.memmove:和memcpy类似,但是memmove采用了中间空间,memcpy是直接拷贝
两者区别之处在于当拷贝地址重复的时候,结果不一样(比较代码可知)
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<malloc.h>
void
* mymemmove(
void
* dest,
const
void
* sor,
size_t
size)
{
char
* ptemp =
malloc
(size);
//中间 地址
memcpy
(ptemp, sor, size);
memcpy
(dest, ptemp, size);
free
(ptemp);
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
//memmove(str + 3, str + 4, 2);
mymemmove(str + 3, str + 4, 2);
printf
(
"%s\n"
,str);
system
(
"pause"
);
}
|
6.memset:对指定内存每个字节赋某个值
[C]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
//下标法
void
* mymemsetbyindex(
void
* dest,
int
val,
size_t
len)
{
if
(dest == NULL)
{
return
NULL;
}
if
(len == 0)
{
return
dest;
}
char
* p = dest;
for
(
int
i = 0; i < len; i++)
{
p = val;
}
return
dest;
}
//指针法
void
* mymemsetbyaddr(
void
* dest,
int
val,
size_t
len)
{
if
(dest == NULL)
{
return
NULL;
}
if
(len == 0)
{
return
dest;
}
char
* p = dest;
char
* plast = p + len;
while
(p < plast)
{
*p++ = val;
}
return
dest;
}
void
main()
{
char
str[50] =
"fengcong is fucking too handsome"
;
//printf("%s\n", memset(str, 65, 8));
printf
(
"%s\n"
, mymemsetbyaddr(str, 65, 8));
system
(
"pause"
);
}
|
*******结束语
*******
内容应该都不难,希望大家讨论讨论,认真实现,不要让这基本功成为
面试官挥动大斧砍你工资的把柄
文中代码区,少许地方少*,不知道为什么,请注意添加
再会了,还是那句话,你们开心就好,拜个早年!
再会了,还是那句话,你们开心就好,拜个早年!