13.1 字符串字面量
#include <stdio.h>int main(){printf("this is String")}
13.1.3 如何存储字符串字面量
如存储 “abc” 实际上就是存储
空字符串的存储
note
- 这里有一个需要了解的是,当我 printf 一个 “abc” 时,我传递的实际上是一个指针,而且是 a 的地址
#include <stdio.h>int main(){char *p;p = "abc";printf("%c",p[2]);}// 输出c
13.2 字符串变量
假设需要变量存储 80 个字符,则需要申请 81 个字符的数组,最后一个用作空字符。
int main(){char date1[8] = "June 14";// 等价于 char date1[8] = {'J','u','n','e',' ','1','4'};}

如果声明的字符数组比实际存储字符长,在内存中会是什么样呢
char date1[9] = "June 14";

注意,不能声明一个长度小于(字符数量+空字符)
你也可以不指定长度,但编译器在编译时会自动确定。
#include <stdio.h>int main(){char date[] = "June 14";printf("%d",sizeof(date));}// 输出8
13.2.2 字符数组与字符指针
注意,二者并不是等价的
#include <stdio.h>int main(){char date[] = "June 14";char *date1 = "June 14";}
字符数组可以操纵每一个字符元素,但字符指针不行,它的整个被当作一个整体来看待。
#include <stdio.h>int main(){char date[] = "June 14";char *date1 = "June 14";date[0] = 'h';printf("%c",date[0]);}// 输出,这样的操作只能在字符数组中出现h
13.3 字符串的读/写
13.3.1 使用 printf 或者 puts 来写字符串
printf 函数逐个写字符,遇到空字符才停止,如果空字符丢失,则会一直写,直到在内存中遇见空字符。
#include <stdio.h>int main(){char str[] = "Are we having fun yet?";printf("%s",str);}// 输出Are we having fun yet?
你可以通过 %.ms 来设置输出的字符串数量
#include <stdio.h>int main(){char str[] = "Are we having fun yet?";printf("%.6s",str);}// 输出Are we
你也可以用 puts 来输出
#include <stdio.h>int main(){char str[] = "Are we having fun yet?";puts(str);}// 输出Are we having fun yet?
13.3.2 使用 scanf 函数和 gets 函数读字符串
1. scanf 的使用
- 不需要在 str 前面添加 &,因为 str 是数组名,编译器自动把它当作指针处理
- scanf 会跳过开头的空格,且在遇到下一个空格的时候停止
- gets 不会跳过空格,而是原样输出,直到遇到换行符才停止
#include <stdio.h>int main(){char str[10];printf("在这里开始输入:");scanf("%s",str);printf("输出刚才的内容:%s",str);}// 输出在这里开始输入:To c, or not to c: that is the question输出刚才的内容:To
#include <stdio.h>int main(){char str[10];printf("在这里开始输入:");gets(str);printf("输出刚才的内容:%s",str);}// 输出在这里开始输入:To c, or not to c: that is the question输出刚才的内容:To c, or not to c: that is the question
13.3.3 逐个字符读字符串
scanf 和 gets 都有风险,自己编写一个函数读取字符
#include <stdio.h>int read_line(char str[],int n);int main(){char str[10];read_line(str,10);printf("%s",str);}int read_line(char str[],int n){char ch;int i=0;printf("在这里开始:");while((ch = getchar())!='\n')if(i<n)str[i++] = ch;str[i] = '\0';return i;}// 输出在这里开始: abc_12,3abc_12,3
13.4 访问字符串中的字符
#include <stdio.h>int main(){char *s = "Are you OK?";int count = 0;for(;*s!='\0';s++){if(*s ==' ')count++;}printf("%d\n",count);}// 输出2
13.5 字符串内置函数
13.5.1 strcpy
char strcpy(char s1,char *s2)
将字符串 s2 的值赋给 s1,并返回 s1。记住,这里必须是将 s 声明为数组的形式,不能是指针的形式
#include <stdio.h>#include <string.h>int main(){// 这样就是错误的// char *s1;// char *s2 = "this is s2";char s1[100];char s2[] = "this is s2";strcpy(s1,s2);printf("%s\n",s1);}// 输出this is s2
13.5.2 strcat
追加 s2 到 s1 的后面
#include <stdio.h>#include <string.h>int main(){char s1[] = "this is s1";char s2[] = "this is s2";strcat(s1,s2);printf("%s\n",s1);}// 输出this is s1this is s2
13.5.3 strcmp
比较两个字符串的大小。
比较原则:
- 长度相同,看某个字符的 ascll 码值
- 长度不同,长度短的小
- 如果长度不同,存在字符不同,优先比较字符
- 小于返回 -1,等于返回 0,大于返回 1
#include <stdio.h>#include <string.h>int main(){char s1[] = "this is s1";char s2[] = "this is s2";printf("%d\n",strcmp(s1,s2));}// 输出-1#include <stdio.h>#include <string.h>int main(){char s1[] = "this is";char s2[] = "this is s2";printf("%d\n",strcmp(s1,s2));}// 输出-1#include <stdio.h>#include <string.h>int main(){char s1[] = "this iz";char s2[] = "this is s2";printf("%d\n",strcmp(s1,s2));}// 输出1
13.5.4 strlen
计算字符串长度
#include <stdio.h>#include <string.h>int main(){char s1[] = "this iz";char s2[] = "this is s2";printf("%d\n",strcmp(s1,s2));}// 输出7
13.7 字符串数组
如何存储字符串数组?
一个简单的浪费的方式是建立二维数组
char str[][8] = {"Mercury","Venus","Earth","Mars","Jupi ter","Saturn","Uranus","Neptune","pluto"};

图示就是这样,可以看出很浪费空间,毕竟不是每个字符都占用了所有格子
另一种更好的方式就是建立指向字符串的指针数组
char *str[] = {"Mercury","Venus","Earth","Mars","Jupi ter","Saturn","Uranus","Neptune","pluto"};
其图示如下:
