字符串是以空字符\0结尾的char类型数组。
字符数组和字符串
1.字符数组 %c
声明 char arr[5];
初始化 char arr[]={'h','e','l','l','o'}; //字符数组来的初始化
字符数组用单引号,用%c来作为单个字符的占位符
赋值 除了初始化不能直接赋值,只能遍历和函数赋值
字符数组的一般语法和其他数组的操作是相同的
2.字符串 %s
字符串是以空字符(\0)结尾的char类型数组。
'h','e','l','l','o' //字符
"hello\0" //字符串
char arry[]='h','e','l','l','o','\0'};
区分字符数组和字符串的区别 /0,/0是字符串的结束标志,%s读取字符串的时候在遇到/0的时候会自动结束。
字符串arry[10] ; //可以存放10个字符,只不过最后一个是'\0',所以只能存放我们需要的9个字符
处理单字符的两种函数getchar()和putchar()
字符串的输入函数
1.字符串的输入-fgets()函数
fgets()函数一共有三个参数
第一个参数,读入的字符串
第二个参数,读入字符串的最大值
第三个参数,读入字符串写入的文件, 如果读入从键盘输入的数据,则以stdin(标准输入)作为参数,该标识符定义在stdio.h中。
fgets()函数会将换行符也储存进字符串中。
我们通过一系列的操作来查找字符串中的换行符并把它替换掉
空字符('0')和空指针(NULL)的区别
空字符('\0')是用于标记C语言字符串末尾的字符,对应编码为0
空指针(NULL)有一个值,该值不会和任何数据的有效地址连接起来
空字符是整数类型,是一个字符,占1字节
空指针是指针类型,是一个地址,通常占4字节
字符串的输出(-fgets函数的好兄弟)-fputs()函数
fputs()函数通常与fgets()函数配对使用
fputs()函数的第1个参数是它要输出的字符串或字符串的地址,第2个参数指明它要写入的文件。如果要显示在计算机显示器上,应使用stdout(标准输出)作为该参数。
fputs函数的返回值返回指向char类型的指针。如果一切进行顺利,该函数返回的地址与传入的第 1 个参数相同。但是,如果函数读到文件结尾,它将返回一个特殊的指针:空指针(null pointer)。
2.get_s函数
get_s()函数和fgets()函数相类似,用一个参数限制读入的字符数。
get_s(word,longs)函数和fgets()函数的不同点
get_s()函数只从标准输入中读取数据,所以不需要第三个文件参数
如果get_s()读到换行符,丢弃它而不是储存它。
3.s_gets()函数
fputs()函数和puts()函数的不同点
puts()函数会给字符串添加换行符,当字符串遇到换行符时候,停止输出。
puts()函数针对于屏幕,fputs()是puts()函数针对于文件订制的版本。
gets()函数丢弃换行符
fgets()函数保留换行符
puts()函数添加换行符
fputs()函数不添加换行符
字符串的输出-puts()函数
1.和printf( )函数相同,puts( )函数也属于stdio.h系列的输入输出函数。
2.与printf( )函数不同的是,函数只显示字符串,并且自动在显示的字符串末尾加上换行符\n 。
3.只需要把要输出的字符串的地址作为参数传递给puts()函数即可。
4.puts()函数遇到空字符\n就停止输出。
结果
字符串面量,字符串常量
双引号括起来的内容被称为字符串面量,字符串面量和/0被存储在内存中
char greeting[] = "Hello, and"" how are" " you"
char greeting[] = "Hello, and how are you today!";
两个代码等价,字符串之间用空白间隔,C视其为连接起来的字符串面量。
字符串常量属于静态存储类别。函数中使用字符串常量,在函数中使用字符串面量,只会在内存中被存储一次。函数被调用多次。用双引号括起来的内容被视为指向该字符串存储位置的指针。类似于数组名作为指向该数组位置的指针,但是字符串面量被清除。
3.初始化和赋值的区别
初始化: 在定义的时候进行赋值
赋值:必须用for循环或者函数进行拷贝
4.字符串的使用 arr指向字符串的第一个字符
int arr[10]; arr指向arr[1]
char arr[10]; arr指向字符串的第一个字符
字符串数组和指针
输出结果
注意这段代码有三种形式的字符串 MSG ar[ ]数组 和指针 p
相同的字符串面量,但是数组的地址不同于其它两种。`
第一 p 和 MSG 的地址相同,而 ar 的地址不同。
第二 虽然字符串面量 "I love Huangyiding" 在两个 printf( ) 函数中出现了两次,但是编译器可以多次使用相同字面量储存在一处或者多处。
第三 静态数据使用内存和 ar 使用的动态内存不一样,不仅地址不同,特定编译器甚至使用不同的位数表示两种内存。
字符串数组和指针的区别
用数组存储一个字符串
用指针指向一个字符串两者有什么区别吗
输出结果
数组和指针的区别
虽然数组名是数组首元素的地址,
数组名是常量,右值。不能进行++运算
指针是变量,左值。可以进行++运算
附录:如果打算修改字符串,就不要用指针指向字符串面量
字符串数组
我们用指针和数组形式 分别写了两个字符串数组
结果
从某些方面看,book和bank字符串数组相似
book [1][2]表示数组中第二2个指针单元所指向的字符串第三个字符
bank[1][2]表示的数组中第二个字符串的第三个字符
book数组是一个含有5个指针的数组 char*book[5],[ ]优先级高于*
占用20字节
bank是一个5个字符串数组的数组
占用200字节
book中的指针指向初始化字符串面量的位置,存在静态内存
bank数组储存字符串面量的副本,存在动态内存。分为指针地址和字符串地址
二者区别
一个是规则矩形,一个是不规则矩形
5.字符串的函数 C标准库 <string.h>
5.1 strcpy函数:
我们把src所指向的字符串 拷贝 到dest中,str(string) cpy(copy)
char*strcpy(char *dest,const char*src) //src 源
中文占用两个字节
5.2 strncmp函数
比较两个字符串前n个字符,相同返回0,不同返回1
不同的情况下:比较e和h的ASCII值,e<h,返回-1,e>h,返回1。函数核心比较字符的ASCII值哪个比较大
接下来我们通过指针来自己写一个函数strcpy
反思:
函数的参数和返回值为char类型指针型
在我们函数调用的时候传递的实参是字符型常量?
我们自己写一个strncmp函数
结果
反思:
1.用for控制字符偏移,和字符自加
2.设置多个条件 if-esle if - else if ,注意区分函数块
3.for循环外的return0 ,如果前面第一个条件成立,直接return 0;
4. 如果前面的任意一个条件成立,执行一个return 1 后return 0不执行。因为函数只能执行一个return
其他函数
头文件<string.h>函数还定义了很短函数,在下面各个函数中 s和t为char*类型,c和n为int类型
strcat(char* s,char* t) 将 t 指向的字符串链接到 s 指向字符串的末尾
strncat(char* s,char* t,int n) 将 t 指向的字符串的前 n 个字符链接到 s 指向的字符串的末尾
strcmp(char* s ,char* t ) 将 s 指向的字符串和 t 指向的字符串进行比较,并返回一个 int值。
strncmp(char* s ,char* t ) 将 s 指向的字符串和t指向的字符串比较前 n 个字符,返 回 一 个int值
strcpy(char* s,char* t) 将 t 指向的字符串拷贝到 s 位置上
strncpy(char* s,char* t,int n) 将 t 指向的字符串的前 n 个字符拷贝到 s 位置上
strlen(char* s) 返回 s 指向的字符串的长度
strchr(char* s , int c ) s 指向的字符串中查找 c,若找到,则返回它指向第一次 出现位置的指针,否则返回 NULL
strrchar(char* s , int c)