一、程序结构
C 程序主要包括以下部分:
预处理器指令
函数
变量
语句 & 表达式
注释
一个简单的程序
#include <stdio.h>
int main()
{
/* 我的第一个 C 程序 */
printf("Hello, World! \n");
return 0;
}
程序解释
1.程序的第一行 #include <stdio.h> 是预处理器指令,告诉 C 编译器在实际编译之前要包含 stdio.h 文件。
2.下一行 int main() 是主函数,程序从这里开始执行。
3.下一行 /*...*/ 将会被编译器忽略,这里放置程序的注释内容。它们被称为程序的注释。
4.下一行 printf(...) 是 C 中另一个可用的函数,会在屏幕上显示消息 "Hello, World!"。
5.下一行 return 0; 终止 main() 函数,并返回值 0。
数据类型
类型 存储大小 值范围
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 2 或 4 字节 - 32,768 到 32,767 或 -2,147,483,648 到2,147,483,647
unsigned int 2 或 4 字节 0 到 65,535 或 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295
整型(基本型):类型说明符为int,在内存中占2个字节。
短整型:类型说明符为short int或short。所占字节和取值范围均与整型(基本型)相同。
长整型:类型说明符为long int或long,在内存中占4个字节。
无符号型:类型说明符为unsigned。
无符号型又可与上述三种类型匹配而构成:
单精度(float型)、双精度(double型)和长双精度(long double型)三类。
单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字
双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。
长双精度型16 个字节(128位)内存空间,可提供18-19位有效数字。
常见常用符号
\b 退格(当前位置啊后退一个字符)
\f 走纸换页(当前位置移到下一页的开头)
\n 换行(当前位置移到下一行的开头)
\r 回车(当前位置移到本行的开头)
%d 整型(有符号10进制) int
%c 字符型 char
%f 浮点型(单精度) float
%lf 浮点型(双精度) double
%s 字符串型
%ld 长整型 long int
%lld 长整型 long long
%llu 无符号长整型 unsigned long long
%o或%O 无符号8进制型
%x或%X 无符号16进制型
%e或%E 指数型
二、 变量与常量
变量定义: 就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表
变量的名称:可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C 是大小写敏感的。另外定义的变量不能是C语言中的关键字 例如变量不能是int double等见一个记一个就行了
常量: 是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值,也有枚举常量。
常量就像是常规的变量,只不过常量的值在定义后不能进行修改。
整数常量: 可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
浮点常量: 浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。
下面列举几个整数常量的实例:
212 /* 合法的 */
215u /* 合法的 */
0xFeeL /* 合法的 */
078 /* 非法的:8 不是八进制的数字 */
032UU /* 非法的:不能重复后缀 */
以下是各种类型的整数常量的实例:
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* 整数 */
30u /* 无符号整数 */
30l /* 长整数 */
30ul /* 无符号长整数 */
下面列举几个浮点常量的实例:
3.14159 /* 合法的 */
314159E-5L /* 合法的 */
510E /* 非法的:不完整的指数 */
210f /* 非法的:没有小数或指数 */
.e55 /* 非法的:缺少整数或分数 */
对于你定义的变量 变量之间进行运算时 期间会有强制类型转换 下面看一个例子
#include <stdio.h>
int main()
{
int a=1,c=0;
float b=1.1;
c=a+b;
//变量a和变量b的类型是不一样的 但由于变量c是整型 所以在会强制类型转换 结果取整型
结果是2 而不是2.1;
printf("%d\n",c);此处的%字母(类型)和你后面输出的变量是相对应的 否则结果会是乱码
return 0;
}
在涉及小数位数时 在%.后写需要的位数 例如两位 %.2f 保留整数%.0f
字符型数据: 是指单个字符,在计算机内存中占一个字节,C语言规定字符常量用单引号括起来。例如:'a','b','c','8',但输出时不输出单引号。
格式说明%c用于输出一个字符,字符可以按整形式输出,而且是以ASCII码形式来输出,字符a和A的ASCII码值分别为97和65。
字符常量可以参与运算,表达式'a'+1的值是字符'a'的ASCII码值97和1之和。
小写字母和其对应的大写字母的ASCII码值之差都是32,没两个字母的ASCII码值相差1且下写字母的ASCII码值是比大写字母的大的,因此将字母'H'可表示为'h'-32,字母'm'可表示为'M'+32
字符常量是ASCII字符集中的一个字符,但是有些字符是在键盘上找不到的,在程序中使用这些字符的方法是在“\”后加该字符的八进制ASCII码值(最多三位)或在“\x”后加该字符的十六进制ASCII码值(最多两位)
因此,字符常量有两种形式:一个是常规字符(用单引号括起来的单个字符),二是转义字符(以“\”开头的字符序列),字符常量可以按其ASCII码值参与整数运算,即字符数据与整形数据可以通用
以"\"开头的字符序列为转义字符,下列是常用的转义字符
\\ \ 字符
\' ' 字符
\" " 字符
\? ? 字符
\a 警报铃声
\b 退格键
\f 换页符
\n 换行符
\r 回车
\t 水平制表符
\v 垂直制表符
\ooo 一到三位的八进制数
\xhh . . . 一个或多个数字的十六进制数
字符型变量:可以存放ASCII字符集中的任何一个字符,字符变量在内存中占一个字节
将常规字符或转义字符赋给字符变量时都需要在其两侧加单引号,但将整形数据赋给字符常量时,不能加单引号
转义字符“\0”的ASCII码值为0
由于字符按其ASCII码值参与整数运算,因此可以将其运算结果直接赋给整形变量,当把一个字符放在字符变量时,实际上是将该字符的ASCII码值存放在变量所带代表的存储单元,即变量中的内容为该字符的ASCII码值,因此字符变量可以参加整形数据的任何运算,
编写程序时,建议用c作为变量的第一个字母,表示该变量为字符型
三、输入和输出
先写一个简单的输入输出程序
#include<stdio.h>
int main()
{
int num;
printf("Please enter a number");
scanf("%d",&num);
printf("You entered %d",num);
return 0;
}
首先要用到输入输出函数,就要引用头文件:#include<stdio.h>
输入语句:scanf函数格式:
scanf("格式控制字符串",变量地址);
变量地址代表scanf函数获取的是变量的地址(其中&符号为获取变量的地址),而不是一个变量的值,通过这个变量地址,就能找到这个变量在哪里,从而可以改变这个变量的值,“%d”是格式控制字符串,表示scanf函数将接收一个整数
在程序运行到这里时,会检查格式字符串来确定要接收的数据类型,然后把键盘输入的值通过&来找到变量从而把值存进去
输出语句:printf函数:
printf(“格式控制字符串”,变量);
这个的意思就是把变量中的值以“”中的格式输出到屏幕上
常用的格式控制字符:
由%+特定字符构成,如%d表示十进制整数,%f表示小数形式,%c表示单个字符
普通的字符将原样输出
一个简单的开平方程序
#include<stdio.h>
#include<math.h> //这个要加上
int main()
{
int a;
a=sqrt(4); //对4开平方并赋给a
printf("%d",a); // 输出a的值为2
return 0;
}
四、运算符和表达式
基本的算术运算符: 算术运算符用于各类数值运算 c语言的算术运算符有五种:+(加)-(减)*(乘)/(除)%(求余)
基本算术运算符都是双目运算符,即运算符要求有两个运算量,如:a+b a*b
基本算术运算符优先级别和数学一样,遵循原则:先乘除后加减,算术运算符的结合方向为自左向右
%运算要求运算量必须为整形数据,5%2=1 1%10=1都是正确的,而5/1.0是错误的
/运算时参与运算量均为整形时结果也为整形,舍去小数 5/3=1
加减乘除运算时,有一个数为实数时结果为double型 1+2.0=3.0
字符型数据可以和数值型数据混合运算
算术表达式: 由算术运算符和括号把常量.变量.函数连接起来的式子为算术表达式 单个常量,变量,和函数可以看做是表达式的特例 a*b+c/d
算术表达式中的变量必须有确定的值
数学中的{}和[]再表达式中不能使用,c只允许使用圆括号,而且可以是多层
如果一个运算符两侧数据类型不同,先自动进行类型转换,再进行运算
运算符的优先级和结合性:
优先级:优先级高的先于优先级低的进行运算,和数学一样,先算括号内再算括号外,先乘除后加减
结合性:一个运算数据两侧的运算符优先级相同时,按运算符结合性规定的结合方向处理,结合性分为两种,左结合性(从左往右)和右结合性(从右往左)
数据类型的转换规则:垂直降落,向上位移
垂直降落:如果运算符是cher型的,则必须转换为int型,是float的先转换为double型
向上位移:如果时数据类型不相同,则先将低级别类型的转换为高级别的
:int型的和double型运算,则现将int型装换为double型在运算,结果为double型的
如果int型和float型运算,则先降再移则是先将float转换为double型,然后int 型转换为double型进行运算
![](http://upload-images.jianshu.io/upload_images/7035387-5369705e4572256e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
[强制类型转换](https://baike.baidu.com/item/%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2)
强制类型转换:是通过类型转换运算来实现的。其一般形式为:(类型说明符)(
[表达式](https://baike.baidu.com/item/%E8%A1%A8%E8%BE%BE%E5%BC%8F)
)其功能是把表达式的运算结果
[强制转换](https://baike.baidu.com/item/%E5%BC%BA%E5%88%B6%E8%BD%AC%E6%8D%A2)
成类型说明符所表示的类型
例如(float) a 把a转换为浮点型,(int)(x+y) 把x+y的结果转换为[整型](https://baike.baidu.com/item/%E6%95%B4%E5%9E%8B)
。
类型说明符和[表达式](https://baike.baidu.com/item/%E8%A1%A8%E8%BE%BE%E5%BC%8F)
都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。
无论是[强制转换]
或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
main()
{
float f=5.75;
printf("f=%d,f=%f\n",(int)f,f);
}
结果:f=5,f=5.750000
将浮点数(单双精度)转换为整数时,将舍弃浮点数的小数部分, 只保留整数部分。将整型值赋给浮点型变量,数值不变,只将形式改为浮点形式, 即小数点后带若干个0。注意:赋值时的类型转换实际上是强制的。
由于C语言中的浮点值总是用双精度表示的,所以float 型数据只是在尾部加0延长为double型数据参加运算,然后直接赋值。double型数据转换为float型时,通过截尾数来实现,截断前要进行四舍五入操作。
自加自减运算符:自加运算符++;自减运算符--,自加自减运算符都是单目运算符,即运算符要求有且只能有一个运算量,例如:5++ ++5 4-- --4
++运算符的功能是使变量的值自加1;--运算符功能是使变量值自减1
自加自减运算符的两种形式:
前置:++i、--i,它的功能就是在使用i之前,i值先加(减)1(先执行i+1或i-1,再使用i值)
后置:i++,--i,它的功能就是在使用i之后,i值再加(减)1(先执行i值,再执行i+1或i-1)
例如:j=3;k=++j; /赋值时j先加1,再将j的值赋给k,结果k=4,j=4;
j=3;k=j++; /赋值时j先赋给k,然后j再增1,结果k=3,j=4;
优先级:高于算术运算符,具有右结合性
正负号运算符:+(正号)-(负号),和数学中一样,运算符优先级大于算术运算符,而与++ --同级,结合方向为自有向左
五、运算符优先级
http://blog.csdn.net/huangblog/article/details/8271791
注:上面网址里面有非常详细的表格
六、逻辑运算符
下面显示了 C 语言支持的所有关系逻辑运算符。假设变量 A 的值为 1,变量 B 的值为 0,则:
&& 称为逻辑与运算符。 如果两个操作数都非零,则条件为真。 (A && B) 为假。
|| 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 (A || B) 为真。
! 称为逻辑非运算符。 用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 !(A && B) 为真。
&& 左边为0 结果=0 后面的不执行 ;
|| 左边为1 结果=1 后面的不执行 ;
要注意的是&& ||都有不完全运送。对于&&运送则从左到右进行判断,如果左边为0,说明此命题不可能再为真 ,则右边不再计算,整个&&运算就是0. ||运算也是从左到右,如果有左边为1,说明此命题不可能为假,则右边也不在计算,直接输出1.
七、三目运算符与if语句
条件运算符为?和:,它是一个三目运算符,即有三个参与运算的量。由条件运算符组成条件表达式的一般形式为:
表达式1? 表达式2: 表达式3
其求值规则为:如果表达式1的值为真,则以表达式2 的值作为条件表达式的值,否则以表达式2的值作为整个条件表达式的值。 条件表达式通常用于赋值语句之中。
例如条件语句:
if(a>b) max=a;
else max=b;
可用条件表达式写为 max=(a>b)?a:b; 执行该语句的语义是:如a>b为真,则把a赋予max,否则把b 赋予max。
使用条件表达式时,还应注意以下几点:
1. 条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符。因此 max=(a>b)?a:b可以去掉括号而写为 max=a>b?a:b
2. 条件运算符?和:是一对运算符,不能分开单独使用。
3. 条件运算符的结合方向是自右至左。
例如:
a>b?a:c>d?c:d应理解为
a>b?a:(c>d?c:d) 这也就是条件表达式嵌套的情形,即其中的表达式3又是一个条
件表达式。
if 语句
用 if 语句可以构成分支结构,它根据给的条件进行判定,以决定执行哪个分支程序段。
C 语言的 if 语句有三种基本形式
第一种形式:
if(条件表达式)
{
语句1;
}
if(条件表达式)
{
语句1;
}
这种形式运行顺序为:当条件表达式为真,执行语句1,否则,直接跳过语句1,执行后面的语句
例子1:
BOOL result = YES;
if(result)
{
printf("result is true\n");
}
BOOL result = YES;
if(result)
{
printf("result is true\n");
}
输出结果为:
result is true
如果把 result 的值改为 NO,那么就什么都不输出了。
例子2:
int a = 5;
int b = 6;
if(a >= b)
{
printf("a大于b\n");
}
int a = 5;
int b = 6;
if(a >= b)
{
printf("a大于b\n");
}
输出结果为:
什么都不输出
如果改成这样:
if(a <= b)
{
printf("a小于b\n");
}
if(a <= b)
{
printf("a小于b\n");
}
那么输出结果为:a小于b。
第二种形式:
if(条件表达式)
{
语句1;
}
else
{
语句2;
}
if(条件表达式)
{
语句1;
}
else
{
语句2;
}
这种结构的执行顺序为:当条件表达式为真时,执行语句1,否则执行语句2。
例子1:
BOOL result= YES;
if(result)
{
printf("result 为真\n");
}
else
{
printf("result 为假\n");
}
BOOL result= YES;
if(result)
{
printf("result 为真\n");
}
else
{
printf("result 为假\n");
}
这里的两个输出语句绝对不会同时输出。
第三种形式:
if(条件表达式1)
{
语句1;
}
else if(条件表达式2)
{
语句2;
}
else
{
语句3;
}
if(条件表达式1)
{
语句1;
}
else if(条件表达式2)
{
语句2;
}
else
{
语句3;
}
这种结构的执行顺序为:当条件表达式1成立时,执行语句1,如果不成立则看条件表达式2是否成立,如果条件表达式2成立,则执行语句2,如果条件表达式2也不成立这会执行语句3。
例子1:
int age = 35;
if(age < 18)
{
printf("你是小孩子\n");
}
else if(age >= 60)
{
printf("你是位老人\n");
}
else
{
printf("你正当青年啊, 小伙子!\n");
}
int age = 35;
if(age < 18)
{
printf("你是小孩子\n");
}
else if(age >= 60)
{
printf("你是位老人\n");
}
else
{
printf("你正当青年啊, 小伙子!\n");
}
输出结果为:
你正当青年啊,小伙子!
八、switch语句
C语言还提供了另外一种多分支选择的语句——switch 语句,它的基本语法格式如下:
switch(表达式){
case 常量表达式1: 语句 1;
case 常量表达式2: 语句 2;
......
case 常量表达式n: 语句 n;
default: 语句 n+1;
}
它的执行过程是:首先计算“表达式”的值,然后从第一个 case 开始,与“常量表达式x”进行比较,如果与当前常量表达式的值不相等,那么就不执行冒号后边的语句 x,一旦发现和某个常量表达式的值相等了,那么它会执行之后所有的语句,如果直到最后一个“常量表达式 n”都没有找到相等的值,那么就执行 default 后的“语句 n+1”。
需要注意的是,当找到一个相等的 case 分支后,会执行该分支以及之后所有分支的语句。例如
#include <stdio.h>
int main(){
int a;
printf("Input integer number:");
scanf("%d",&a);
switch(a){
case 1: printf("Monday\n");
case 2: printf("Tuesday\n");
case 3: printf("Wednesday\n");
case 4: printf("Thursday\n");
case 5: printf("Friday\n");
case 6: printf("Saturday\n");
case 7: printf("Sunday\n");
default:printf("error\n");
}
return 0;
}
运行结果:
Input integer number:
Thursday
Friday
Saturday
Sunday
error
输入4,发现和第四个分支匹配,于是就执行第四个分支以及后面的所有分支。这显然不是我们想要的结果,我们希望只执行第四个分支,跳过后面的所有分支。
为了避免这种情况,C语言还提供了一个关键字 break,专门用于跳出switch语句。
switch 的分支语句一共有 n+1 种,而我们通常希望的都是选择其中的一个分支来执行,执行完后就结束整个 switch 语句,而继续执行 switch后面的语句,此时就可以通过在每个分支后加上 break 语句来实现了。如下:
switch (表达式){
case 常量表达式1: 语句1; break;
case 常量表达式2: 语句2; break;
......
case 常量表达式n: 语句n; break;
default: 语句n+1; break;
}
加了这个 break 语句后,一旦“常量表达式 x”与“表达式”的值相等了,那么就执行“语句 x”,执行完毕后,由于有了 break 则直接跳出 switch 语句,继续执行 switch 语句后面的程序了,这样就可以避免执行不必要的语句。
使用switch语句修改上面的代码:
#include <stdio.h>
int main(){
int a;
printf("Input integer number:");
scanf("%d",&a);
switch(a){
case 1: printf("Monday\n"); break;
case 2: printf("Tuesday\n"); break;
case 3: printf("Wednesday\n"); break;
case 4: printf("Thursday\n"); break;
case 5: printf("Friday\n"); break;
case 6: printf("Saturday\n"); break;
case 7: printf("Sunday\n"); break;
default:printf("error\n"); break;
}
return 0;
}
运行结果:
Input integer number:4
Thursday
值得一提的是,由于default是最后一个分支,匹配后不会再执行其他分支,所以也可以不用break;语句。