13.1 字符串字面量

  1. #include <stdio.h>
  2. int main()
  3. {
  4. printf("this is String")
  5. }

13.1.3 如何存储字符串字面量

如存储 “abc” 实际上就是存储
image.png

空字符串的存储
image.png

note

  1. 这里有一个需要了解的是,当我 printf 一个 “abc” 时,我传递的实际上是一个指针,而且是 a 的地址
  1. #include <stdio.h>
  2. int main()
  3. {
  4. char *p;
  5. p = "abc";
  6. printf("%c",p[2]);
  7. }
  8. // 输出
  9. c

13.2 字符串变量

假设需要变量存储 80 个字符,则需要申请 81 个字符的数组,最后一个用作空字符。

  1. int main()
  2. {
  3. char date1[8] = "June 14";
  4. // 等价于 char date1[8] = {'J','u','n','e',' ','1','4'};
  5. }

image.png

如果声明的字符数组比实际存储字符长,在内存中会是什么样呢

  1. char date1[9] = "June 14";

image.png

注意,不能声明一个长度小于(字符数量+空字符)

你也可以不指定长度,但编译器在编译时会自动确定。

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char date[] = "June 14";
  5. printf("%d",sizeof(date));
  6. }
  7. // 输出
  8. 8

13.2.2 字符数组与字符指针

注意,二者并不是等价的

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char date[] = "June 14";
  5. char *date1 = "June 14";
  6. }

字符数组可以操纵每一个字符元素,但字符指针不行,它的整个被当作一个整体来看待。

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char date[] = "June 14";
  5. char *date1 = "June 14";
  6. date[0] = 'h';
  7. printf("%c",date[0]);
  8. }
  9. // 输出,这样的操作只能在字符数组中出现
  10. h

13.3 字符串的读/写

13.3.1 使用 printf 或者 puts 来写字符串

printf 函数逐个写字符,遇到空字符才停止,如果空字符丢失,则会一直写,直到在内存中遇见空字符。

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char str[] = "Are we having fun yet?";
  5. printf("%s",str);
  6. }
  7. // 输出
  8. Are we having fun yet?

你可以通过 %.ms 来设置输出的字符串数量

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char str[] = "Are we having fun yet?";
  5. printf("%.6s",str);
  6. }
  7. // 输出
  8. Are we

你也可以用 puts 来输出

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char str[] = "Are we having fun yet?";
  5. puts(str);
  6. }
  7. // 输出
  8. Are we having fun yet?

13.3.2 使用 scanf 函数和 gets 函数读字符串

1. scanf 的使用
  1. 不需要在 str 前面添加 &,因为 str 是数组名,编译器自动把它当作指针处理
  2. scanf 会跳过开头的空格,且在遇到下一个空格的时候停止
  3. gets 不会跳过空格,而是原样输出,直到遇到换行符才停止
  1. #include <stdio.h>
  2. int main()
  3. {
  4. char str[10];
  5. printf("在这里开始输入:");
  6. scanf("%s",str);
  7. printf("输出刚才的内容:%s",str);
  8. }
  9. // 输出
  10. 在这里开始输入:To c, or not to c: that is the question
  11. 输出刚才的内容:To
  1. #include <stdio.h>
  2. int main()
  3. {
  4. char str[10];
  5. printf("在这里开始输入:");
  6. gets(str);
  7. printf("输出刚才的内容:%s",str);
  8. }
  9. // 输出
  10. 在这里开始输入:To c, or not to c: that is the question
  11. 输出刚才的内容:To c, or not to c: that is the question

13.3.3 逐个字符读字符串

scanf 和 gets 都有风险,自己编写一个函数读取字符

  1. #include <stdio.h>
  2. int read_line(char str[],int n);
  3. int main()
  4. {
  5. char str[10];
  6. read_line(str,10);
  7. printf("%s",str);
  8. }
  9. int read_line(char str[],int n)
  10. {
  11. char ch;
  12. int i=0;
  13. printf("在这里开始:");
  14. while((ch = getchar())!='\n')
  15. if(i<n)
  16. str[i++] = ch;
  17. str[i] = '\0';
  18. return i;
  19. }
  20. // 输出
  21. 在这里开始: abc_12,3
  22. abc_12,3

13.4 访问字符串中的字符

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char *s = "Are you OK?";
  5. int count = 0;
  6. for(;*s!='\0';s++)
  7. {
  8. if(*s ==' ')
  9. count++;
  10. }
  11. printf("%d\n",count);
  12. }
  13. // 输出
  14. 2

13.5 字符串内置函数

13.5.1 strcpy

char strcpy(char s1,char *s2)
将字符串 s2 的值赋给 s1,并返回 s1。记住,这里必须是将 s 声明为数组的形式,不能是指针的形式

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. // 这样就是错误的
  6. // char *s1;
  7. // char *s2 = "this is s2";
  8. char s1[100];
  9. char s2[] = "this is s2";
  10. strcpy(s1,s2);
  11. printf("%s\n",s1);
  12. }
  13. // 输出
  14. this is s2

13.5.2 strcat

追加 s2 到 s1 的后面

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char s1[] = "this is s1";
  6. char s2[] = "this is s2";
  7. strcat(s1,s2);
  8. printf("%s\n",s1);
  9. }
  10. // 输出
  11. this is s1this is s2

13.5.3 strcmp

比较两个字符串的大小。
比较原则:

  1. 长度相同,看某个字符的 ascll 码值
  2. 长度不同,长度短的小
  3. 如果长度不同,存在字符不同,优先比较字符
  4. 小于返回 -1,等于返回 0,大于返回 1
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char s1[] = "this is s1";
  6. char s2[] = "this is s2";
  7. printf("%d\n",strcmp(s1,s2));
  8. }
  9. // 输出
  10. -1
  11. #include <stdio.h>
  12. #include <string.h>
  13. int main()
  14. {
  15. char s1[] = "this is";
  16. char s2[] = "this is s2";
  17. printf("%d\n",strcmp(s1,s2));
  18. }
  19. // 输出
  20. -1
  21. #include <stdio.h>
  22. #include <string.h>
  23. int main()
  24. {
  25. char s1[] = "this iz";
  26. char s2[] = "this is s2";
  27. printf("%d\n",strcmp(s1,s2));
  28. }
  29. // 输出
  30. 1

13.5.4 strlen

计算字符串长度

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char s1[] = "this iz";
  6. char s2[] = "this is s2";
  7. printf("%d\n",strcmp(s1,s2));
  8. }
  9. // 输出
  10. 7

13.7 字符串数组

如何存储字符串数组?
一个简单的浪费的方式是建立二维数组

  1. char str[][8] = {"Mercury","Venus","Earth",
  2. "Mars","Jupi ter","Saturn",
  3. "Uranus","Neptune","pluto"};

image.png
图示就是这样,可以看出很浪费空间,毕竟不是每个字符都占用了所有格子

另一种更好的方式就是建立指向字符串的指针数组

  1. char *str[] = {"Mercury","Venus","Earth",
  2. "Mars","Jupi ter","Saturn",
  3. "Uranus","Neptune","pluto"};

其图示如下:
image.png