一、字符串字面量
- 什么是字符串字面量?----字符串常量;
- 字符串常量怎么表示?--用一对双引号括起来的字符序列。例如:
"Hello man,Welcome to china !"
1.1 字符串字面量的延续
- 有时候,我们使用printf()函数来展示一段字符串字面量的时候,在编写代码的时候,一行是存放不下的,怎么办?这里有两种方式来处理。
1.在第一行字符串字面量结尾的地方采用字符\来结尾,(注意\后面不能再接任何字符)然后回车,在新的一行继续输入(必须从新一行的起始位置继续输入)
printf("Put a disk in drive A,then \
press any key to continue\n");
2.采用另外一对""开始新的一行,新的一行,不要求从起始位置输入。例如:
printf("Put a disk in drive A,then"
"press any key to continue\n");
显然,第二种表示方式看起来更加美观。
1.2 字符串字面量如何存储?
在C语言中,并没有单独为字符串定义一个数据类型出来,而是把字符串字面量作为字符数组来处理。假设当编译器在程序中遇到一个长度为n的字符串字面量时,它会为字符串字面量分配长度为n+1的内存空间。为什么是n+1的长度呢?因为最后一个字符是用来存储空字符的,也就是'\0',空字符用来标志字符串的末尾。
**既然字符串字面量时作为数组来存储的,那么编译器会把它看成是一个char * 类型的指针。那么是否可以认为当printf("abced")运行时,调用printf()函数,然后传递"abcde"的地址(就是指向字母a存储单元的指针)?
char *ch;
ch = "abced";//使指针ch指向"abcde"的首元素地址
char n = ch[3];
char m = "abcde"[1]; //将"abcde"下标为1的字符元素,赋值给字符变量m
printf("%c\n",n);
printf("%c\n",m);
通过编译运行可以发现,n的值现在为'e',m的值为'b'。由此可以看出,实际上字符串字面量在当做字符型数组来存储的时候,这个数组的名称,就是该字符串字面量本身。
为了验证是不是字符串末尾是以空字符结尾,可以把上述代码中的 ch n = ch[3]修改成
ch n = ch[5];编译后运行,结果就是一个空字符。
利用这个特性,我们可以做出一个简单的小功能函数,比如把0~15的整数转换成等价的十六进制的字符形式。
char digit_to_hex_char (int digit)
{
return "0123456789ABCDEF"[digit];//顺序千万别排错了
}
二、字符串变量
在第一部分我们知道,在C语言中,字符串是用一维数组来存储的。并且我们也知道,如果我们要存储n位长度的字符串,那么实际需要的空间长度是n+1。比如我们要存储20个字符,需要这样来申明 char ch[21];
2.1 字符串变量的初始化
char ch1[6] = "Hello";//方式一
char ch2[6] = {'H','e','l','l','o','\0'};//方式2
char ch3[] = "Hello,man !"; //方式3,这种情况下编译器自动计算长度
如果初始化式太短,不能填满字符串变量的时候,编译器会自动添加空字符。如果初始化式比字符串变量长呢?那么这对字符串就是不合规的,编译不能通过。
2.2 字符数组和字符指针
- 申明为字符数组时,可以修改存储在数组中的元素,当申明为字符指针,同时初始化指向一个字符串后,指针指向的是字符串字面量,当然,字符串字面量时不允许修改的,因为它是一个“常量”。
- 在申明为字符指针的时候,指针是一个变量,那么在程序执行期间指针可以重新指向其他字符串。如下图所示:
三、字符串的读与写
- 写字符串(显示到屏幕上)
采用printf()函数以及puts()函数
char str[] = "Are you ok?";
printf("%s\n",str);
//调用printf()函数,采用格式转换说明符%s来输出字符串,当然也可以采用%m.ns来控制显示的字符数量
printf("%.7s\n",str);
puts(str); //调用puts()函数写字符串
puts("I love you") ;
- 读字符串
1,可以使用scanf()函数实现,但是scanf()有一个缺陷,它会跳过第一个空白字符,然后开始录入,直到遇到下一个空白字符。
char str1[30];
printf("请输入29个字符: ");
scanf("%s",str1);
//调用scanf()函数来实现读入字符串,因为str1是数组,编译器会自动当做指针来处理,因此不用&(取地址符)
puts(str1);
如果我们输入:空格 hello 空格 you,boy ! 会发现,调用puts()函数的时候,只能写出hello。这是因为在hello之前的空格,scanf()函数自动跳过,从hello开始读,当读到hello后面的一个空格时,函数停止读入。
2.采用gets()函数实现字符串的读入
采用gets()函数读入字符串,不会跳过空白字符,直到遇到换行符为止。
printf("以下内容采用gets()函数实现字符串录入: ");
gets(str1);
puts(str1);
两种方案对比,显然采用gets()函数在读入字符串方面更加便捷,符合程序员的心理预期。但是两者都有个明显的缺陷,那就是,不会自动检测输入的字符是否超过,申明时,字符数组定义的长度。
3.利用一般数组赋值方法,采用循环结构来实现赋值。
int read_line(char str[],int n)
{
char ch;
int i = 0;
while ((ch = getchar()) != '\n') //遇到换行符后停止读入
if(i < n) //判断输入的字符个数是否超过数组长度,当条件为真时,读入的字符有效
str[i++] = ch ;
str[i] = '\0';
return i;
}
四、使用<string.h>中的函数
- strcpy() 字符串复制
函数原型 char *strcpy (char *s1, const char *s2); //把s2指向的字符串复制到s1指向的数组中。
//举例
char str1[30],str2[] = "EastMoney !";
strcpy(str1,"hello world !");//把字符串"hello world" 复制给str1
strcpy(str1,str2); //把str2复制给str1
- strcat()字符串拼接
函数原型: char *strcat (char *s1, const char *s2);把字符串s2的内容追加到字符串s1的末尾,并且返回字符串s1(指向结果字符串的指针);
- strcmp() 字符串比较
函数原型: int strcmp(const char *s1, const char *s2) ;比较的结果如下:
(1)字符串1==字符串2,返回0
(2)字符串1>字符串2,返回一个正整数
(3)字符串1<字符串2,返回一个负整数。
- strlen() 求字符串长度
函数原型 size_t strlen(const char *s) ;//size_t是定义在C函数库中的无符号整数类型(通常是unsigned int 或 unsigned long int)。