0x01 字符串字面值

字符串是所有语言中最重要的类型之一,而C语言没有直接定义 String 类型
C语言中可以用字面值,字符数组和字符指针表示字符串,字符串字面值用双引号括起来

1
2
3
4
5
//可以延续字符串字面量
"I am string \
and go on."

"a string" "another string"

字符串以 “\0” 结束,编译器会把字面量看成是 char *类型的指针
字符串字面量也叫字符产量,值相同的字面值内存地址是一样的

0x02 字符数组

在C语言中,字符串由一维数组存储,但必需在结尾加 “\0” 没有 “\0” 的字符数组不是字符串
char arr[]; 可以代表字符串类型的变量(数组)
char 数组方式的字符串其值可以改变,但char数组地址是不可以改变

1
2
3
//初始化字符串变量
char data[8] = "July 10"; //包括 \0
char data[]= "July 10";

0x03 字符指针

char *str (字符指针)可以代表字符串类型的变量

1
2
3
4
char *data = "July 10";

char data[8] = "July 10";
char *data2 = data; //数组本身就是地址

char * 本身是一个地址,即可以指向字面值,也可以指向 char 数组
当 char * 指向字面值时,其值不可改变,当 char * 指向数组时,其地址可以改变

0x04 字符串的输入输出

输入:
scanf();
      scanf(“%s”,str); //str作为一个字符数组或者字符指针,本身就是一个地址,因此不需要在加 &
scanf_s();
      scanf_s(“%s”,str,10); //在原本scanf的基础上增加了安全性
gets();
      gets(str); //函数在 ISO/IEC 9899 2011(C11)标准中被移除

输出:
printf();
      printf(“%s\n”,str);
puts();
      puts(str);

scanf 永远不会读入空白符,而会跳过。换行、空格、制表等空白符会使 scanf 结束
scanf 和 puts 读入字符串时无法判断数组是否填满,可以使用 %ns 代替 %s 使用 scanf 更安全

0x05 字符串函数库

使用以下字符串函数,需要包含头文件 string.h

strcpy 和 strncpy
函数原型:char *strcpy(char* dest, const char *src);
功能:把从 src 地址开始且含有 NULL 结束符的字符串复制到以 dest 开始的地址空间
说明:src 和dest所指内存区域不可以重叠且 dest 必须有足够的空间来容纳 src 的字符串
返回值:返回指向 dest 的指针

strncpy 是部分复制
函数原型:char *strncpy(char *dest, const char *src, int n)

1
2
3
//demo
strcpy(p_str1,p_str);
strncpy(p_str1,p_str,10);

strlen 和 strcat
函数原型:unsigned int strlen(char *s);
功能:计算字符串 s 的长度,不包括 “\0”
返回:返回 s 的长度

函数原型:extern char *strcat(char *dest, const char *src);
功能:把 src 所指字符串添加到 dest 结尾处 (覆盖 dest 结尾处的“\0”),并添加“\0”
说明:src 和 dest 所指内存区域不可以重叠且 dest 必须有足够的空间来容纳 src 的字符串
返回:返回执行 dest 的指针

1
2
3
//demo
strlen(p_str);
strcat(p_str,p_str1);

strcmp 和 strncmp
函数原型:extern int strcmp(const char *s1,const char *s2);
功能:比较两个字符串是否相等或者比较大小
说明:
      若 s1 == s2 ,则返回零
      若 s1 > s2 ,则返回正数
      若 s1 < s2 ,则返回负数

函数原型:int strncmp(const char *str1, const char *str2, size_t num );
功能:比较字符串前 num 字符是否相等或者比较大小

1
2
3
//demo
strcmp(s1,s2);
strncmp(s1,s2,3);

memset
函数原型:void *memset(void *s, int ch, size_t n);
功能:将 s 所指向的某一块内存中的后 n 个字节的内容全部设置为 ch 指定的 ASCII 值
说明:
      第一个值为指定的内存地址,块的大小由第三个参数指定
      这个函数通常为新申请的内存做初始化工作
返回:返回 s

1
memset(buffer,0,sizeof(char)*4);  //对字符数组 buffer 前4个字节置零

strstr
函数原型:char *strstr(const char *haystack, const char *needle)
功能:在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 ‘\0’。
返回:找到返回在 haystack 中第一次出现 needle 字符串的位置,找不到返回 NULL

1
strstr("abcwww","www");  //返回www

不需要包含 string.h 头文件

sprintf
函数原型:int sprintf(char *str, const char *format, …)
功能:把多个数组按照格式拼凑成字符串记录到字符数组里

1
sprintf(str,"%d %g %c",45,4.5f,'c');

sscanf
函数原型:int sscanf(const char *str, const char *format, …)
功能:从字符串里获得多个数值并记录到存储区

1
sscanf("3.2 3 T","%g%d%c",&f,&d,&c);

需要包含 stdlib.h 头文件

atoi:把字符串开头的整数部分转换成整数类型

atof:把字符串开头的浮点数转换成双精度类型

1
2
number = atoi(str);
number1 = atof(str);

fgets
函数原型:char *fgets(char *str, int n, FILE *stream)
功能:可以把键盘输入的东西记录到字符数组里,同scanf
说明:
      第一个参数:数组名称
      第二个参数:数组存储区个数
      第三个参数:指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流,如用 stdio 则表示键盘

1
fgets(str,10,stdio);

注:
1.scanf 读数时,空格后面的内容不会读,但是 fgets 会.
2.如果输入的内容不能把数组充满就把最后输入的换行字符(‘\n’)也放到数组里
3.每次使用fgets函数从键盘得到字符串以后都应该清理输入缓冲区里可能存在的多余数据

1
2
3
4
5
fgets(str, 10, stdin);
if (strlen(str) == 9 && str[8] != '\n') {
scanf("%*[^\n]");
scanf("%*c");
}