初识C语言(二)


本章简单字符串、转义字符、选择语句、循环语句、函数和数组。

字符串

在C语言中,有没有字符串类型?

int main()
{
	//char - 字符类型
	//'a'
	//'x'
	
	//字符串类型?
	"abcdef";//字符串字面值
	
	//字符串存储在字符数组中
	//使用字符串"abcdef"来初始化字符数组ch
	char ch[10] = "abcdef";//放进去7个字符,剩下三个字符默认放'\0'
	
	//字符串的末尾隐藏了一个'\0'
	return 0;
}

在这里插入图片描述
开启监视窗口,我们会发现字符串“abcdef”存入字符数组中,结尾会有一个’\0’,而ch[7],ch[8],ch[9]的’\0’是初始化时,自动放入的。

注意区别以下3种写法:

int main()
{
	char ch1[] = {'a','b','c','d','e','f'};
	printf("%s\n",ch1);

	char ch2[] = "abcdef";
	printf("%s\n",ch2);

	char ch3[] = { 'a','b','c','d','e','f','\0'};
	printf("%s\n", ch2);

	return 0;
}

在这里插入图片描述

字符串字面量

首先介绍一下字符串字面量,像’‘hello world’‘,’‘ABC’'这些用双引号引起来的一串字符称为字符串字面量

在字符串字面量的末尾会被加上一个null字符,该字符的值为0,用八进制转义字符表示null字符就是’\0’,null字符的每一位都是0,若不用字符常量,而用整数表示就是0。

所以字符串字面量’‘ABC’'实际占用了4个字符的内存空间,如下图所示:
在这里插入图片描述
而双引号中,没有任何字符的字符串字面量’‘’'表示的就是null字符:
在这里插入图片描述

字符串字面量的大小

通过以下程序分别显示三个字符串字面量的大小,来确认字符串字面量的末尾被加上了null字符,这三个字符串字面量在内存中的存储形式如下图所示:
在这里插入图片描述

int main()
{
	//字符串字面量的大小
	printf("sizeof(\"123\")       = %u\n",(unsigned)sizeof("123"));//4
	printf("sizeof(\"AB\\tC\")    = %u\n",(unsigned)sizeof("AB\tC"));//5
	printf("sizeof(\"abc\\0def\") = %u\n",(unsigned)sizeof("abc\0def"));//8
	return 0;
}

sizeof关键字是计算变量/类型所创建变量所占内存的大小(单位是字节),运行程序发现,sizeof(“123”)是4,sizeof(“AB\tC”)是5,sizeof(“abc\0def”)是8,表明字符串字面量’‘abc\0def’‘中间的null字符’\0’被忽略,而在末尾加上一个null字符。

int main()
{
	printf("%zu\n",sizeof("abcedfg\0\0\0\0ahucd"));//17
	printf("%s\n", "abcedfg\0\0\0\0ahucd");//abcdefg
	printf("%zu\n", strlen("abcedfg\0\0\0\0ahucd"));//7
}

注意:字符串字面量"AB\tC"中的’\t’表面上是两个字符,实际上是表示水平制表的转义字符,所以算作一个字符。

下面来讲讲字符串字面量的特性。

(1)具有静态生命周期

如下函数:

void func()
{
	puts("ABCD");
	puts("ABCD");
}

该函数显示两次字符串字面量’‘ABCD’‘,所以调用该函数时,必须将字符串字面量’‘ABCD’‘传入puts函数,所以字符串字面量’‘ABCD’'就必须在程序的整个生命周期内都可以使用,所以字符串字面量自然就具有了静态生命周期。字符串字面量存储在内存的常量区,是不可以被修改的。

(2)对于同一个字符串字面量,不同的编译器的处理方式不同

对于上面的func函数中的两个相同的字符串字量’‘ABCD’',如果看成是同一个字符串字面量,那么就能减少内存空间,具体内容可查阅所用的编译器说明文档。

字符串

C语言没有字符串类型?C语言怎么存储字符串?

答案:C语言没有字符串类型,但是可以存储字符串,可以使用字符数组进行存储。例如要保存字符串’‘ABC’‘,数组元素必须按照顺序存储’A’ 、‘B’、 ‘C’、‘\0’。字符串是以字符数组的形式实现,其结束标志是首次出现的null字符(‘\0’)。

%s :打印字符串,'\0’是字符串的结束标志,不算作字符串的内容。

int main()
{
	char arr1[] = "hello world";
	char arr2[] = {'h','e','l','l','o','w','o','r','l','d'};
	char arr3[] = { 'h','e','l','l','o','w','o','r','l','d' ,'\0'};

	printf("%s\n",arr1);//hello world
	printf("%s\n",arr2);//随机值
	printf("%s\n",arr3);//hello world
	return 0;
}

因为字符串的结束标志是字符’\0’,对于数组arr1,将字符串字面值"hello world"存入数组arr1中(字符串字面值本身是带有一个结束标志’\0’的),所以以%s形式打印arr1,结果是hello world;对于arr2,以%s形式打印,并不知道字符串结束标志’\0’在什么位置,所以结果是随机值;对于arr3,同arr1.

字符串的长度

字符串的结束标志是一个’\0’的转义字符,在计算字符串长度的时候’\0’(第一个’\0’)是结束标志,不算作字符串的内容】

#include <string.h>
int main()
{
	//保存字符串
	char str[4];
	str[0] = 'A';
	str[1] = 'B';
	str[2] = 'C';
	str[3] = '\0';
	printf("字符串str为%s\n",str);//ABC
	printf("字符串长度为%d\n",strlen(str));//3
	printf("字符串str的大小为%d\n",sizeof(str));//4
	return 0;
}

strlen函数计算字符串的长度,不包含’\0’,sizeof关键字计算变量的大小(占用内存的大小,单位是字节)。

**注:**字符串字面量的中间可以有null字符,但是要区分,字符串字面量’‘ABC’‘是字符串,但是字符串字面量’‘AB\0CD’'不是字符串。

int main()
{
	printf("%s\n","123");//123
	printf("%s\n","AB\tC");//AB    C
	printf("%s\n","abc\0def");//abc
	return 0;
}

转义字符

这里简单介绍几个常见的转义字符。所谓转义字符就是转变字符的意思。
在这里插入图片描述

int main()
{
	//\n   - 换行
	printf("abc\n");

	//\t   - 水平制表符 -tab键
	printf("abc\tdef");

	//\ddd   - 表示1-3个八进制的数字
	//ddd的8进制数字转换成10进制后的值,作为ASCII码值所代表的字符
	printf("C:\test\32\test.c\n");
	
	printf("%d\n",strlen("C:\test\32\test.c\n"));//14
	//8进制没有8
	printf("%d\n",strlen("C:\test\328\test.c"));//14
	
	//\xdd  - 表示两位16进制数字
	printf("%d\n",strlen("C:\test\x28\test.c"));//13
	
	//在字符串里面打印"
	printf("\"");
	
	
	printf("%c\n", '\32');
	printf("%c\n", '\141');//8进制141---10进制  97  ----字符'a'
	//\ddd   ddd的8进制数字转换成10进制的值,作为ASCII码的值代表的字符
	printf("%c\n",'\065');//\065 - 10进制的53,对应字符'5'
	printf("%d\n", '\x67');//103
	return 0;
}

注释

  1. 代码中有不需要的代码可以直接删除,也可以注释掉;
  2. 代码中有些代码比较难懂,可以加一下注释文字。
int Add(int x, int y)
{
	return x + y;
}

/*C语言风格注释
int Mul(int x, int y)
{
  return x*y;
}
*/

int main()
{
	//C++注释风格
	//int a = 10;
	//int b = 20; 
	//调用Add函数
	printf("%d\n", Add(1, 2));
	return 0;
}

注释有两种风格:
C语言风格的注释 /xxxxxx/
缺陷:不能嵌套注释

C++风格的注释 //xxxxxxxx
可以注释一行也可以注释多行

注释代码快捷键:ctrl+k,ctrl+c
取消注释快捷键:ctrl+k,ctrl+u

选择语句

程序并不总是执行相同的处理。可能在A条件下,执行B处理,在C条件下,执行D处理;程序通过条件判断来选择性的执行不同的处理,比如,今天下雨,出门就需要带伞,今天不下雨,出门就不需要带伞;努力学习,等到毕业就能找到一份好的工作,不努力学习,毕业就找不到好工作,等等。

#include <stdio.h>
int main()
{
  int coding = 0;
  printf("你会坚持每天敲代码吗?(选择1 or 0):>");
  scanf("%d", &coding);
  if(coding == 1)
  {
   	  prinf("坚持,你会有好offer\n");
  }
  else
  {
   	  printf("放弃,找不到好工作,回家种田\n");
  }
  return 0;
}

if(表达式)
语句

这样的语句称为if语句,首先判断表达式的值,如果结果不为0则执行相应的语句
在这里插入图片描述

if(表达式) 语句1 else 语句2
在这里插入图片描述

判断一个数是奇数还是偶数

#include <stdio.h>
int main()
{
	int num; = 0;
	printf("请输入一个整数:");
	scanf("%d",&num);
	if(0 == num%2)
	{
		puts("输入的是偶数.");
	}else
	{
		puts("输入的是奇数。");
	}
	return 0;
}

switch语句

switch(整型变量)
{
case 整型常量表达式1;
	语句1;
	break;
case 整型常量表达式2:
	语句2;
	break;
}
int main() {
	int day = 0;
	scanf("%d",&day);
	switch (day)
	{
	case 1:
		printf("星期一\n");
		break;
	case 2:
		printf("星期二\n");
		break;
	case 3:
		printf("星期三\n");
		break;
	case 4:
		printf("星期四\n");
		break;
	case 5:
		printf("星期五\n");
		break;
	case 6:
		printf("星期六\n");
		break;
	case 7:
		printf("星期天\n");
		break;
	default:
		break;
	}
	return 0;
}
int main() {
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("工作日\n");
		break;
	case 6:
	case 7:
		printf("休息日\n");
		break;//这里加上,养成好习惯
	}
	return 0;
}
//case的顺序没有要求。default也可以放在最前面,但是建议放在最后面

注意:每个case语句只是一个入口标志,并不能确定执行的终止点,因此每个case分支最后应该加上break语句,用来结束整个switch结构,否则会从入口点开始一直执行到switch结构结束。

int main() {
	int n = 1;
	int m = 2;
	switch (n) {//n = 1
	case 1:
		m++;//m = 3
	case 2:
		n++;//n = 2
	case 3:
		switch (n) {//n = 2
		case 1:
			n++;
		case 2:
			m++;//m = 4
			n++;//n = 3
			break;
		}
	case 4:
		m++;//m = 5
		break;
	default:
		break;
	}
	printf("m = %d,n = %d\n", m, n);//5,3
	return 0;
}

如果在case语句内声明/定义变量,需要使用{}把case语句内部执行的代码包裹起来。

循环语句

C语言中如何实现循环呢?
while语句、for语句、do … while语句

While(表达式) 循环语句;

int main() {
	int i = 1;
	while (i<11) {
		printf("%d\n",i);
		i++;
	}
	return 0;
}
int main() {
	int ch = getchar();//获取键盘输入的一个字符

	putchar(ch);//打印字符

	printf("%c\n",ch);
	printf("%d\n",ch);

	return 0;
}
int main() {
	int ch = 0;
	//循环从键盘获取字符
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
	return 0;
}
//while循环的实例
#include <stdio.h>
int main()
{
  int line = 0;
  while(line<=20000)
 {
    line++;
    printf("我要继续努力敲代码\n");
 }
  if(line>20000)
    printf("赢取白富美\n");
  return 0;
}

For循环
为什么要有for循环?
While循环的初始值、循环条件、步长,可能相距很远,不好调整
—for循环,三部分放在一起

for(表达式1;表达式2;表达式3){
循环体;
}
表达式2是一个逻辑表达式,为真时,才会进入循环,为假,则不进入循环。

int main() {
	//     初始化    判断    调整
	for (int i = 1; i < 11; i++) {
		printf("%d\n",i);
	}
	return 0;
}

For循环的初始化、调整、判断,都可以省略,但是如果都省略,判断条件恒为真,For(;;)是死循环。

int main() {
	for (;;) {
		printf("hehe\n");

	}
	return 0;
}

for循环的坑点
案例1:

int main() {
	int i = 0;
	int j = 0;
	for (i = 0;i<10;i++) {
		for (j = 0; j < 10;j++) {
			printf("hehe\n");
		}
	}
	return 0;
}

打印100次hehe,每次重新进入内层循环,j的值都从0开始。
案例2:

int main() {
	int i = 0;
	int j = 0;
	for (;i<10;i++) {
		for (; j < 10;j++) {
			printf("hehe\n");
		}
	}
	return 0;
}

打印10次hehe,i= 0时,j从0开始,打印10次hehe,i=1时,j的值为10,不再满足j<10,所以内层循环都进不去了。
案例3:

int main() {
	int i = 0;
	int j = 0;

	for (i = 0, j = 0; i < 2 && j < 5;++i,j++) {
		printf("hehe\n");
	}
	return 0;
}

打印2次hehe,当i=2时,表达式(i < 2 && j < 5)为假,不再满足循环条件。
案例4:

int main() {
	int i = 0;
	int j = 0;
	for (i = 0, j = 0; j = 0;i++,j++) {
		j++;
	}
	return 0;
}

根本没有进入循环,因为j = 0是赋值语句,结果为0,所以不满足循环的条件。

函数

#include <stdio.h>
int main()
{
  int num1 = 0;
 int num2 = 0;
  int sum = 0;
  printf("输入两个操作数:>");
  scanf("%d %d", &a, &b);
  sum = num1 + num2;
  printf("sum = %d\n", sum);
  return 0;
}
//上述代码,写成函数如下:
#include <stdio.h>
int Add(int x, int y)
{
 int z = x+y;
 return z;
}
int main()
{
  int num1 = 0;
 int num2 = 0;
  int sum = 0;
  printf("输入两个操作数:>");
  scanf("%d %d", &num1, &num2);
  sum = Add(num1, num2);
  printf("sum = %d\n", sum);
  return 0;
}

函数的特点就是简化代码,代码复用。

数组

要存储1-10的数字,怎么存储?
C语言中给了数组的定义:一组相同类型元素的集合。

一般变量的声明如下:

int a;
类型 变量名;

与之对应,数组的声明如下:
int arr[5];
元素类型 数组名[元素个数];

这样声明了包含5个int型变量的数组arr。

数组中的元素可以通过下标运算符来获得,比如arr[0],arr[1],…arr[4],下标从0开始。

声明数组的时候,元素的个数必须是常量,它所需要的内存在编译时分配,如下声明会报错:

 int n = 10;
 int arr[n];//报错

注:
C99标准支持可变长数组,并且可变长数组是不能进行初始化的。

数组初始化

int arr1[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,并且进行初始化

int arr2[] = {1,2,3,4,5};//声明数组时,如果不指定数组个数,数组会根据初始值的个数自动进行设定。

//当初始值的数量不足时,自动用0对剩下的元素进行初始化。
int arr3[5] = {1,2,3};//用0 来初始化第4个和第5个元素

//当初始值的个数超过数组的元素的个数时候,程序会发生错误。
//int arr4[4] = {1,2,3,4,5};//报错

//另外,不能通过赋值语句对数组进行初始化
int arr5[3];
//arr5 = {1,2,3};//错误

//C语言不支持数组的相互赋值
int vx[3] = {1,2,3};
int dx[3];
//dx = vx;//错误

数组的使用

#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
for(i=0; i<10; i++)
{
   printf("%d ", arr[i]);
}
printf("\n");
  return 0;
}

本章完。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值