C语言语法入门-字符串和指针
9unk Lv5

字符串和指针

用数组实现的字符串和用指针实现的字符串

代码清单11-1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*程序名:list1101.c*/
/*
用数组实现的字符串和用指针实现的字符串
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
char str[] = "ABC";
char* ptr = "123";

printf("str = \"%s\"\n", str);
printf("ptr = \"%s\"\n", ptr);

return 0;

}

用数组实现的字符串和用指针实现字符串的不同点

代码清单11-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*程序名:list1102.c*/
/*
用数组实现的字符串的改写
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
char s[] = "ABC";
printf("s = \"%s\"\n", s);

//s = "DEF"; /* 出错 */

printf("s=\"%s\"\n", s);

return 0;

}

代码清单11-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*程序名:list1103.c*/
/*
用数组实现的字符串的改写
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
char* p = "123";
printf("p = \"%s\"\n", p);

p = "456";

printf("p = \"%s\"\n", p);

return 0;

}

案例1:是将常量区域的 “ABC” 传给数组 s[],而 s 是指针,常量是无法直接改写指针。
案例2:是传递 “123” 常量的指针到 char* p,后面把 char* p 的值改为 “456” 常量的指针。所以可以输出不同的值。

字符串数组

代码清单11-4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*程序名:list1104.c*/
/*
字符串数组
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
int i;
char a[][5] = { "LISP","C","Ada" };
char* p[] = { "PAUL","X","MAC" };

for (i = 0; i < 3; i++)
printf("a[%d] = \"%s\"\n", i, a[i]);

for (i = 0; i < 3; i++)
printf("p[%d] = \"%s\"\n", i, p[i]);

return 0;

}

反汇编

1
2
3
4
5
6
7
8
9
10
11
printf("a[%d] = \"%s\"\n", i, a[i]);
//ebp-0Ch = i
//ebp-24h = a[0][0]

003B18DD imul eax,dword ptr [ebp-0Ch],5
003B18E1 lea ecx,[ebp+eax-24h]
003B18E5 push ecx
003B18E6 mov edx,dword ptr [ebp-0Ch]
003B18E9 push edx
003B18EA push 3B7B70h
003B18EF call 003B10D2

1

首先数组 “a[][5]” 表示每个字符串分配 5 字节的空间,因此第一个汇编代码的常量是5。i*5 表示以5字节为基准增加指针,”[ebp-24h+eax]” 每次循环加5字节。

1
2
3
4
5
6
7
8
9
10
11
printf("p[%d] = \"%s\"\n", i, p[i]);
//ebp-0Ch = i
//ebp-38h = &p

003B1911 mov eax,dword ptr [ebp-0Ch]
003B1914 mov ecx,dword ptr [ebp+eax*4-38h]
003B1918 push ecx
003B1919 mov edx,dword ptr [ebp-0Ch]
003B191C push edx
003B191D push 3B7B60h
003B1922 call 003B10D2

“[ebp-38h]”:表示数组指针 p 的地址,而数组 p 中存储的是各字符串 “PAUL”、”X”、”MAC” 的指针。”[ebp-38h+i*4]” 表示根据循环次数,取指针数组中的各字符串的指针。

通过指针操作字符串

判断字符串的长度

代码清单11-5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*程序名:list1105.c*/
/*
判断字符串的长度(适用指针遍历)
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---返回字符串s的长度---*/
int str_length(const char* s)
{
int len = 0;
while (*s++)
len++;
return len;
}

int main(void)
{
int str[128];
scanf("%s", str);

printf("字符串\"%s\"的长度是%d。\n", str, str_length(str));

return 0;

}

字符串的复制

代码清单11-6

1
2
3
4
5
6
7
8
9
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
/*程序名:list1106.c*/
/*
复制字符串
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---将字符串s复制到d---*/
int str_copy(char* d,const char* s)
{
char* t = d;
//*d = *(&str) 和 *s = &tmp
while (*d++ = *s++)
;
return t;
}

int main(void)
{
char str[128] = "ABC";
char tmp[128];

printf("str = \"%s\"\n\n", str);
printf("请输入将要复制到 str 的字符串:");
scanf("%s", tmp);
//注意:这里 str 参数是 str 变量的指针
str_copy(str, tmp);
printf("复制了:");
printf("str = \"%s\"\n", str);

return 0;

}

不正确的字符串复制

代码清单11-7

1
2
3
4
5
6
7
8
9
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
/*程序名:list1107.c*/
/*
复制字符串(误例)
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---将字符串s复制到d---*/
int* str_copy(char* d,const char* s)
{
char* t = d;
//这里的错误是 *d = *(&ptr) = ptr = "1234" 的指针。
//最终反汇编:mov byte ptr [ptr],[tmp],但是 "1234" 在常量区(无修改权限)
//最终导致报错,无写入权限
while (*d++ = *s++)
;

//t 是 char*,而返回值是 int*,因此程序执行错误(提示函数返回类型错误)。可使用 (int*)t 来将变量 t 类型进行强制转换。
return t;
}

int main(void)
{
char* ptr = "1234";
char tmp[128];

printf("ptr = \"%s\"\n\n", ptr);
printf("请输入将要复制到 str 的字符串:");
scanf("%s", tmp);
//注意:这里 ptr 参数是常量 "1234" 的指针。
str_copy(ptr, tmp);
printf("复制了:");
printf("str = \"%s\"\n", ptr);

return 0;

}

字符串处理相关的库函数

strlen 函数

2

代码清单11-8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*程序名:list1108.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---返回字符串s的长度---*/
size_t strlen(const char* s)
{
size_t len = 0;
while (*s++)
len++;
return len;
}

int main(void)
{
char* str = "1234";

printf("字符串的长度是%d\n", strlen(str));

return 0;

}

strcpy 函数、strncpy 函数:复制字符串

3

代码清单11-9

1
2
3
4
5
6
7
8
9
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
/*程序名:list1109.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---使用函数 strcpy 函数的例子---*/
char* strcpys(char* s1, const char* s2)
{
char* tmp = s1;
while (*s1++ = *s2++)
;
return tmp;
}

/*---使用 strncpy 函数的例子---*/
char* strncpys(char* s1, const char* s2, size_t n)
{
char* tmp = s1;
while (n)
{
if (!(*s1++ = *s2++)) break;
n--;
}
while (n--)
*s1++ = '\0';
return tmp;
}

int main(void)
{
char source[] = "1234";
char dest[sizeof(source)] = {0};

strcpys(dest, source);
printf("复制的字符串是%s\n", dest);
return 0;

}

strcat 函数、strncat 函数:连接字符串

4

代码清单11-10

1
2
3
4
5
6
7
8
9
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
/*程序名:list1110.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---使用 strcat 函数的例子---*/
char* strcats(char* s1, const char* s2)
{
char* tmp = s1;
while (*s1)
s1++;
while (*s1++ = *s2++)
;
return tmp;
}

/*---使用 strncat 函数的例子---*/
char* strncats(char* s1, const char* s2, size_t n)
{
char* tmp = s1;
while (*s1)
s1++;
while (n--)
if (!(*s1++ = *s2++)) break;
*s1 = '\0';
return tmp;
}


int main(void)
{
char source[] = "1234";
char dest[9] = {'A','B','C','D'};

strcats(dest, source);
printf("复制的字符串是%s\n", dest);
return 0;

}

strcmp 函数、strncmp 函数:比较字符串的大小关系

5

代码清单11-11

1
2
3
4
5
6
7
8
9
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
/*程序名:list1111.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---使用 strcmp 函数的例子---*/
int strcmps(const char* s1, const char* s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return (unsigned char)*s1 - (unsigned char)*s2;
}


/*---使用 strncmp 函数的例子---*/
int strncmps(const char* s1, const char* s2, size_t n)
{
while (n && *s1 && *s2)
{
if (*s1 != *s2)
return (unsigned char)*s1 - (unsigned char)*s2;
s1++;
s2++;
n--;
}
if (!n) return 0;
if (*s1) return 1;
}

int main(void)
{
char source[] = "ABCD";
char dest[9] = {'A','B','C','D'};

if (strcmps(dest, source))
{
printf("两个字符串不相等\n");
}
else
{
printf("两个字符串相等\n");
}

return 0;

}

atoi 函数、atol 函数、atof函数:转换字符串

6

代码清单11-12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*程序名:list1112.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
char str[128];
printf("请输入字符串:");
scanf("%s", str);

printf("转换为整数后为 %d。\n", atoi(str));

return 0;

}

总结

1
2
3
4
5
6
7
8
9
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
/*程序名:summary.c*/
/*
字符串和字符串数组
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/*---用 "" 将字符串 s 括起来显示并换行---*/
#define put_str_ln(s) (put_str(s),putchar('\n'))

/*---用 "" 将字符串 s 括起来显示并换行---*/
void put_str(const char* s)
{
putchar('\"');
while (*s)
putchar(*s++);
putchar('\"');
}

/*---将字符串转换为大写并复制---*/
char* str_cpy_toupper(char* d, const char* s)
{
char* tmp = d;
while (*d++ = toupper(*s++))
;
return tmp;
}

int main(void)
{
int i;
char s[128], t[128];
char a[] = "CIA";
char* p = "FBI";
char a2[][5] = { "LISP","C","Ada" };
char* p2[] = { "PAUL","X","MAC" };

printf("字符串 s = "); scanf("%s", s);
printf("转换为大写并复制到数组t。\n");
printf("字符串t = %s\n", str_cpy_toupper(t, s));

printf("a = "); put_str_ln(a);
printf("p = "); put_str_ln(p);

for (i = 0; i < sizeof(a2) / sizeof(a2[0]); i++)
{
printf("a2[%d] = ", i); put_str_ln(a2[i]);
}

for (i = 0; i < sizeof(p2) / sizeof(p2[0]); i++)
{
printf("p2[%d] = ", i); put_str_ln(p2[i]);
}
return 0;

}

练习

练习11-1

7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*程序名:lx11-1.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void)
{
char* p = "123";
printf("p = \"%s\"\n", p);

p = "456" + 1;

printf("p = \"%s\"\n", p);

return 0;

}

p = “456” + 1:表示将常量 “456” 的指针加1 ,传输到指针变量p中。

练习11-2

8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*程序名:lx11-2.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
int i;
int strlen;
char a[][5] = { "LISP","C","Ada" };
char* p[] = { "PAUL","X","MAC" };

strlen = sizeof(a) / sizeof(a[0]);
for (i = 0; i < strlen; i++)
printf("a[%d] = \"%s\"\n", i, a[i]);


strlen = sizeof(p) / sizeof(p[0]);
for (i = 0; i < strlen; i++)
printf("p[%d] = \"%s\"\n", i, p[i]);

return 0;

}

练习11-3

9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*程序名:lx11-3.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*---将字符串s复制到d---*/
int str_copy(char* d, const char* s)
{
char* t = d;
//*d = *(&str) 和 *s = &tmp
while (*d++ = *s++)
;
return t;
}

int main(void)
{
char str[128] = "ABC";
char tmp[128];

printf("str = \"%s\"\n\n", str);
printf("请输入将要复制到 str 的字符串:");
scanf("%s", tmp);
//注意:这里 str 参数是 str 变量的指针
printf("复制了:");
printf("str = \"%s\"\n", str_copy(str, tmp));

return 0;

}

练习11-4

10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*程序名:lx11-4.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void put_string(const char* s)
{
printf("%s\n", s);
}

int main(void)
{
char str[128] = "ABC";
put_string(str);

return 0;

}

练习11-5

11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*程序名:lx11-5.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int str_chnum(const char* s,int c)
{
int count = 0;
while (*s != '\0')
{
if (*s == c)
{
count++;
}
s++;
}
return count;
}

int main(void)
{
char str[128] = "AQCQWEQ";
char key = 'Q';
printf("字符串%s中含有%d个字符%c", str, str_chnum(str, key),key);

return 0;

}

练习11-6

12

1
2
3
4
5
6
7
8
9
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
/*程序名:lx11-6.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* str_chr(const char* s,int c)
{
char* ptrkey = NULL;
while (*s != c)
{
if (*s == '\0')
{
return ptrkey;
}
else
{
s++;
ptrkey = s;
}
}

return ptrkey;
}

int main(void)
{
char str[128] = "AQCQWEQ";
char key = 'Q';
printf("字符串%s中的第一个字符%c字符在%p中。\n", str, key,str_chr(str,key));

return 0;

}

练习11-7

13

1
2
3
4
5
6
7
8
9
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
/*程序名:lx11-7.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

/*---将字符串中的英文字符转换为大写字母---*/
void str_toupper(char* s)
{
while (*s)
{
*s = toupper(*s);
s++;
}
}

/*---将字符串中的英文字符传唤为小写字符---*/
void str_tolower(char* s)
{
while (*s)
{
*s = tolower(*s);
s++;
}
}
int main(void)
{
char str[128];

printf("请输入字符串:");
scanf("%s", str);

str_toupper(str);
printf("大写字母:%s\n", str);

str_tolower(str);
printf("小写字母:%s\n", str);

return 0;
}

练习11-8

14

1
2
3
4
5
6
7
8
9
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
/*程序名:lx11-8.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void del_digit(char* str)
{
char buffer[sizeof(str)];
char* buffer_ptr = buffer;
char* ptr_back = str;

while (*str)
{
if (*str < '0' || *str > '9')
{
*buffer_ptr = *str;
buffer_ptr++;
}
str++;
}
*buffer_ptr = 0;

strcpy(ptr_back, buffer);
}


int main(void)
{
char str[128];

printf("请输入字符串:");
scanf("%s", str);

del_digit(str);
printf("删除数字后的字符串:%s\n", str);

return 0;
}

练习11-9

15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*程序名:lx11-9.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char str[128];
char str1[128];

printf("请输入字符串:");
scanf("%s", str);

printf("字符串的长度:%d\n", strlen(str));

printf("请输入另一个字符串:");
scanf("%s", str1);

printf("拼接两个字符串:%s\n", strcat(str, str1));
printf("第二个字符串复制到第一个字符串:%s\n", strcpy(str, str1));
printf("比较两个字符串是否相等:%d\n", strcmp(str, str1));
printf("将第二个字符串前3个字符拼接到第一个字符串中:%s\n", strncat(str, str1, 3));
printf("将字符串 \"123\" 前2个字符复制到第一个字符串中:%s\n", strncpy(str, "123", 2));
printf("比较两个字符串前6个字符是否相等:%d", strncmp(str, str1, 6));
return 0;
}

练习11-10

16

1
2
3
4
5
6
7
8
9
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*程序名:list0911.c*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

int strtoi(const char* nptr)
{
int tmp=0;
int flag;

if (*nptr == '-')
{
flag = 1;
nptr++;
}
else
flag = 0;

while (*nptr)
{

if (*nptr >= 0 || *nptr <= 9)
{
tmp = tmp * 10 +(*nptr - 0x30);
}
nptr++;
}

if (flag == 1)
return -tmp;
else
return tmp;
}


long strtol(const char* nptr)
{
long tmp = 0;
int flag;

if (*nptr == '-')
{
flag = 1;
nptr++;
}
else
flag = 0;

while (*nptr)
{

if (*nptr >= 0 || *nptr <= 9)
{
tmp = tmp * 10 + (*nptr - 0x30);
}
nptr++;
}

if (flag == 1)
return -tmp;
else
return tmp;
}

double strtof(const char* nptr)
{
int tmp = 0;
int flag;

if (*nptr == '-')
{
flag = 1;
nptr++;
}
else
flag = 0;

while (*nptr)
{

if (*nptr >= 0 || *nptr <= 9)
{
tmp = tmp * 10 + (*nptr - 0x30);
}
nptr++;
}

if (flag == 1)
return -tmp;
else
return tmp;
}

int main(void)
{
char str[128];
char str1[128];

printf("%d", strtoi("1234"));

return 0;
}

对于浮点数的转换有点麻烦,这里直接忽略。

  • 本文标题:C语言语法入门-字符串和指针
  • 本文作者:9unk
  • 创建时间:2023-07-12 15:21:00
  • 本文链接:https://9unkk.github.io/2023/07/12/c-yu-yan-yu-fa-ru-men-zi-fu-chuan-he-zhi-zhen/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!