总结(题)
1. 一个C语言的执行是从本程序的main函数开始,到main函数结束,但需要注意的是,也是有特殊情况的,若是代码中出现了exit函数,则直接结束程序
2. while(!x)的含义
!x,就是非x,非0就是真,非其他数字就是假。就是当x为0才成立.
void main()
{
int x=3;
do
{
printf("%3d",x-=2);
}while(!(--x));
int i=3;
if(i%3)
{
printf("1");
}
else
{
printf("0");
}
//输出0,当0的时候为假
}
1 -2,第一遍while(!0),成立,继续执行。第二遍while(!-3),不成立,跳出循环
3. 优先级题
int a=5,b=6,c=7,d=8,m=2,n=2;
(m=a < b)&&(n=c<d);
printf("%d",n);
输出1
int a=5,b=6,c=7,d=8,m=2,n=2;
(m=a < b)&&(n=c>d);
printf("%d",n);
输出0
int a=5,b=6,c=7,d=8,m=2,n=2;
(m=a > b)&&(n=c>d);
printf("%d",n);
输出2
考点:优先级,>比=高
&&,左边假,右边不执行
4. 结合性,数值比较
printf("%d", 3<x<5);
值永远为1,因为<的结合性左到右,如果x的值大于3,那么就是1与5比较,
小于就是0和5比较,结果也是1
printf("%d",3==x==3);
值永远为0,
不管x的值为几,第一次结束要不就是0与3比较,要不就是1与3比较,答案永远为0
5. 强制类型转换
把表达式的运算结果强制转换成类型说明符所表示的类型,只是转换了结果,变量的类型并不转换
运算符的操作数
-
单目运算符:只有一个操作数,例如:
逻辑非运算符【!】、按位取反运算符【~】、自增自减运算符【++ --】、负号运算符【-】、类型转换运算符【(类型)】、指针运算符和取地址运算符【*和&】、长度运算符【sizeof】这些是单目运算符 -
双目运算符:有两个操作数,例如:
,+,-,*,/,=,== -
三目运算符:需要三个操作数,例如:
?:
逗号运算符
int x, y, z;
x=y=1;
z=x++,y++,++y;
printf("%d,%d,%d\n",x,y,z);
2,3,1
z=(x++,y++,++y);
printf("%d,%d,%d\n",x,y,z);
2,3,3
表达式
- 表达式加分号之后就变成了语句了,就不是表达式了
- 表达式是不能被赋值的,=左边不能有表达式
在C程序中无论是整数还是实数,只要在允许的范围内都能准确无误的表示
有大小的允许范围,但是精度有限制,不可能都准确无误的表示。
范围和精度是两个概念
比如 6.221121346541200231230是无法用浮点数准确表示的。
这句话应该加上“在精度范围内”的限定才算正确。
语法
scanf
int main()
{
int a,b,c;
printf(“input three data:\n”);//使用 scanf 之前先用 printf 提示输入。
scanf("%d%d%d",&a,&b,&c); // scanf 的“输入参数”中,前面的取地址符&记住
printf("%d,%d,%d/n",a,b,c);
return 0;
}
运行时按如下方式输入三个值:
3□4□5↙(输入a,b,c的值)
3,4,5 (printf输出的a,b,c的值)
数值与字符
%c的时候,前面是不能加空格的,后面可以
getchar 一个一个输出字符
printf
%d:十进制整数
printf("%5d",123);// 123前面有俩空格
5代表宽度
printf("%-5d",123);//123 后面有俩空格
printf("%5d",-123);// -123前面有一个空格,-5d,后面有一个空格
%c:输出一个字符
printf("%5c",‘a’);// a前面有四个空格
也能输出printf("%c",121);//输出y,输出ASCII码值的转换
0~127之间的,超过了就把它最后一个字节的信息以字符形式输出
%s:输出一个字符串
printf("%s",“china”);// 等价于printf(“china”);
%f
printf("%.2f\n",3.141592);
3.14
printf("%.3f\n",3.141592);
3.142
输出左对齐,用%-m.nf
putchar,一个一个输出字符
数据类型
变量
- 一个有名字的,具有特定属性的一个存储单元,用来存放数据,可以改变。先定义(声明)后使用。
- a(3)a:变量名(不可变),3:变量值(可变),():存储单元:不能变
- 变量名实际上是以一个名字代表的一个存储地址,编译时,系统给每一给变量名分配对应的内存地址。
- 从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。。。间接访问:通过地址访问(指针),直接访问:从变量中取值
标识符,就是一个对象的名字(变量,函数)
常量
-
在那些定义中是一个常量:
1、字符常量:就是输入的字符,比如’c’就是常量,是不能改变的
2、const定义的常量:const int a = 10;
3、枚举定义的常量:enum sex{ grade, cls, num };此时当中的grade、cls、num都是常量
4、宏可以定义一个常量#define max_size = 400 -
程序运行过程中,不能被改变的值就是常量
1)整形常量,整数
2)实型常量,十进制小数形式,数字和小数点组成。指数形式(1.2e3=1.2*10^3)(e或者E之前必须有数字)
3)字符常量,普通字符,单引号括起来的一个字符,存储过程中不是存储字符,而是存储其代码。转义字符,以\开头的字符序列
4)字符串常量,用双引号把若干个字符括起来,“123”,“fsfd”
5)符号常量,用#define PI 3.14 末行没有分号,经过以上处理,文件中从此行开始,PI都是3.14。符号常量不占用内存,只是一个临时符号,预编译之后就不存在了
字符型数据********,与字符串数据进行比较
- char c=‘a’; 单引号,字符不能超过四个,最好是一个字符
- putchar(c)
putchar('s');输出s
putchar(66);输出B
char ch;
ch = getchar();
putchar(ch);
输入qqq,输出q,getchar函数只能接受一个字符
运算符和表达式
if(A)就是当A!=0得时候,A等于0的时候就不执行这个if语句,if(!E)就是!E!=0,就是E==0
i++,i–
使变量的值加减
++i,使用i之前增加1
i++,i使用之后增加1
数组
C语言中不可以对数组整体引用。
int a[] = {1,2,3};
printf("%d",a[2]);
数组是可以省略下标 的
二维数组
- 与java相反,可以不写前面的下标,但必须写后面的。
- 每一行的列必须相同
int a[][3]={1};
printf("%d",a[0][1]);//输出1
printf("%d",a[1][0]);//输出0
字符数组
定义
用%s输出字符串时,printf函数中输出的是字符数组名,而不是数组元素名,不能写成printf("%s\n",c[0]);
char a[7]="dfsfwfd";
char b[7]={"dfsfwfd"};
b[7]等价于{'d','f','s','f','w','f','d','\0'};
char c[7]={'d','f','s','f','w','f','d'};
所以c和b是不一样的,b长度为8,c长度为7
printf("%c\n",c[6]);
char c[8];
scanf("%s",c);
printf("%s",c);
特点
- 用
双撇号
括起来的部分就是字符串常量,如“abc”,"Hello!"都是字符串常量。 - 字符串常量"abc"在内存中占用4个字节(而不是3个字节),编译系统会在字符串最后自动加上一个’\0’作为字符串结束标志。但’\0’并不是字符串的一部分,它只作为字符串的结束标志。 字符串常量通常要用字符数组来存放。
- '\0’是结束字符串
int i,j;
char st[4][5]={"ABCDE","12345"};如果改成"1234567",也是输出12345,不会输出后面的,并且有警告
char s[5]={'A','B','C','D','E'};
for(i=0;i<4;i++){
for(j=0;j<5;j++){
printf("%c",st[i][j]);
}
printf("\n");
}
输出:
ABCDE
12345
字符串数组
char str1[10],str2[]="china"
字符数组里面没有几个也行,只要不少于就行
B.char str[2]={’a’,’b’,’e’),这种就不行
int i,j;
char c[3][8]={{"apple"},{"orange"},{"banana"}};
for(i=0;i<3;i++){
printf("%s\n",c[i]);
}
printf ("%c",c[1][4]); //输出1行4列元素'g'字符
scanf ("%c",&c[2][3]); //输入一个字符到2行3列元素中
c[2][0]='B'; //把字符赋值给2行0列元素
printf ("%s",c[1]); //c[1]为第2行的数组名(首元素地址),输出 orange
scanf ("%s",c[2]); //输入字符串到c[2]行,从c[2]行的首地址开始存放
选择结构
if…else…,没有循环的特点
- 可以是关系表达式,逻辑表达式,算术表达式
C语言规定else总是与其前面最近的尚未配对的if语句组成配对关系。
switch
switch括号中的表达式,其值的类型应该为整数类型(包括字符型)
可以没有default
各个case标号出现的顺序不影响执行结果
每个case常量必须互不相同
循环
break
只能用于循环语句和switch语句
continue
- 提前结束本次循环,接着执行下次循环
- 跳过下一个右括号
指针,啊啊啊啊啊啊啊啊
指针是什么
- 对变量的访问都是通过地址进行的
- 直接访问:按照变量名进行的访问
- 间接访问:将变量i的地址存放在另一个变量中,然后通过该变量来找到变量i的地址,从而访问i变量
指针变量
- 如果有一个变量专门用来存放另一个变量的地址(即指针),则它称为指针变量。指针变量就是地址变量,用来存放地址,指针变量的值就是地址
- 指针是一个地址,指针变量是存放地址的变量
- *表示指向
- 类型 * 指针变量名
指针参数
- C语言中实参变量和形参变量之间的数据传递是单向的值传递
用指针变量做函数参数时同样要遵循这一规则 - 不可能通过执行调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值
对应的实参和形参是两个独立实体,它们之间只有单向的值的传递,即实参的值传递给形参。形参的值在函数中不论怎么改变,都不会影响实参。
void asd(int x,int y){
int t;
t=x;
x=y;
y=t;
}
void main()
{
int a=1,b=2;
if(a<b){
asd(a,b);
}
printf("%d%d",a,b);
输出12
}
总结
不带 * 是指针变量,代表地址。带了 * 是表示变量的值,是真的值
指针变量的值(不带*的)是地址,
- C语言不可能通过执行调用函数来改变实参指针变量的值(也就是地址),
- 但是可以改变实参指针变量所指变量的值
void swap(int *p1,int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}
void swap(int *p1,int *p2)
{
int *t;
t=p1;
p1=p2;
p2=t;
}
不能这么写,违背了1
函数
函数处理字符串,需要# include “String.h”
puts(字符数组)
- 作用:将一个字符串(以’\0’结束的字符序列)输出。
可以包含转义字符,但是’\0’还是结束,后面的字符串不输出
- 只能输出一个字符串
gets(字符数组)
- 输入一个字符串到字符数组,并且得到一个函数值,该函数值是字符数组的起始地址
- hello,不是五个字符,是六个
- 只能输入一个字符串
strcat(字符数组1,字符数组2)–字符串连接函数
- 字符串2接到字符串1后面,
- 连接前两个字符串的后面都有’\0’,连接时将字符串1后面的’\0’取消
字符串复制函数 strcpy(字符数组1,字符数组2)和strncpy,
- 字符数组1必须写成数组名的形式(str1),字符数组2可以是字符数组名,也可以是一个字符串常量,strcpy(str1,“china”);
#include "stdio.h"
#include "string.h"//使用字符串函数必有的
void main(){
char s1[20]="hello",s2[]="world";
printf("%s",strcpy(s1,&s2[1]));
}
输出orld
- strncpy(str1,str2,2)是将str2中最前面的两个字符复制到str1中,取代str1中原有的字符的最前面两个字符,但是复制的字符个数n不应该多于str1中原有的字符(不包括’\0’)
strcmp(字符串1,字符串2)
- 两个字符串从左到右逐个字符相比,根据ASCII码值大小比较,直到出现不同的字符或遇到’\0’为止。
- 比较的结果由函数值带回,相等返回0,1>2返回正整数,1<2返回负整数
strlen(字符数组)
- 测试字符串长度(不包括‘\0’)
char str1[20]="hello",str2[]="world"; printf("%d",strlen(str1));
,输出5
strlwr(字符串)
大写转换为小写
strupr(字符串)
小写转换为大写
函数的声明与定义的区别
-
C语言编译系统是由上往下编译的. 一般被调函数放在主调函数后面的话,前面就该有声明。正如变量必须先声明后使用一样,函数也必须在被调用之前先声明,否则无法调用!函数的声明可以与定义分离,要注意的是一个函数只能被定义一次,但可以声明多次。
-
函数声明由函数返回类型、函数名和形参列表组成。形参列表必须包括形参类型,但是不必对形参命名。这三个元素被称为函数原型,函数原型描述了函数的接口。定义函数的程序员提供函数原型,使用函数的程序员就只需要对函数原型编辑即可。
【返回类型】 函数名(参数1类型 参数1,参数2类型 参数2,……);
函数声明中的形参名往往被忽略,如果声明中提供了形参的名字,也只是用作辅助文档。另外要注意函数声明是一个语句,后面不可漏分号! -
声明与定义的区别:
函数的声明与函数的定义形式上十分相似,但是二者有着本质上的不同。声明是不开辟内存的,仅仅告诉编译器,要声明的部分存在,要预留一点空间。定义则需要开辟内存。
1)函数的定义
函数的定义是一个完整的函数单元:
包含函数类型、函数名、形参及形参类型、函数体等(首部?)
在程序中,函数的定义只能有一次
函数首部与花括号间不加分号
2)函数的声明
函数声明只是对编译系统的一个说明:
函数声明是对定义的函数的返回值的类型说明,以通知系统在本函数中所调用的函数是什么类型。
不包含函数体(或形参)
调用几次该函数就应在各个主调函数中做相应声明
函数声明是一个说明语句,必须以分号结束
// 只是做个函数声明,并不用实现
int sum(int a, int b);
int main()
{
int c = sum(1, 4);
return 0;
}
// 函数的定义(实现)
int sum(int a, int b) {
return a + b;
}
2018
5.若有以下定义:int x[10];int *pt=x;则对x数组元素的正确引用是( )。
A.pt+3 B.*&x[10] C.*(pt+10) D.*(x+3)
【解析】引用数组元素可以有两种方法,一种是使用下标值法,如x[i]表示引用数组下标为i的元素,另一种方法是使用指针引用数组元素,如*(pt+i)表示引用指针pt当前所指元素后的第i个元素。这两种方法的前提条件是所引元素的位置包含在数组范围以内,即不发生溢出,否则会出现错误。因此,本题的答案为D)。