本章简单字符串、转义字符、选择语句、循环语句、函数和数组。
字符串
在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;
}
注释
- 代码中有不需要的代码可以直接删除,也可以注释掉;
- 代码中有些代码比较难懂,可以加一下注释文字。
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;
}
本章完。