字符串

  • 字符串是以字符数组的方式存在的

  • 不能对其用运算符做运算

  • 通过数组的方式可以遍历字符串

  • 可以通过字符串常量去初始化字符数组

字符数组

  • 以0结尾的一串字符

  • 0标志字符串的结束,但它不是字符串的一部分,计算字符串长度的时候不包含这个0

  • 字符串以数组的形式存在,以数组或指针的形式访问

格式: char hello[] = {'H','e','l','l','o','!','\0'};

每个字符使用单引号

结尾的'\0'可以写成0,但是不能写成’0’

对应的分别是

元素
hello[0] H
hello[1] e
hello[2] l
hello[3] l
hello[4] o
hello[5] !
hello[6] \0

字符串变量

指针变量 char *string = "Hello";

字符数组 char word[] = "Hello";

字符数组char line[6] = "Hello"会占据6个字节的空间

字符数组在本地存放,本地变量的空间会自动回收

指针用来处理参数和不可修改的值,以及动态分配空间

当需要构建一个字符串时使用数组的方式,当处理字符串时用指针

char *

字符串可以表达成char*的形式,但char* 不一定是字符串,只有当它所指的字符数组的结尾处是0才能确定它指向的是字符串

字符串常量

“Hello”就是字面量/常量,它会被编译器变成一个字符数组放在某处,这个数组的长度是字符+1,在结尾处还有个表示结束的0

两个相邻的字符串常量会被自动连接起来

当使用指针去定义字符串的时候,字符串常量是只读的,无法被修改 const char *s = "Hello,World";

当有第二个指针变量指向了已有的常量时,它们的地址是一模一样的

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main() {
char *s = "Hello,Wolrd";
char *s2 = "Hello,Wolrd";
printf("s = %p\n", s); // s = 0x10e9c2f92
printf("s2 = %p", s2); // s2 = 0x10e9c2f92
return 0;
}

如果需要修改字符串中的常量,需要使用字符数组去定义字符串char word = "Hello,Wolrd";

输入输出

将指针变量a字符串赋值给另一个指针b的时候,是将a地址指向了b,将它们两个链接起来了,对b做的任何操作都会映射到a

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main() {
char *a = "Hello,Wolrd";
char *b = a;
printf("a = %s\n", a); // a = Hello,World
printf("a = %p\n", a); // a = 0x104f2af82
printf("b = %p\n", b); // b = 0x104f2af82
printf("b = %s", b); // b = Hello,World
return 0;
}

scanf作为字符串输入时,会读入一个单词(一串字符以空格和tab作为结束)

限制scanf的长度为12scanf ("%12s, a");当超过12个字符后,越界的部分会被裁掉,当有连续的字符串时,会被挤到下个scanf

定义指针类型的字符串时,需要对变量进行初始化为0

空字符串

char a[10] = ""意味着这是一个空的字符串,a[0] == ‘\0’

char a[] = ""意味着这个字符串的长度只有1,而a[0]就是’\0’,所以你放不下任何东西

程序参数

main函数的参数有两个参数,前者a是告诉后者b数组中有多少个元素

后者b是在执行时可以带上的任何字符

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main(int a, char *b[]) {
int i;
for ( i = 0; i < a; i++ ) {
printf("%d:%s\n", i, b[i]);
}
return 0;
}

输入输出

putchar

int putchar(int x)

把一个字符输出在标准输出上

当输出EOF( -1 )代表输出失败

参数是int类型,但只能接收一个字符,返回类型也是in

getchar

不需要参数int getchar(void)

返回从标准输入读取到的字符

返回类型是int,目的是为了返回EOF( -1 )表示标准输入结束

当程序获取到EOF状态,即当用户使用Ctrl + D中断运行,就会在标准输出得到EOF结束程序运行

06-07_20:11

字符串函数

在头文件string.h中有很多函数可以调用

strlen (string length)

返回字符串的长度(不包含结尾的\0)size_t strlen(const char *s);

不会修改参数表中的参数

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "string.h"

int main() {
char s[] = "Hello";
printf("sizeof = %lu\n", sizeof(s)); // sizeof = 6
printf("strlen = %lu\n", strlen(s)); // strlen = 5
return 0;
}

仿照strlen函数写一个自己的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include "string.h"

int my( const char *s ) {
int time = 0;
while ( s[time] != '\0' ) {
time++;
}
return time;
}
int main() {
char s[] = "Hello";
printf("sizeof = %lu\n", sizeof(s)); // sizeof = 6
printf("strlen = %lu\n", my(s)); // strlen = 5
return 0;
}
strcmp (string compare)

对比两个字符串的大小,同样不会修改字符串int strcmp(const char *s1,const char *s2)

前者比较后者,前者与后者相同则返回0,前者小于后者则结果小于0,前者大于后者则结果大于0

不相等的结果取决于等于两者之间的差值,按照ASCII表中字符的顺序计算

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "string.h"

int main() {
char s1[] = "abc";
char s2[] = "abc";
printf("%d", strcmp(s1,s2)); // 0
return 0;
}

仿照strcmp函数写一个自己的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include "string.h"

int my(const char *s1,const char *s2){
while ( *s1 == *s2 && *s1 != '\0' ){
s1++;
s2++;
}
return *s1 - *s2;
}
int main() {
char s1[] = "abc";
char s2[] = "abc";
printf("%d", my(s1,s2)); // 0
return 0;
}
strcpy (string copy)

char *strcpy(char *restrict s1,const char *restrict s2)将后者的内容拷贝到前者

restrict表示这两个字符串在地址中没有重叠部分

strcpy具有返回值,能够继续参与代码的其他运算,返回值是前者

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "string.h"

int main() {
char s1[] = "123";
char s2[] = "abc";
printf("s1 = %s", strcpy(s1, s2)); // abc
return 0;
}
strcat (concatenate string)

char *strcat(char *restrict s1,const char *restrict s2)把后者连接到前者的后面,拼凑成一个字符串

restrict表示这两个字符串在地址中没有重叠部分

返回值是s1,在完成拼凑的这个操作时,得确保s1的空间是足够容纳s2的内容

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "string.h"

int main() {
char s1[12] = "Hello,";
char s2[12] = "World";
printf("s1 = %s", strcat(s1,s2)); // Hello,World
return 0;
}
strchr (locate character in string)

char *strchr(const char *s, int c);返回一个指针,指向变量c第一次出现的位置,自左向右寻找

char *strrchr(const char *s, int c);返回一个指针,指向变量c第一次出现的位置,自右向左寻找

当返回Null时表示没有找到,非0的值表示寻找到了,并返回指针

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "string.h"

int main() {
char s[] = "11223344";
char *p = strchr(s, '2'); // 223344
printf("%s", p);
return 0;
}
定位第二个相同字符
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "string.h"

int main() {
char s[] = "11223344";
char *p = strchr(s, '2'); // 223344
p = strchr(p + 1, '2'); // 23344
printf("%s", p);
return 0;
}
反向定位

第一个2开始算作p[0]以此类推

首先将p[0]的值备份一下,然后让它变成\0代表结束

动态分配一个临时的变量t去保存字符串s的值,也就是11

t = | 1 | 1 | \0 | 2 | 3 | 3 | 4 | 4 | \0 |

再恢复*p的值

s = | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | \0 |

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include "string.h"
#include "stdlib.h"
int main() {
char s[] = "11223344";
char *p = strchr(s, '2'); // 223344
char c = *p; // char c = p[0] = 2; 备份*p
*p = '\0'; // p[0] = '\0'
char *t = (char*)malloc(strlen((s)+1));
strcpy(t, s); // 将s的值拷贝到t中
*p = c; // 恢复*p
printf("%s", t);
free(t); // 释放临时变量t的空间
return 0;
}
strstr (locate a substring in a string)

char *strstr(const char *s1, const char *s2);从字符串s2中定位s1的内容,并返回一个指针

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "string.h"

int main() {
char s1[10] = "11223344";
char s2[10] = "22";
char *p = strstr(s1,s2);
printf("%s", p); // 223344
return 0;
}

char *strcasestr(const char *s1, const char *s2);从字符串s2中定位s1的内容忽略大小写,并返回一个指针

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "string.h"

int main() {
char s1[10] = "aabbcdDee";
char s2[10] = "Dd";
char *p = strcasestr(s1,s2);
printf("%s", p); // dDee
return 0;
}

char *strnstr(const char *s1, const char *s2, size_t 3);仅从3个长度的字符串s2中定位s1的内容,并返回一个指针,当超过3个长度会返回null

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "string.h"

int main() {
char s1[10] = "123456789";
char s2[10] = "5";
char *p = strnstr(s1,s2,7); // 长度可以为7
printf("%s", p); // 56789
return 0;
}
限制字符串数量
strncpy

限制拷贝的最大字符数为12

char *strncpy(char *restrict s1,const char *restrict s2,size_t n); – > strncpy(s1,s2,12);

strncat

限制能将后者连接到前者的最大字符数为12

char *strncat(char *restrict s1,const char *restrict s2,size_t n); –> strncat (s1,s2,12);

strncmp

限制仅对比开头的三个字符

int strncmp(const char *s1,const char *s2,size_t n); –> strncmp(s1,s2,3)

评论