字符,字符串(C语言)

字符

  • char 是整数类型,也是字符类型
  • 单引号表示的是字符字面量:
'a'
'1'
''// 这也是一个字符
  • %c 占位符 用来输出字符
	char a = 1; // 整数 1
	char b = '1'; // 字符 1
	
	printf("%d",a==b); 

输出

0

变量 a 和变量 b 的值并不想等。

	printf("%d\n",a); 
	printf("%d\n",b);

输出

1
49

得到变量 a 的值是 1 ;变量 b 的值是 49。

	char a,c;
	int b;
	
	scanf("%c",&a); // 输入的是字符 
	scanf("%d",&b); // 输入的是整数
	
	c = b;
	
	printf("%d\n",a); // 输出的是整数
	printf("%c\n",a);
	printf("%c\n",c); // 输出的是字符 

输入

1
49

输出

49
1
1

注意:
当变量是char 类型时,scanf中不能用 %d ,如果要使用 %d 需要使用 int 类型。
错误示例:

	char b;
	scanf("%d",&b); // 输入的是整数
	printf("%d\n",b); // 输出的是字符 

error 报错。

	if( 49 == '1'){
		printf("OK!");
	}

输出:

OK!

所以说,输入49和输入’1’是一样的。

字符串

构造一个字符数组

char word[] = {'H','e','l','l','o','!'};

这个字符数组不是字符串,因为不能执行字符串的相关运算。
构造真正的字符串

char word[] = {'H','e','l','l','o','!','\0'};

比字符数组多了 ‘\0’,表示的是整数值的0,使得其称为C语言的字符串

  • 以0(整数0)结尾的一串字符
    • 0或’\0’是一样的,但是和’0’不同
  • 0标志字符串的结束,但它不是字符串的一部分
    • 计算字符串长度的时候不包含这个0
  • 字符串以数组的形式存在,以数组或指针的形式访问
    • 更多的是以指针的形式
  • string.h 里有很多处理字符串的函数

字符串变量

*str = 'hello';
str[] = 'hello';
str[10] = 'hello';

以上三种都是定义字符串变量的方法。其中虽然hello有5个字母,但是由于结尾有’\0’,所以在数组中占据6个单元。

字符串常量

"Hello"
  • ”Hello"会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0.
char* s = "Hello, world!";

表示 s 是字符串。

能够通过数组的操作改变s中的某个值。

#include <stdio.h>


int main(void)
{
	char* s = "Hello, world!";
	s[0] = 'B';
	
	printf("Here! s[0] = %c \n",s[0]);
	
	return 0;

}

结果出错了。

新的程序测试

#include <stdio.h>


int main(void)
{
	int i = 0;
	char* s = "Hello, world!";
	// s[0] = 'B';
	char* s2 = "Hello, world!";
	printf("&i = %p \n",&i);
	printf("s = %p \n",s);
	printf("s2 = %p \n",s2);
	printf("Here! s[0] = %c \n",s[0]);
	
	return 0;

}

输出结果

&i = 000000000062FE0C
s = 0000000000404000
s2 = 0000000000404000
Here! s[0] = H

--------------------------------
Process exited after 0.005692 seconds with return value 0
请按任意键继续. . .

可以看到,对于初始化相同的字符串变量,它们的地址是相同的。而且,相对于 int 类型的变量,字符串数组的地址更小。

这个地址很小的位置里的数据是只读的,试图修改数据会报错。

  • s 是一个指针,初始化为指向一个字符串常量
  • 由于这个常量所在的地方,所以实际上 s 是 const char* s ,但由于历史原因,编译器不接受不带 const 的写法。
  • 试图对 s 所指的字符串做写入会出错。

如果要做字符串,并且可以修改的,应该使用数组来定义字符串。

char s[] = "Hello, world!";
#include <stdio.h>

int main(void)
{
	int i = 0;
	char* s = "Hello, world!";
	// s[0] = 'B';
	char* s2 = "Hello, world!";
	char s3[] = "Hello, world!";
	
	printf("&i = %p \n",&i);
	printf("s = %p \n",s);
	printf("s2 = %p \n",s2);
	printf("s3 = %p \n",s3);
	s3[0] = 'B';
	printf("Here! s3[0] = %c \n",s3[0]);
	
	return 0;
}

输出结果:

&i = 000000000062FE0C
s = 0000000000404000
s2 = 0000000000404000
s3 = 000000000062FDF0
Here! s3[0] = B

--------------------------------
Process exited after 0.00528 seconds with return value 0
请按任意键继续. . .

分析:
看到 s3 的地址很大,说明 s3 的数组在本地变量那里。

指针还是数组

当程序里面需要有字符串时,是写出指针还是字符串。

char *str = "Hello"; // 指针
char word[] = "Hello"; //数组
  • 数组:这个字符串在这里,作为本地变量空间自动被回收。
  • 指针:字符串不知道在哪里,用于处理参数,动态分配空间。

所以说,要构造字符串——数组;要处理字符串——指针。

** char* 是字符串吗?

  • 字符串可以表达为 char * 的形式
  • char* 不一定是字符串
  • char* 本意是指向字符的指针,可能指向的是字符的数组。就像int*
  • 只有 char* 所指的字符数组结尾有 0 ,才能说明它所指的是字符串。

字符串的赋值

	char* str1 = "Hello";
	char* str2;
	
	str2 = str1;
	
	printf("%p\n",str1);
	printf("%p\n",str2);

并没有产生新的字符串,而是将指针str2指向了str1的地址。

0000000000404000
0000000000404000

--------------------------------
Process exited after 0.004713 seconds with return value 0
请按任意键继续. . .

如果需要产生一个新的字符串,需要使用字符串函数。

字符串的输入输出

使用占位符 %s

  • scanf 读入一个单词(到空格、TAB、回车为止)
#include <stdio.h>

int main(void)
{
	char word[8];
	scanf("%s",word);
	printf("%s##\n",word);
	
	return 0;
}

输入:

hello world!

输出:

hello##

输出hello,没有读入空格,world也没有。如果程序里面有第二个scanf,则会读到 word。

	char word[8];
	char word2[8];
	scanf("%s",word);
	scanf("%s",word2);
	printf("%s##%s##\n",word,word2);

输入:

hello world!

输出:

hello##world!##

两次都没有读入 hello world!中的空格,因此这个空格是个分隔符。

  • scanf是不安全的,因为不知道要读入的内容的长度。
  • 改进: 在%s的%和s中间加数字,表明最多读入几个字符。这个数字应该比数组的大小小一。例如:%7s,因为对于字符串而言,还有最后的’\0’。

常见错误

  • 以为 char* 是字符串类型,定义了一个字符串类型的变量就可以直接使用了(×)
char* string;
scanf("%s",string);

这段代码是错误的,因为,char* 定义的是指针变量,是以后要存储某个变量的地址的。但是指针没有被初始化,本地变量是没有默认初始值的,原来内存里面有什么,这个指针变量就是什么值。

  • 改进: 指针需要初始化。

  • " " 表示空字符串。
char buffer[100]="";

等价于

buffer[0] == '\0';
  • 如果没有指定数组长度
char buffer[] = "";

这个数组的长度只有1。这样的buffer 数组里面放不下任何字符串。

字符串函数

C的标准库中的函数,头文件<string.h>。strlen、strcmp、strcpy、strcat、strchr、strstr

strlen

size_t strlen(const char* s)//const指strlen不会修改字符串。
  • 返回 s 的字符串长度(不包括结尾的0)

strcmp

compare。

int strcmp(const char* s1,const char* s2);

比较两个字符串,并且返回一个整数。

  • 0: s1 == s2
  • 1: s1 > s2
  • -1: s1 < s2
    不相等时,会给出差值。
s1 == s2 //表达的数组数组是否是相同的地址

strcpy

char* strcpy(char* restrict dst,const char* restrict src);
  • 把 src 的字符串拷贝到 dst
  • restrict 表明 src 和 dst 不重叠
  • 返回 dst

src 指向一个字符串,dst对应一个空间,将src的内容拷贝到dst中,包括结尾的0.

strcat

做连接

char* strcat(char* restrict s1,const char* restrict s2);
  • 把s2拷贝到s1的后面,(s1末尾的0会去掉),接成一个长的字符串
  • 返回s1
  • 注: s1必须有足够的空间

安全问题:

  • strcpy 和 strcat 可能目的地没有足够的空间

改进安全版本

char* strncpy(char* restrict dst,const char* restrict src, size_t n);
char* strncat(char* restrict s1,const char* restrict s2, size_t n);
int strncmp(const char* s1 , const char* s2, size_t n);

注: 多了一个n,并且指定多少空间。
strncmp是指定比较前几个字符。

字符串中找字符

char* strchr(const char* s,int c);
char* strchr(const char*s , int c);

返回 NULL 表示没有找到

总结:

  • C语言的字符串是以字符数组的形态存在的
  • 不能用运算符对字符串做运算
  • 通过数组的方式可以遍历字符串
  • 唯一特殊:字符串字面量可以用来初始化字符数组
  • 标准库提供了一系列字符串函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值