拾遗
1、赋值运算符
赋值运算符的左边必须是一个lvalue,变量名就是lvalue
例:int a;
a=5;
如果 int a;
5=a;
那么会提示错误
2、复合的赋值运算符
...
a=a+1 写成 a +=1
a=a-2 写成 a -=2
a=a*3 写成 a*=3
a=a/4 写成 a /=4
a=a%5 写成 a %=5
...
3、自增自减运算符
i=i+1 写成 i++或++i
i=i-1 写成 i- -或 - -i
i++和++i的区别
#include<stdio.h>
int main()
{
int i=5,j;
j=++i;
printf("i=%d,j=%d\n",i,j);
i=5;
j=i++;
printf("i=%d,j=%d\n",i,j);
return 0;
}
运行结果:i=6,j=6
i=6,j=5
区别在于:j=++i是i先自加1,然后赋值给j;而j=i++是先赋值给j然后在自加1
3、逗号运算符
- 形式
...
i=1;
j=2; 写成...i= 1,j=2,k=3;...
k=3;
...
- 语法
表达式1,表达式2,表达式3......表达式n
——从左到右运算
——逗号表达式作为一个整体,他的值为最后一个表达式的值(其他表达式只运算,不取值)
例1:a=3,5;就是
a=3;
5;
例2:a=(b=3,(c=b+4)+5)
——先将变量b赋值为3
——然后将变量c赋值为b+4,即7
——接下来c赋值为7+5等于12
——最后赋值给变量a,得到变量a的值为12
- C语言中看到逗号也不一定是逗号运算符,也有可能只是一个分隔符
4、条件运算符
- 语法
exp1? exp2: exp3;
——exp1是条件表达式
——如果结果为真,返回exp2
——如果结果为假,返回exp3
例:
if(a>b)
max = a;
else
max = b;
变为:
max = a>b ? a : b
5、go to 语句
- 语法:goto 标签;
例:
#include<stdio.h>
int main()
{
int i=5;
while(i++)
{
if(i>10)
{
goto A;
}
}
A: printf("i=%d\n");
return 0;
}
运行结果:i=11
注意:
虽然很方便,但是在开发中应该尽量避免使用goto语句,因为跳来跳去的话可能会破坏程序的逻辑。
有一种情况是如果要从最内层的循环跳到最外层,比较适合用goto语句,break语句的话只能跳出一层循环。
6、注释
- //......某行注释
- /*......*/跨越多行的注释
- 注释是写给自己看的,保证以后再拿来看可以迅速看懂
数组
- 定义
存储一批同类型数据的地方
- 格式
类型 数组名 [元素个数]
1、数组不能动态定义(C99新标准中已经可以)
2、如何访问数组中的元素?
a[0] ; //访问数组中的第一个元素
a[1] ; //访问数组中的第二个元素
a[2]; //访问数组中的第三个元素
......
例:
#include<stdio.h>
int main()
{
int a[10],i;
for(i=0;i<=10;i++) //这里按照定义会产生数组越界的情况
{
a[i] = i;
}
for(i=0;i<=10;i++)
{
printf("%d\n",a[i]);
}
return 0;
}
但是事实上并没有编译错误,打印出了11个值;如果第一个for改为正常的i<10,结果还是可以正常编译出11个值;
事实上这是新版C语言编译器在出现数组溢出时程序的保护,使程序不会产生较大的错误。
尽管如此,但是实际编程中不要出现数组溢出的情况!
3、循环跟数组的关系
int a[10];
for(i=0;i<10;i++) //这里 i 通常从0开始原因就是数组的第一个元素的下标是a[0]
{
a[i] = i;
}
例:计算某次测试10位同学的平均成绩
#include<stdio.h>
#define NUM 10
int main()
{
int s[NUM];
int i,sum=0;
for(i=0;i<10;i++)
{
printf("请输入第%i位同学的成绩\n",i+1);
scanf("%d",&s[i]);
sum+=s[i];
}
printf("这次测试的平均分是:%.2f\n",(double)sum/NUM);
return 0;
}
4、数组的初始化
即在定义的同时赋初值
- 将数组中所有元素初始化为0,可以这么写:
int a[10] = {0}; //事实上这里只是将第一个元素赋值为0;如果是 int a[10] = {1}的话,就是1 0 0 0 0 0 0 0 0 0
- 如果是赋予不同的值,那么用逗号分隔开即可:
int a[10] = {1,2,3,4,5,6,7,8,9,10};
- 还可以只给一部分元素赋值,未被赋值的元素自动初始化为0
int a[10] = {1,2,3,4,5,6}; //前六个有值,后四个初始化为0
- 有时候还可以偷懒,可以只给出各个元素的值,而不指定数组的长度(因为编译器会根据值的个数自动判断数组的长度,Lesson1已经提过)
int a[] = {1,2,3,4,5,6,7,8,9,5,2,};
- C99增加了一种新特性:指定初始化的元素
这样就可以只对数组中的某些指定元素进行初始化赋值,而未被赋值的元素自动初始化为0
int a[10] = {[3] = [3],[5] =[5],[8] = [8]};
5、字符数组
- 字符类型的数组
可以逐个用单个字符常量存放在字符变量里:
char str1[10] = {'F','i','s','h','c','\0'} ; //初始化字符数组的每个元素
char str1[] = {'F','i','s','h','c','\0'}; //可以不写元素的个数,因为编译器会自动计算
也可以直接用字符串常量存放在数组里面:
char str2[] = {”Fis'hc”}; //使用字符串常量初始化字符数组
char str2[] = ”Fis'hc”; //使用字符串常量初始化字符数组可以省略大括号
- 字符串变量的说明:
1、字符变量在内存中占一个字节。
2、在内存中,是把字符对应的ASCII码值放到存储单元中。
3、字符型数据与整型数据之间可以通用。
6、字符串处理函数
- 获取字符串的长度:strlen
#include<stdio.h>
#include<string.h>
int main()
{
char str[]="I love biancheng!";
printf("sizeof str=%d\n",sizeof(str));
printf("strlen str=%d\n",strlen(str));
return 0;
}
//编译结果:sizeof str=18
strlen str=17
注意:字符串的长度不包含 ‘\0’,所以比sizeof(获取字符串的尺寸)少1。
- 拷贝字符串:strcpy和strncpy
#include<stdio.h>
#include<string.h> //别忘记头文件!
int main()
{
char str1[]="I love FishC.com!";
char str2[]="New string";
char str3[100];
strcpy(str1,str2); //这里要保证str1的尺寸大于str2
strcpy(str3,"Copy successful!");
printf("str1=%s\n",str1);
printf("str2=%s\n",str2);
printf("str3=%s\n",str3);
return 0;
}
//编译结果:str1=New string
str2=New string
str3=Copy successful
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="To be or not to be";
char str2[100];
strncpy(str2,str1,5); //把str1中的前5个字符复制到str2(不包含'\0')
str2[5]='\0'; //加上结束标志'\0'
printf("str2=%s\n",str2);
return 0;
}
- 连接字符串:strcat和strncat
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="To be or";
char str2[]="or not to be";
strcat(str1," ");
strcat(str1,str2);
printf("str1=%s\n",str1);
return 0;
}
//编译结果:str1=To be or not to be
同样的strncat可以限定连接的字符个数,但是与strncpy不同的是,它编译过程中已经加了'\0',不用再追加'\0'。
- 比较字符串:strcmp和strncmp
原理:从第一个字符串开始,依次对比每一个字符串的ASCII码;
如果
① str1小于str2,返回负值或者-1
② str1等于str2,返回0;
③ str1大于str2,返回正值或者1
(str1和str2可以是字符串常量或者字符串变量,返回值为整形)
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="I love biancheng.com!";
char str2[]="I love biancheng.com!";
if(!strcmp(str1,str2))
{
printf("两个字符串完全一致!\n");
}
else
{
printf("两个字符串存在差异!\n");
}
return 0;
}
//编译结果:两个字符串完全一致!
二维数组
- 格式
类型 数组名 [常量表达式] [常量表达式]
int a[6][6] //6行6列
- 二维数组的访问
和一维数组一样;在C语言中,二维数组是线性按行排列的,先排第一行,再排第二行......
- 二维数组的初始化
(1)由于二维数组在内存中是线性存放的,因此可以将所有的数据写在一个花括号内:
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}
(2)为了更直观的表示元素的分布,可以用大括号将每一行的元素括起来
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
};
(3)二维数组也可以仅对部分元素赋初值:
int a[3][4] = { {1},{5},{8}}; //每一行的第一列赋值为1,5,8
(4)如果希望将整个二维数组赋初值为0,那么
int a[3][4] = {0};
(5)C99同样也对二维数组支持初始化指定元素的值
int a[3][4] = {[0][0] = 1,[1][1] = 2,[2][2] = 3};
(6)二维数组的初始化也可以偷懒。但是只有第一维的元素个数可以不写,其他维度必须写上