用sizeof()来查看在你的平台上到底占用多少你多少字节的内存。
Int x= sizeof(int);
Int x=sizeof(shrt int);
Int x=sizeof(long);
Int x=sizeof(long double);
等等。
http://www.enet.com.cn/article/2012/0822/A20120822153730_2.shtml
#—是个预处理的标志,表示对文本进行预处理操作,预处理操作表示对该行代码要预先进行处理;预处理—就是在编译器编译代码之前预先进行的处理操作。#后面的include<stdio.h>是预处理指令,就是预先把标准输入输出函数包括进来—即预先读入标准输入输出头文件。头文件就像一本书的目录,可以方便地查到所需要的内容。头文件中声明了用于输入输出的函数,假如你用到标准输入输出函数时,就要添加这个头文件。如,下例,所以屏幕第一行是输出:我喜欢C语言。
总之,#include<stdio.h>就是在编译器进行编译之前,把stdio包含的头文件(内容)读入到第一行。
操作系统进行操作时,从主函数开始,主函数又间接地调用printf()函数。
即头文件中包含了标准输入输出函数。
函数—是实现一个或多个功能的代码。
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf(“我喜欢C语言\n”);
system(“pause”);
/操作系统先调用主函数。从main()函数中返回。
正常:int main()–return 0、1、-1、2即只要返回整数都正常,或者return不返回也正常;
void main()–return不返回正常;
异常:int main()–return -1;/
}
;----空语句,因为C语言都是以;结束的。
表达式语句:int a=1,b=2,c=5,x=0;x=c=a+b; printf(“%d\n”,x); 结果为3.
VC++自动排版:选择内容---- Alt+F8;
VS2010自动排版: 选择内容---- Ctrl+k------Ctrl+F;ctrl + a , ctrl + k ,ctrl + f ;
%----求模数运算符:用来求出两操作数相除的余数;5 % 6==5
优先级
复合赋值运算符:
+= 增量赋值运算符
-= 减量赋值运算符
*= 相乘赋值运算符
/= 相除赋值运算符
%= 取模赋值运算符
= 按位右移赋值运算符 //如x>>=1; //x右移1位再赋值给x
<<= 按位左移赋值运算符 //如x<<=2; //x左移2位再赋值给x
&= 按位与赋值运算符 //如,x&=0xf0;x与十六进制数0xf0按位与的结果再赋值给x
|= 按位或赋值运算符 //如,x|=0XFF;x与十六进制数0XFF按位或的结果再赋值给x
^= 按位异或赋值运算符//如,x^=0x0f;x与十六进制数0x0f按位异或的结果再赋值给x
后置自加自减
X++;
x–;
前置自加自减
++x;
–x;
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=3;
printf(“%d\n”,x–);//先取变量值并输出—原值;再计算表达式的值,再赋给变量—新值(待下次输出);
printf(“%d\n”,x);
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=3;
printf(“%d\n”,x–+5);//先取变量值—原值3;再计算表达式的值并输出,同时计算变量的值再赋给变量—新值(待下次输出);
printf(“%d\n”,x);
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=3;
printf(“%d\n”,–x); //先计算表达式–x的值,同时赋给变量(以备后用),并输出表达式–x的值;
printf(“%d\n”,x);//输出上一步计算出的变量值。
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=3;
printf(“%d\n”,–x+5); //先计算表达式–x的值,同时赋给变量(以备后用),同时计算表达式–x+5的值,并输出表达式的值;
printf(“%d\n”,x);//输出上一步计算出的变量值。
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=15;
printf(“%d\n”,x<<2);//x左移2位,表达式x<<2的值是60,但是x没变。类似x+5表达式。
printf(“%d\n”,x<<=1);//复合赋值运算符:<<= ,按位左移赋值运算符。x改变
printf(“%d\n”,x+5);
system(“pause”);
}
第四章 初识函数—1,看讲解
函数就是完成一定功能的代码块。
函数—----又叫 方法
1.自定义函数
#include<stdio.h>
#include<stdlib.h>
//int show()
void show()//自定义无参函数
{
printf(“要摘取果子必须先爬上树。\n”);
// return;正常。
//return 0;会报错:IntelliSense: 返回值类型与函数类型不匹配
}
int main()
{
printf(“main函数开始。\n”);
show();
printf(“main函数结束。\n”);
system(“pause”);
}
执行过程:操作系统会先调用main()函数,。。。。。
2.带参数的函数
加法函数:
#include<stdio.h>
#include<stdlib.h>
int add(int x,int y)
{
int sum;
sum=x+y;
return sum;
}
int main()
{
printf(“%d\n”,add(2,3));
system(“pause”);
}
nclude<stdio.h>
#include<stdlib.h>
int add(int x,int y)
{
return x+y; //返回值的类型必须与函数的类型一致。
}
int main()
{
int a; //定义接收返回值的变量;
a=add(2,3);
printf(“%d\n”,a);
system(“pause”);
}
3.函数的返回值
函数的返回值。
#include<stdio.h>
#include<stdlib.h>
void show()
{
printf(“今天比昨天进步了就是成功|!\n”);
//不需要返回值。因函数是void型,不要return语句或用return;即可。
}
int main()
{
show();
system(“pause”);
}
4.形式参数与实际参数
#include<stdio.h>
#include<stdlib.h>
int add(int x,int y,int z)
{
return x+y+z;
}
int main()
{
int a; a=0; //a=0;
printf(“%d\n”,add(1+2,a,3));//常量,变量,表达式
system(“pause”);
}
形参—形式参数,是形式上的,只有在调用时系统才给其分配内存空间,调用结束即释放空间。这样的参数实际上是不存在的,只有在调用时才存在。
实参—调用时传递实际参数;实参可以是:常量,变量,表达式;实参一定要有确定的值,否则报错----警告1 warning C4700: 使用了未初始化的局部变量“a”。
5.形参与实参的类型必须一致
#include<stdlib.h>
int add(int x,int y)
{
return x+y;
}
int main()
{
double i=1.5,j=2.3;
int a=add(i,j);//警告
printf(“%d\n”,a);//常量,变量,表达式
system(“pause”);
}
警告 1 warning C4244: “函数”: 从“double”转换到“int”,可能丢失数据
警告 2 warning C4244: “函数”: 从“double”转换到“int”,可能丢失数据
警告 3 warning C4761:参数的整型大小不匹配,提供转换。
警告 4 warning C4761:参数的整型大小不匹配,提供转换。
6.局部变量
#include<stdio.h>
#include<stdlib.h>
void show(x)//警告3;
{
int x=0;//局部变量,只在调用时产生,只在本函数内有效;只有在本函数被调用时才有生命,主要为节省内存空间。错误1;
}
int main()
{
printf(“%d\n”,x);//验证局部变量的作用域。%d也叫----占位符;错误2,警告5;
system(“pause”);
}
错误 1 error C2082: 形参“x”的重定义
错误 2 error C2065: “x”: 未声明的标识符
3 IntelliSense: 未定义标识符 “x”
4 IntelliSense: 未定义标识符 “x”
IntelliSense----智能提示,智能感知
7.全局变量
在所有函数外部定义的变量,包含main()函数。可被所有函数使用。其作用域从定义处开始到源程序结束。源程序—是指未编译的程序;源文件—是指保存源程序的文件。在整个程序运行期间都占用内存,直到整个程序运行结束,才释放内存空间。
#include<stdio.h>
#include<stdlib.h>
int x=576;
void show()
{
printf(“在show()函数中,x的值为:%d\n”,x);
}
int main()
{
show();
printf(“在main()函数中,x的值为:%d\n”,x);
system(“pause”);
}
局部变量与全局变量同名时会发生什么情况?
#include<stdio.h>
#include<stdlib.h>
int x=576,y;
void show()
{
int x=222;int z;
printf(“在show()函数中,x的值为:%d\n”,x);
printf(“在show()函数中,y的值为:%d\n”,y);
printf(“在show()函数中,z的值为:%d\n”,z);
}
int main()
{
show();
printf(“在main()函数中,x的值为:%d\n”,x);
printf(“在show()函数中,y的值为:%d\n”,y);
system(“pause”);
}
局部变量优先。
全局变量y未被赋值时,被初始化为0值。局部变量z未被赋值时,其初始化值随机__不可预测。
警告 1 warning C4700: 使用了未初始化的局部变量“z”
8.全局变量的缺点
诸多缺点:生存周期长,占用内存,容易和局部变量重名,误被局部变量所屏蔽(但是主要缺点是:值容易被修改-----因为局部变量优先);
#include<stdio.h>
#include<stdlib.h>
int x=567;
void show()//将全局变量x的值修改为222,为了演示全局变量容易被修改
{
x=222;// 修改全局变量的值
printf(“在show()函数中,x的值为:\n”,x);
}
int main()
{
printf(“在main()函数中,x的值为:%d\n”,x);
show();
printf(“在main()函数中,x的值为:%d\n”,x); // 也修改了全局变量的值
x=3; // 修改全局变量的值
printf(“在main()函数中,x的值为:%d\n”,x);
system(“pause”);
}
9.作用域
#include<stdio.h>
#include<stdlib.h>
int x=567;
void show()//将全局变量x的值修改为222,为了演示全局变量容易被修改
{
x=222;// 修改全局变量的值
printf(“在show()函数中,x的值为:%d\n”,x);
}
int main()
{
x=3; // 修改全局变量的值
printf(“在main()函数中,x的值为:%d\n”,x);
show();//调用show()函数后,全局变量在show()函数的修改值有效,因全局变量的生存期直到整个程序结束。
printf(“在main()函数中,x的值为:%d\n”,x);
printf(“在main()函数中,x的值为:%d\n”,x);
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int x=567;
void show()//定义重名局部变量并赋值222,为了演示全局变量,局部变量的作用域及生命周期
{
int x=222;// 定义重名局部变量并赋值222
printf(“在show()函数中,x的值为:%d\n”,x);
}
int main()
{
x=3; // 修改全局变量的值
printf(“在main()函数中,x的值为:%d\n”,x);//主函数中的局部变量X优先
show();//show函数中的局部变量X优先, 其作用域从定义变量处开始,到定义变量的函数的右大括号结束。
printf(“在main()函数中,x的值为:%d\n”,x); //主函数中的局部变量X优先
printf(“在main()函数中,x的值为:%d\n”,x); //主函数中的局部变量X优先
system(“pause”);
}
作用域:就是变量的有效作用范围;
局部变量的作用域:从定义变量处开始,到定义变量的函数的右大括号结束。
全局变量的作用域:从定义变量处开始,到整个程序结束(即主函数的右大括号)。
变量的作用域与变量的生存期是不一样的。
变量的生存期,是从创建开始到生命结束(从调用开始—也就是创建开始并分配内存,到调用结束—释放内存);
变量的作用域,是变量的有效访问范围;
#include<stdio.h>
#include<stdlib.h>
int x=567;
void show()//定义重名局部变量并赋值222,为了演示全局变量,局部变量的作用域及生命周期
{
int x=222;// 定义重名局部变量并赋值222
printf(“在show()函数中,x的值为:%d\n”,x);
}
int main()
{
int x=3; // 定义局部变量并赋值
printf(“在main()函数中,x的值为:%d\n”,x); //主函数中的局部变量X优先
show();//show()函数中的局部变量X优先
printf(“在main()函数中,x的值为:%d\n”,x); //主函数中的局部变量X优先
printf(“在main()函数中,x的值为:%d\n”,x); //主函数中的局部变量X优先
system(“pause”);
}
Main()函数中的x只在Main()函数中起作用—即有效访问访问在Main()函数中,当调用show()函数时, Main()函数中的x就不起作用了,超出了其访问范围,这个x在show()函数中就不能访问了,这就是Main()函数中局部变量x的作用域;
在调用show()函数时,虽然从Main()函数跳到show()函数,导致Main()函数中的x作用域发生了变(不起作用),但其x的生命期并没有结束,直至返回Main()函数到Main()函数结束,x的寿命才结束。
10.输出函数
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf(“四则运算… \n”);
printf(“%d+%d\t=%d\n”,15,16,15+16);
printf(“%d-%d\t=%d\n”,15,16,15-16);
printf(“%d*%d\t=%d\n”,15,16,15*16);
printf(“%d/%d\t=%d\n”,15,16,15/16);//15/16—整数/整数=整数0
printf(“%d/%d\t=%f\n”,15,16,15/16);//15/16—整数/整数=整数0,再转换为浮点数0?
printf(“%d/%d\t=%f\n”,15,16,(float)15/16);// 把15强制转换为浮点数
system(“pause”);
}
printf(“%d/%d\t=%d\n”,15,2,15/2);//15/16—整数/整数=整数0
printf(“%d/%d\t=%f\n”,15,2,15/2);//15/2—整数/整数=整数0,再转换为浮点数0?
printf(“%d/%d\t=%f\n”,15,2,(float)15/2);// 把15强制转换为浮点数
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf(“%d\n”,-5/3); //向下取整,即所取整数是靠近原点的整数。当然取-1
printf(“%d\n”,5/3); //向下取整,即所取整数是靠近原点的整数。当然取+1
printf(“%f\n”,5/3);/* 结果按照浮点数输出。浮点数是用double表示的64位,由于字长不够,系统就取了整数后面的字节作为浮点数的一部分,所以输出成了0.000000的样子,这是随机的,和机器有关。*/
printf(“%f\n”,5.0/3);
printf(“%d\n”,5.0/3); // 按照整数输出,系统将浮点数转化为整数(出现截断),出现此乖乖的结果。
printf(“%f\n”,5/3.0);
printf(“%d\n”,5/3.0); // 按照整数输出,系统将浮点数转化为整数(出现截断),出现此乖乖的结果。
system(“pause”);
}
-1
1
0.000000
1.666667
-1431655765
1.666667
-1431655765
请按任意键继续. . .
// printf(“%f\n”,5/3);
说明_____分析“错误”及纠正办法:printf();函数将两个整数相除的结果看作整数而不是浮点数,而使用%f来输出整数是非法的,其结果是未定义。
假如不使用强制转换运算符,可以这么做:
printf(“%f\n%f\n%f\n “,5.0/3,5/3.0,5.0/3.0);
使用强制转换运算符,可以这么做:
printf(”%f\n”,(float)(5/3));
// printf(“%d\n”,5/3.0);
说明_____分析“错误”及纠正办法:printf();函数将两个整数与浮点数相除的结果看作浮点数而不是整数,而使用%d来输出浮点数发生截断,其结果是随机的。
假如不使用强制转换运算符,可以这么做:
printf(“%d\n”,5/3);
使用强制转换运算符,可以这么做:
printf(“%d\n”,(int)(5.0/3));
修改后的程序如下。
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf(“%d\n”,-5/3); //向下取整,即所取整数是靠近原点的整数。当然取-1
printf(“%d\n”,5/3); //向下取整,即所取整数是靠近原点的整数。当然取+1
printf(“%f\n”,(float)(5/3));/强制转换。或者 printf(“%f\n”,5.0/3)/
printf(“%f\n”,5.0/3);
printf(“%d\n”,(int)(5/3)); // 强制转换。
printf(“%f\n”,5/3.0);
printf(“%d\n”,(int)(5/3.0)); // 强制转换。
system(“pause”);
}
-1
1
1.000000
1.666667
1
1.666667
1
请按任意键继续. . .
11.输入函数 _取地址
Scanf()函数
&取地址运算符-----获取变量在内存中的地址。
获取变量的地址以后,才能把用户输入的数据保存到变量地址所对应的内存单元中。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a;
scanf(“%d”,&a);
printf(“a=%d\n”,a);
system(“pause”);
}
F5运行,闪烁光标提示用户输入数据,输入数据后,Scanf()从内存中获取变量的地址并将其保存在变量的内存单元中;printf()函数又将其复制值输出在屏幕上(系统复制一份给printf()函数)。
张三查阅李四的试卷:李四复制了一份给张三,张三不能修改李四的试卷。张三要想修改李四的试卷,必须获取存放试卷的地址—获取原版试卷—才能修改。
printf()函数仅仅是读取(输出)变量a的值,不需要获取其地址,系统只需要将变量a的值复制一份传递给printf()函数(放到printf()函数中);而Scanf()函数是能修改变量的原始值,将变量的值修改为用户输入的值。如果再用这种方法,修改的只是复制的值,而不是变量的原始值。为了能将原始值修改为用户输入的值,所以就需要获取变量a的地址才能对它进行修改。
printf()函数仅仅是输出变量的值,而不是修改变量的值,所以系统只需复制一份放置到printf()函数中,来输出复制的变量的值。为什么printf()函数需要将变量的值复制一份,不复制就不行吗?看看下面的所举的比较形象的例子。
每颗原子弹都有自己的有效破坏范围,但超出了这个范围就无效了。要在另一个范围有效,又不能移动这颗原子弹的前提条件下,就必须再制造(复制)一颗原子弹放到另一个范围,这就是另一颗原子弹的有效作用范围了。
同样道理,每个局部变量都有自己的作用域,在自己的作用域内,变量的作用是有效的,但是超出了这个作用域,这个变量就无效了。因此,假设要它在别的作用域也有效,必须将这个变量复制一份,然后将它放到别的作用域中去。举例来说,我们在main()函数中,我们声明了局部变量a,将它传递给printf()函数,这会暂时终止main()函数的执行,而转到printf()函数中去执行,这会导致局部变量a超出了自己的作用域。变量a的作用域只在main()函数中,不在printf()中,printf()将无法访问变量a。所以,解决的办法是,系统再复制一个变量a,将它作为printf()函数的局部变量,这样printf()函数就能访问它了。
C语言读入字符不会跳过空白字符。我们可以看一个简单的例子:
#include<stdio.h>
#include<stdlib.h>
int main (void)
{ //getchar()可消除上次回车符对下次字符输入函数的影响。
char ch;
scanf(“%c”,&ch); // ch=getchar();
printf(“%c”,ch); // putchar(ch);
system(“pause”);
return;
} //我现在键入一个字符A,回车:
它把字符A读入,换行然后打印出来,接着输出提示结束。
//我现在键入一个换行符:(说明换行符总是最后读入最先输出----属于栈操作)
它除了把换行符读入,换行然后打印出来,接着输出提示结束。
//同理,我现在键入一个空格符,回车:
它也把空格符读入,换行然后打印出来,接着输出提示结束。
//同理,我现在键入一个制表符,回车:
它也把制表符读入,换行然后打印出来,接着输出提示结束。
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
char ch1,ch2,ch3;
scanf(“%c”,&ch1); // ch=getchar();
printf(“%c”,ch1); // putchar(ch);
scanf(“%c”,&ch2); // ch=getchar();
printf(“%c”,ch2); // putchar(ch);
scanf(“%c”,&ch3); // ch=getchar();
printf(“%c”,ch3); // putchar(ch);
putchar(‘\n’);//控制字符’\n’表示:回车 + 换行
system(“pause”);
return;
}//三条输出语句分别输出:a,空格,b三个字符。
//getchar()可消除上次回车符对下次字符输入函数的影响。
上述程序添加两次getchar()语句,三次分别输入单个字符,分别输出其字符。
#include<stdio.h>
#include<stdlib.h>
int main()
{char ch1,ch2,ch3;
scanf(“%c”,&ch1); // ch=getchar();
printf(“本次输入的是%c\n”,ch1); // putchar(ch);
getchar();//getchar()可消除上次回车符对下次字符输入函数的影响。
scanf(“%c”,&ch2); // ch=getchar();
printf(“本次输入的是%c\n”,ch2); // putchar(ch);
getchar();//getchar()可消除上次回车符对下次字符输入函数的影响。
scanf(“%c”,&ch3); // ch=getchar();
printf(“本次输入的是%c”,ch3); // putchar(ch);
putchar(‘\n’);//控制字符’\n’表示:回车 + 换行
system(“pause”);
return;
}
以下疑问? 循环次数问题
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
char ch;
int i,len;
printf(“请输入调试次数len = “);
scanf(”%d”,&len);
for(i=0;i<len;i++)
{
printf("请输入字符或字符串! ");
ch=getchar();
putchar(ch);
}
system(“pause”);
return;
}
12.字符输出函数
字符输出函数putchar()在头文件stoid.h中声明。它的作用是向标准输出设备输出一个字符。标准输出设备是指打印机、显示器、指示灯、扬声器、磁盘或光盘等。一般默认的是显示器。
#include<stdio.h>
#include<stdlib.h>
int main()
{
putchar(‘\n’);// 输出控制字符,如,一个换行符
putchar(‘s’);// 输出一个字符,不换行。
char a;//必须先在代码段开头定义变量,即不能边编程边定义变量(有的编程语言可以。)
a=‘B’;
putchar(a);// 输出字符变量的值
system(“pause”);
//return; // putchar()函数不返回任何值,return 0;返回整数值0。
}
putchar()可以输出一个字符,也可以输出变量的值,这个变量必须是保存了一个字符。
13.字符输入函数
字符输入函数getchar()在头文件stoid.h中声明。它的作用是从标准输入设备上(字符被输入到输入缓冲区)获取一个输入字符。标准输入设备是指键盘、触摸屏、手写板、扫描仪、磁盘或光盘等。它的返回值就是从输入设备上获取的字符。
看视频讲解。
所有的输入函数都可从输入缓冲区获取一个字符。
#include<stdio.h>
#include<stdlib.h>
int main()
{
char c;
c=getchar();//getchar()函数从输入设备获取字符并返回该字符,交给变量c。从键盘缓冲区获取一个字符。
putchar©;
putchar©;//说明putchar()函数只需要main()函数提供的c的复制值,而不修改c值。【即:putchar()函数是得到c的复制值,不是修改c的值】
system(“pause”);
}
运行后,光标闪烁,提示用户输入(从键盘键入的字符先存入键盘缓冲区,再转存到内存的输入缓冲区,回车后getchar()函数才开始接收字符,进而再保存到变量c的存储单元。);用户输入的字符被保存在输入缓冲区,main()函数调用getchar()函数,getchar()函数就是从输入缓冲区提取一个字符,交给变量c保存。接着,main()函数调用putchar()函数,系统再复制一个变量c,将它作为putchar()函数的局部变量,这样putchar()函数就能访问它了(将c的值输出到屏幕)。
【用户输入的字符并没有立即存放到内存的输入缓冲区,而是暂存在键盘缓冲区;只有按下回车键后才被送入内存的输入缓冲区;getchar()函数就是从输入缓冲区提取一个字符,交给变量c保存。从定义变量c开始,系统自动给c开辟单独的内存空间】
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
char ch;
ch=getchar();
putchar(ch);
putchar(‘\t’);
putchar(ch);
putchar(‘\t’);
putchar(ch);
putchar(‘\n’);
system(“pause”);
return;
} // ch=getchar();只是获取了字符a,所以3次输出a;
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
char ch;
ch=getchar();
putchar(ch);
putchar(‘\t’);ch=getchar();
putchar(ch);
putchar(‘\t’);ch=getchar();
putchar(ch);
putchar(‘\n’);
system(“pause”);
return; // putchar()函数不返回任何值,return 0;返回整数值0。
} // ch=getchar();每次分部获取一个字符A,B,C,所以3次输出后是A B C;
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
char ch;
ch=getchar();
putchar(ch);
ch=getchar();
putchar(ch);
ch=getchar();
putchar(ch);
printf(“\n”);
putchar(ch);// ch=getchar();只是获取了字符c,所以仍然输出C;
ch=getchar();//前图,获取字符D;后图获取回车符,所以换行;换行后执行printf(“程序结束了!”);
putchar(ch);
printf(“程序结束了!”);
system(“pause”);
return; // putchar()函数不返回任何值,return 0;返回整数值0。
}
最后一行输出,表明回车键也被送入栈区(后入先出),其它字符被送入输入缓冲区。在printf(“程序结束了!”);语句前,再加一次ch=getchar();putchar(ch);语句,看看输出结果。
14.函数的声明与定义
函数声明就是让编译器知道有个什么样的函数存在,以便编译器能够找到它,假如没有声明函数,那么可能会出现找不到函数的错误(警告1 warning C4013: “add”未定义;假设外部返回 int)。也可以没有函数声明,但必须把被调函数定义在主函数前面。举例如下:
#include<stdio.h>
#include<stdlib.h>
int add(int ,int );//声明函数,函数声明也叫函数原型;被调函数必须在main()函数前面先声明,否//则编译器编译时找不到该函数会发出警告。函数声明是一条语句,以;结束。
//编译器编译时,不需要具体参数名;只需函数类型、函数名称;参数个数、类型。
int main()
{
int x=add(1,2);
printf(“%d\n”,x);
system(“pause”);
}
int add(int x,int y) //定义函数,函数定义也叫函数实现;函数头—仅仅是函数的开始,所以没有封号
{
return x+y;
}
| 【总结】 |
第一:要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)。
方法2:自己取出缓冲区里的残留数据。
(说实话这个语句我也没看懂,呵呵!为什么格式控制是这样的!希望高手指点一下!)
scanf(“%[^\n]”,string);
第五章 数据类型
1.整型变量 Int , %d
2.长整型变量 long , %ld
3.无符号整型或无符号长整型变量 unsigned int ; %u; unsigned long, %lu
4.双长整型或无符号双长整型 long long ,unsigned long long ; %lld , %llu
5.短整型变量或无符号短整型变量 short, unsigned short; %hd, %hu
6.输出8进制数和16进制数 %o , %x
int a=16;
printf(“%o\n”,a); 字母O表示八进制,字母O而不是数字0
printf(“%x\n”,a); 字母x表示十六进制
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
int a=31;
printf(“%d\t%o\t%0x\n”,a,a,a);//十进制31分别以十进制、八进制、16进制输出。
system(“pause”);
return;
} //%o(八进制,字母O);%0x十六进制,数字0x,0X,x,X均可。
上例加#号时,输出语句及输出截图如下:
printf(“%d\t%#o\t%#0x\n”,a,a,a);//十进制31分别以十进制、八进制、16进制前缀#输出,以示区别。
printf(“o”);printf(“O\n”);//分别输出大小写字母o,以示与数字0的区别.
为了区分数字的进制,C语言规定用前缀来指明数字是哪一种进制。
输出数字格式前缀数字零(0)代表八进制;输出控制字符中字母o代表八进制
输出数字格式前缀数字零x(0x)代表十六进制;输出控制字符中数字零x(0x)代表十六进制.
要输出前缀,可在输出语句中字母o或字母x前添加#号
int a=16;
printf(“%#o\n”,a); 字母o表示八进制
printf(“%#x\n”,a); 字母x表示十六进制(x,X,0x,0X均可)
可以看出:
八进制输出中,数字前面多了一个零(0)
十六进制输出中,数字前面多了一个零x(0x)
这样,就可通过前缀来区分,是八进制数还是十六进制数。
7.为类型取个别名
#include<stdio.h>
#include<stdlib.h>
int main()
{
typedef unsigned short int US;// 将unsigned short int简化为US
US a=15,b=16,c=a+b;// US的作用与unsigned short int作用相同。不过短了很多
printf(“%#0x\t%#o\t%hu\n”,c,c,c);
system(“pause”);
}
8.浮点型变量概论
浮点型变量是用来存放浮点型数据的。如果将45.34交给浮点型变量来保存,它会分成3个部分来保存。45.34在内存中的存放形式如下图,存放形式是 .4534。
符号位:+表示正数,-表示负数;
指数:负数表示小数点向左移动位数,正数表示小数点向右移动位数。指数越大,小数点移动位数越多,那么,表示的数的范围越大。小数点最多能移动多少位,要看C编译系统给小数点分配多少内存。
按照精度的不同,浮点型变量又可分为单精度型,双精度型,长双精度型三种:
float a; //单精度浮点型变量
double b; //双精度浮点型变量
long double c; //长双精度浮点型变量
9.float型变量的取值范围 参见本章第22讲:22.十进制转二进制
指数:负数表示小数点向左移动位数,正数表示小数点向右移动位数。指数越大,小数点移动的位数越多,那么,表示的数的范围越大。小数点最多能移动多少位,要看C编译系统给小数点分配多少内存。float型变量占用4个字节的内存,即32位内存,那么C编译系统会给符号位和小数位分配24位,其它8位用来保存指数,即指数位占用8位内存。
C编译系统,符号位和小数位占24位,指数位占8位。而指数位也分正负,故指数位也有符号位,指数位只有7位用来表示范围大小。即-127~+127
小数的最大值约等于2.
2 IntelliSense: 浮点常量超出范围
10.double型变量的取值范围
11.long double型变量的取值范围
用sizeof()查看运行平台占用多少字节数的内存。
Long double型数据的输出:
%lf----字母l代表long,字母f表示浮点数float。常见的初始化long double型数据如下,
X=3.14L;x=3.14l;x=3.14; 数字后缀L,会把浮点型数据当做long double型数据看待,这样当数据很大的时候,编译器不会报警。
L后缀一般常用大写的L,因小写的字母l容易和数字1混淆。
12.浮点型变量的精度
13.超出精度的误差
Float型精度只能保证6位;double型小数点后也只有6位,且第六位也是不精确的。
#include<stdio.h>
#include<stdlib.h>
int main()
{
float x=31415929.12345678f;
double y=31415929.87654321;
printf(“%f\n”,x);
printf(“%f\n”,y);
printf(“%16.8f\n”,y);
printf(“%50.8f\n”,y);//宽度50位(整数+小数),小数8位。
printf(“%10.8f\n”,y);
printf(“%16.17f\n”,y);
system(“pause”);
}
31415930.000000
31415929.876543
31415929.87654321
31415929.87654321
31415929.87654321
31415929.87654320900000000
请按任意键继续. . .
小数点后数字表示指定小数点小数位数;
小数点前数字表示“整数+小数”所占的总位数;指定总位数小于实际总位数时指定无效,大于实际总位数时才有效,在屏幕输出占用字符宽度等于指定总位数,不足的部分在前面填充空格。如,实际数字为17位,指定总位数为50位,前面填充33个空格。
14.输出浮点型变量的值
%f—表示输出float型或double型的数据。要输出16进制的浮点型数据,要用%a或%A来代替f,前提是编译器要支持C99标准的十六进制分数。VC6.0编译器不支持C99标准。Visual Studio 2010编译器支持C99标准,即支持输出16进制的浮点型数据编译器
Float x=1.2f;如果把f去掉,即float x=1.2; 编译器会把它看做double型数据,那么就要用double型变量来保存。这样就有double x=1.2; 但是,如果后缀为L,就有double x=1.2L;那么编译器会把它看作是long double型数据,这样,我们就要用long double型变量来保存
Float x=1.2f;
float x=1.2; //编译器会把它看做double型数据,那么就要用double型变量来保存。就有:
double x=1.2;// 但是,如果后缀为L,就有:
double x=1.2L;// 编译器会把它看作是long double型数据,那么就要用long double型变量来保存。就有:
long double x=1.2L;//要输出long double型数据,就要用
(%lf) %Lf, 十进制形式
(%la) %La , (%La) %LA 十六进制形式
(%le) %Le 指数形式(指数计数法、科学计数法)
下面是float型数据输出的十进制形式、十六进制形式、指数形式
输出float型数据的形式:
%f , 十进制形式
%a , %A 十六进制形式
%e 指数形式(指数计数法、科学计数法)
下面是long double型数据输出的十进制形式、十六进制形式、指数形式
输出long double型数据的形式
(%lf) %Lf, 十进制形式
(%la) %La , (%La) %LA 十六进制形式
(%le) %Le 指数形式(指数计数法、科学计数法)
注意:float和double类型,都使用%f, %a ,%e来输出这两种类型数据的十进制形式、十六进制形式、指数形式。之所以都用一样的占位符,是因为在默认情况下,编译器会将浮点型float数据看作double类型。因此,在向printf()函数传递浮点型数据的时候,假如不加说明,会自动将其转换为double类型。
15.字符型变量
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch;//定义一个字符变量,取名ch,系统自动为其分配1个字节内存空间并在这个内存空间上贴上标签ch;
char ch1;
ch=97;//将ASCII值97赋给ch,系统便会到内存中寻找标签ch,然后在贴有ch的空间上存储97.
ch1=‘B’;
printf(“ch=%c\n”,ch);//%c告诉编译器这里输出的是字符
printf(“ch1=%d\n”,ch1); //%c告诉编译器这里输出的int类型整数。
//printf(“ch1=%d\n”,(int)ch1);为保证不出错,最好这样强制类型转换。输出是其拷贝值
system(“pause”);
}
字符类型,即char类型占一个字节内存空间,能表示的有符号整数范围是-128+127,能表示的无符号整数范围是0255。char能表示的int类型范围是-128~127;
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch1=128,ch2=383,ch3=-362;//char能表示的int类型范围是-128~127;报警内容如下截图。Ch2,ch3截断。
printf(“%d\n”,ch1+ch2); // 383+128=511,因511>127,所以511-2*256=-1
printf(“%d\n”,sizeof(char));
printf(“%d\n”,ch2);//因383>127,所以383-256=127
printf(“%d\n”,ch1);//因128>127,所以128-256=-128
printf(“%d\n”,ch3);//因-362<128,所以-362+256=-106
system(“pause”);
}
-1
1
127
-128
-106
请按任意键继续. . .
#include<stdio.h>
#include<stdlib.h>
int main()
{//将31~126共96个数字转换成字符
int i;
for(i=31;i<127;i++)
{
if((i+1)%10==0)
putchar(‘\n’);
printf(“%c”,(char)i);//i的整型值等效于ASCII值,转换成ASCII字符。
}
putchar(‘\n’);
system(“pause”);
}
16.数字与数字字符
数字零(0)的ASCII值仍然是零(0);
而数字字符零’0’的ASCII值是48;
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch1=0;
char ch2=‘0’;
printf(“%d\n%d\n”,(int)ch1,(int)ch2);
system(“pause”);
}
17.显式转换与隐式转换
显示转换是手动写代码进行的转换;
隐式转换是系统自动进行的转换。
Double ,float型转换成int型会丢失数据精度。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a=10/3;//取整后赋给a
float b=10/3;//取整后,自动转换成float型再赋给b
printf(“%d %f\n”,a,b);
printf(“%d %f\n”,10/3,10/3);//前者正确。后者0是错误的,也可能生成一个随机数。
printf(“%f %d\n”,10/3,10/3);//都是错误的。后者就生成一个随机数。
printf(“%d\n”,10 % 3);//求余数,即取模运算
printf(“%f\n%f\n%f\n%f\n”,(float)10/3,10.0/3,10/3.0,10.0/3.0);//前者强制类型转换。
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
float f=3.1415; //警告 1 warning C4305: “初始化”: 从“double”到“float”截断
int x=f;//隐式转换–编译器复制f并自动转换为3赋给x;转换后f的值不变
//警告 2 warning C4244: “初始化”: 从“float”转换到“int”,可能丢失数据
printf(“%d %f\n”,x,f);//格式符%f默认输出6位小数。
printf(“%f\n”,10/3);// 是错误的,也可能生成一个其它随机数。
system(“pause”);
}
printf(“%f\n”,10/3);
说明_____分析“错误”及纠正办法:printf();函数将两个整数相除的结果看作整数而不是浮点数,而使用%f来输出整数是非法的,其结果是未定义。
假如不使用强制转换运算符,可以这么做:
printf(“%f\n%f\n%f\n “,10.0/3,10/3.0,10.0/3.0);
使用强制转换运算符,可以这么做:
printf(”%f\n”,(float)10/3);
18.类型提升
使得数据范围变得更大—叫类型提升;如:char–int–float–double,这些类型转换都叫类型提升。
在表达式中无论是char还是short都会自动转换成int或unsigned int.一般在32位系统中会自动转换成int。而在16位系统中会自动转换成short,由于short和int一样大,所以unsigned short一定大于int绝对值,那么在这种情况下unsigned short就会转换成unsigned int。由于当前的计算机系统都是32位或者64位,所以在表达式中char和short类型的值无论有符号还是无符号,都会自动转换成int。举例如下:
Int main()
{
char ch1=12,ch2=108;
ch1+ch2; //在表达式中出现的自动类型提升
system(“pause”);
}//char类型占一个字节内存空间,能表示的有符号整数范围是-128+127,能表示的无符号整数范围是0255。char能表示的int类型范围是-128~127;
在计算表达式ch1+ch2;都会将ch1和ch2的char类型转换成int类型,然后再相加。由于ch1和ch2是转换成表示范围更大的类型,故而把这种转换叫类型提升。不光在表达式中会出现类型提升,在函数中也会出现类型提升。当作为参数传递给函数时,char和short类型会提升为int类型,而float类型则会提升为double类型。举例如下:
Int main()
{
char ch=’a’;
printf(“ch保存的ASCII码值: %d\n”,ch); //在函数中出现的自动类型提升
system(“pause”);
}
Char类型的ch作为参数复制一份自动传递给printf()函数,在printf()函数中char类型的ch自动转换为int类型,因此不用再将ch强制转换成int类型,就可以自动生成ch的整型值。
19.类型下降
在赋值语句中,右边的值的类型先转换为左边变量的类型再赋给左边的变量,这会导致左边变量的值的类型可能会提升也可能会下降(等级降低)。对于下降,大部分编译器会发出警告。假如丢失数据对精度没有影响,可用强制类型转换来消除警告。如果右值过大超出了左值的范围,那么强制赋值会导致左值溢出。
Int main()
{
Int d,e;
Double x=3.1415926, y=4294967296.1415926;
d=x; //在表达式中x出现的自动类型下降. 警告 1 warning C4244: “=”: 从“double”转换到“int”,可能丢失数据.
//d=(int)x;// 用强制类型转换来消除警告
e=y;// 警告1 warning C4244: “=”: 从“double”转换到“int”,可能丢失数据. 右值过大导致左值溢出
//e=(int)y;
system(“pause”);
}
20.特殊字符
\n 回车 + 换行 光标回到下一行行首
\r 回车 光标回到本行行首
\a 警告符 警告符
\b 退格符 回退一个空格
\f 换页符 切换到下一页的开头
\t 水平制表符
\v 垂直制表符
\’ 输出单引号
\”
?
\
\000(三个零)
表示一个8进制数所对应的ASCII字符(值)。如:
\0007,\007,\07,\7,\141都是八进制7及八进制141
\x61 表示一个16进制数所对应的ASCII字符(值)。
int main()
{
char ch=‘\a’;
printf(“%c\n”,ch);
system(“pause”);
}
int main()
{
char ch1=‘h’;
char ch2=‘o’;
char ch=‘\b’;
printf(“%c”,ch1);
printf(“%c”,ch2);
printf(“%c”,ch);
system(“pause”);
}
\f 换页符
\f ,\v ----只能在打印机中测试。
int main()
{
char ch1=‘’‘;
char ch2=’\”‘;
char ch3=’?';
printf("%c\n%c\n%c\n ",ch1,ch2,ch3);
system(“pause”);
}
21._Bool型变量
True,false。在C语言中对应1和0.
#include<stdio.h>
#include<stdlib.h>
define bool int
//# define true 1
//# define false 0
int main()
{
bool num=1;
int flag;//应该初始化flag。int flag=0;
if(num)
{
flag=1;
printf(“该睡觉了!\n”);
}
printf(“%d\n”,flag);
//system(“pause”);
getchar();//getchar();函数的作用是暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
光标闪烁,getchar();函数等待用户输入一个字符。//getchar();函数的作用是暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
将_Bool num=1;改为_Bool num=false;
什么都没输出。还有可能会出错:未定义变量false。
C语言中的布尔类型
在C语言中,是没有布尔类型的,0就是false,非0就是true。
用1/0表示:是/否(Y/N)、真/假(True/False)、开/关(on/off)、启动/停止(Start/Stop)。
于是,写习惯了Java/C#的我们自然会很不习惯,这个时候,我们不妨用宏定义来使我们的代码看起来更舒服一些。
#include<stdio.h>
#include<stdlib.h>
#define BOOL int
#define TRUE 1 //TRUE是符号常量。预先给常量1起一个别名TRUE,TRUE就是宏
#define FALSE 0 //FALSE是符号常量。预先给常量0起一个别名FALSE,FALSE就是宏
int main()
{
BOOL flag=TRUE;
if(flag)
{
printf(“true”);
}
else
{
printf(“false”);
}
putchar(‘\n’);
system(“pause”);
}
在C99中,长期缺乏布尔类型的问题得到的解决,但是在目前,C99标准还没有得到很好的推广。暂且不提。
22.十进制转二进制 参见本章第9讲:9.float型变量的取值范围
回顾:
整数部分除2取余(从低位到高位依次存放余数);
小数部分乘2取整(从高位到低位依次存放取整的数)。
总之,从小数点向两边发散(各散个的)。
如(45.625)10 = 101101.101
浮点数的类型分为:单精度浮点型(即float型),
双精度浮点型(即double型);
45.625
101101.101
本节:
符号位置
1 表示小数点的8位
指数位置(指数部分) Flaot型浮点数的小数部分(小数部分)占23位
#include<stdio.h>
#include<stdlib.h>
int main()
{
float sum=0,x=1.0;int n=0;
do
{
n+=1;
sum+=x;
x/=2;
}while(x>0.000001||sum<=1.999999);
printf(“sum=%f\n”,sum);
printf(“n=%d\n”,n);
getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
float sum=0,x=1.0;int i;
for(i=1;i<22;i++)
{
sum+=x;
x/=2;
}
printf(“sum=%f\n”,sum);
printf(“i=%d\n”,i-1);
getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
45.625是个正数,那么,在10000100(即132)前面放个0就可以了。
第9讲这样表示:
符号位:
1 小数位
23 指数位
8(指数也有符号位)
本讲这样表示:
符号位:
1 指数位
8(指数也有符号位) 指数位
23
23.二进制转十进制
24.宏
//# define sum 100的意思是:预先给常量100起一个别名sum
Int x=100;左边的x是变量,变量的值是可改变的,右边的100是常量,常量是不可改变的。常量不便于记忆,而且没有意义。因此,C语言容许我们给常量取个别名。比如说,
define sum 100 # define是预处理指令,sum是常量 100的别名,它是代表常量的。Sum就是宏。它是代替常量的标识符,此后凡是在本文件中出现的sum都是100。当然也可以给常量取个更有意义的别名,如, # define PRICE 10.5(10.5的别名叫PRICE,PRICE就是宏。凡是在本文件中出现的PRICE都会被编译器替换为10.5.)
PRICE又叫宏名,宏名后面就是宏体,也就是10.5,即10.5就是宏体。当这执行这条预处理指令# define时,会将所有的宏名替换为宏体。本条指令# define PRICE 10.5会将所有的PRICE替换为10.5。这项工作叫宏展开或叫宏替换。不管编译器编译成功与否,其后的PRICE都会被替换为10.5。PRICE和10.5都不能修改。PRICE也叫符号常量。用宏代替数字使程序更加易懂、知名见意、可以做到一改全改。我们看见PRICE就知道是价格,单独看见10.5就不知道它是什么。
#include<stdio.h>
#define PRICE 10.5
int main()
{
int num=20;
double money=PRICE*num;
printf(“20本《格林童话的售价为:%.2f\n”,money);
getchar(); //格式符%.2f中的•2f用来说明输出浮点数时显示小数点后两位。//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
对于宏,我们需要注意两点:
1、 不能对宏进行赋值(即修改);2、为了与变量区别,宏名应尽量大写。
#include<stdio.h>
#define PRICE 10.5
int main()
{
int num=20;
double money=PRICEnum;
//PRICE=20; //错误1 error C2106: “=”: 左操作数必须为左值
//2 IntelliSense: 表达式必须是可修改的左值
printf(“20本《格林童话的售价为:%.2f\n”,money);
getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
25.const常量
const常量与宏的区别:
const常量有数据类型,而宏没有数据类型。由于const常量有数据类型,所以编译器可以对const常量的类型进行安全检查,当发现const常量类型与实际数据类型不一致时,会发生警告。比如:将const float PRICE=20.00f;改为const int PRICE=20.00f;时,会产生警告:将float型常量转换为int型常量时可能会丢失数据。
PRICE是int类型常量,而20.00f是float类型数据,将数据20.00f赋给常量PRICE要进行类型转换,可能会丢失小数点后面的数据。所以会发出警告。
这是const常量的优点,当发现它的类型与值的类型不匹配时会发出警告;而宏没有数据类型,编译器无法对它进行安全检查。这样,当进行宏替换的时候,它不会产生警告,有可能发生不可预料的错误。如,将#define PRICE 20.00或#define PRICE 20.00f改为#define PRICE ‘x’
#include<stdio.h>
//#define PRICE 20.00//#define PRICE 20.00f
//#define PRICE ‘x’//虽然编译能通过。因宏没有数据类型,无法进行安全检查,这样在程序执行中进行宏替换时,会严格按照命令将PRICE替换为x(其ASCII值),而不管对与错,所以会产生不可预料的结果(错误)。
const float PRICE=20.00f;//PRICE是只读的,从此不能再对其赋值。
//除非用关键字EditorFor来取消只读属性.
//const int PRICE=20.50f;//常量类型与实际数据类型不匹配,发生警告。
int main()
{
int num=20;
double money=PRICEnum;
//PRICE=20;//PRICE是只读的,无法对其进行修改,所以会产生错误
printf(“20本《格林童话的售价为:%.2f\n”,money);
getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
26.枚举型常量 定义类型
枚举型常量: 就是将相同类型的常量一一列举出来。
enum num{zero,one,two,three,four};
关键字enum就是将其后的num声明为枚举类型。大括号内则列举了属于这个枚举类型num的所有符号常量,如,zero,one,two,three,four。他们分别代表0,1,2,3,4。
最后的符号;则代表了枚举类型num的定义结束。
枚举常量的默认值依次为:0,1,2,3,4…….
自定义枚举常量值:enum num{ten=10,one,two,three,four};
枚举常量ten值被定义为10,其后的枚举常量one,two,three,four的值依次为11,12,13,14。
又如: enum num{ten=10,one,two,three,four,twenty=20,twentyone,thirty=30};
关键字enum将其后的num声明为枚举类型,大括号中则列举了属于这个枚举类型num的所有符号常量,比如说{ten,one,two,three,four,twenty,twentyone,thirty。他们分别代表10,11,12,13,14,20,21,30。最后的封号”;”则不是枚举类型num的定义结束。
枚举类型的作用,看看下面例子:
#include<stdio.h>
int main()
{
enum money{fen,jiao,yuan,hundredyuan=100};
enum money lostmoney;//用枚举类型money来定义枚举变量lostmoney,其类型为money类型.
lostmoney=fen;//将枚举常量fen的值赋给枚举变量lostmoney
if(lostmoneyhundredyuan)
{
printf(“糟糕,丢失的是一张百元大钞!”);
}
else
{
printf(“丢失的不是一张百元大钞,不必担心。”);
}
getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
关键字enum定义枚举类型money。大括号中列出了属于money的4个枚举常量fen,jiao,yuan,hundredyuan。他们依次被初始化为0,1,2,100。
枚举类型:money----即,枚举类型的名称
枚举常量:fen,jiao,yuan,hundredyuan
枚举变量与枚举常量的区别:
Lostmoney是枚举变量,它的值是可以改变的,我们可对其进行赋值操作;
fen是枚举常量,它的值是不可改变的,我们不能对其进行赋值操作。
枚举常量:是在大括号中列出的常量;
枚举变量:是在大括号外部定义的变量。
#include<stdio.h>
#include<stdlib.h>
int main()
{
enum week{MON,TUE,WEDTHU,FRI,SAT,SUN};//monday,tuesday,wednesday,thureday,friday,saturday,sunday
enum week DayIs=MON;
if(DayIsSAT)
{
printf(“耶,我们又可以度周末了!\n”);
}
else
{
printf(“哎,又要上学了!\n”);
}
system(“pause”);
}
第六章 条件选择语句
1.if语句
if语句
从关键字if开始到封号” ; “结束—就是if语句。
#include<stdio.h>
//int main()
//{
// int x=100;
// if(x==0)
// printf(“x等于0\n”);//从关键字if开始到封号" ; "结束—就是if语句。
// printf(“x不等于0\n”);
// getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
//}
//int main()
//{
// int x=100;
// if(x==0); //; 也是一条语句
//从关键字if开始到封号" ; "结束—就是if语句。
// printf(“x等于0\n”);
// printf(“x不等于0\n”);
// getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
//}
//int main()
//{
// int x=100;
// if(x0)//x100?
// {
// printf(“x等于0\n”);
// printf(“x不等于1\n”);
// }//大括号内是复合语句(块语句),把它也看作一条语句。从关键字if开始到右大括号” } “结束—就是if语句。
// printf(“程序结束\n”);
// getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
//}
int main()
{
int x=100;
if(x100)//x0 ?
{
printf(“x等于0\n”);
printf(“x不等于1\n”);
}//大括号内是复合语句(块语句),把它也看作一条语句。从关键字if开始到右大括号” } “结束—就是if语句。
printf(“程序结束\n”);
getchar();//暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
2.else语句
if(x>y)
{
}
else
{
}
3. else if语句 多分支结构, 选择结构
if(score<60)
{ 不及格
}
else if( score<70)
{ 及格
}
else if(score<80 )
{ 中等
}
else if(score<90 )
{ 良好
}
else
{ 优秀
}
4.if语句的嵌套
#include<stdio.h>
int main()
{
int sex;
int choice;
printf(“测试恋爱性格:\n”);
printf(“下面有几种不同口味的巧克力,你最喜欢的是哪一种呢?\n”);
printf(“(1)酒心巧克力(2)扇贝巧克力(3)果仁巧克力:”);
scanf_s(“%d”,&choice);
printf(“请输入你的性别\n(1)男性(2)女性:”);
scanf_s(“%d”,&sex);
if(sex1)
{
if(choice1)
{
printf(“你是一个恋爱高手,很会讨女孩子喜欢。\n”);
}
else if(choice2)
{
printf(“你是一个有点胆小的人,总是担心自己不符合女朋友的要求。\n”);
}
else if(choice3)
{
printf(“你对女朋友一心一意,但她却经常看不出来。\n”);
}
else
printf(“你输入了一个错误的选项\n”);
}
else if(sex2)
{
if(choice1)
{
printf(“在恋爱中,你往往处于强势,掌握着发言权,男朋友只有乖乖地服从你。\n”);
}
else if(choice2)
{
printf(“你是一个浪漫的人,你会把最好的东西送给男朋友。\n”);
}
else if(choice3)
{
printf(“你是一个喜新厌旧的人,在外人眼里,你就是花心大萝卜。\n”);
}
else
printf(“你输入了一个错误的选项\n”);
}
else
printf(“输入了错误的性别\n”);
getchar();//暂时停留,等待用户输入。
system(“pause”);
}
5.if与else的配对
每个else语句都与它最近的if配对。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x;
printf(“请输入一个小于100的整数:”);
scanf_s(“%d”,&x);
if(x>0)
{
if(x<100)
printf(“x大于0小于100\n”);
}
else printf("x小于等于0\n");
getchar();//暂时停留,等待用户输入。
system("pause");
}
上述程序:当输入的0=<X<100运行正确;当输入的X>=100,运行也正确,什么都不返回,即不执行if……else……语句。而跳到getchar();等待用户输入一个字符。
去掉if后面的 { }
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x;
printf(“请输入一个小于100的整数:”);
scanf_s(“%d”,&x);
if(x>0)
if(x<100)printf("x大于0小于100\n");elseprintf("x小于等于0\n");
getchar();//暂时停留,等待用户输入。
system("pause");
}
分析:
当输入的X>=100时,输出信息不符合输入数据。
当输入的X<=0,运行也正确,局部程序可看作如下:根据else就近原则,与最近if配对。
if(x>0)
{
if(x<100)
printf(“x大于0小于100\n”);
else
printf(“x小于等于0\n”);
}
getchar();//暂时停留,等待用户输入。
进行if(x>0)判断,因输入的X<=0,不执行大括号内的语句,而跳到getchar();等待用户输入一个字符。
当输入的X>=100时,进行if(x>0)判断,大括号内的语句才被执行。大括号内继续进行判断,当然是输出错误信息。
如何改正:
If语句后面最好用大括号括起来,即使有一条语句也要这样。即使用复合语句----“块”结构形式的语句。
if(x>0)
{
if(x<100)
printf(“x大于0小于100\n”);
}
else
printf(“x小于等于0\n”);
getchar();//暂时停留,等待用户输入。
这样就与最开始编写的程序一样:功能是判断输入的数是否是0到100之间的数。
上述程序:当输入的0=<X<100运行正确;当输入的X>=100,运行也正确,什么都不返回,即不执行if……else……语句。而跳到getchar();等待用户输入一个字符。
总结:从关键字if开始到封号" ; “结束—就是if语句。
每个else语句都就近与if语句配对。添加大括号则可以改变配对关系。
6.复杂的嵌套
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
float num;
printf(“请输入该生当月的消费额:\n”);
scanf_s(”%f",&num);
if(num>=0)
{
if(num0)
{
printf(“零消费额。\n”);
}
else
{
if(num>=1000)
{
printf(“高消费额。\n”);
}
else if(num>500)
{
printf(“中等消费额。\n”);
}
else
printf(“低消费额。\n”);
}
}
else
printf(“该生不光没有消费,反而挣了%.2f元。\n”,fabs(num));
getchar();//暂时停留,等待用户输入。
system(“pause”);
}
2. 逻辑
1.逻辑与
#include<stdio.h>
#include<stdlib.h>
int main()
{
int age;
char sex;
printf(“please input age :\n”);
scanf(“%d”,&age);
printf(“please input sex :\n”);
scanf(“%d”,&sex);
if((sex’f’ && age>=50)||(sex==‘m’ && age>=60))
printf(“你可以退休了!\n”);
else
printf(“你还得继续工作!\n”);
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int money;
char looks;
printf(“请输入财富值(万元):”);
scanf(“%d”,&money);
getchar();//getchar()提取缓冲区的回车符并抛弃掉,以消除上次回车符对下次字符输入函数的影响。如果此处没有此语句,输入任何一个整数并回车后,直接执行下一条printf()语句,接着执行scanf(“%c”,&looks);语句时而不停留下来等待输入, scanf()函数直接提取缓冲区的回车符,判断后不符合其他条件,因此直接执行最后两条语句:printf(“不能嫁给你!\n”); system(“pause”);见截图。
printf(“请输入你的长相。1、帅(y);2、不帅(n): “);
scanf(”%c”,&looks);// 此处只能用scanf(),而不能用scanf_s(),否则执行到scanf_s()时直接结束程序。
if(money>=100&&looks==‘y’)
{
printf(“可以嫁给你!\n”);
}
else if((money>=10 && money<100)&&looks==‘y’)
{
printf(“首先考虑!\n”);
}
else if((money>=10 && money<100)&&looks==‘n’)
{
printf(“需要考虑考虑-1!\n”);
}
else if(money<10 &&looks==‘y’)
{
printf(“需要考虑考虑-2!\n”);
}
else
{
printf(“不能嫁给你!\n”);
}
system(“pause”);
}
2.逻辑或
#include<stdio.h>
#include<stdlib.h>
//该女的择偶标准
int main()
{
int money;//财富值
char looks;//外表帅/不帅
printf(“你有多少钱? “);
scanf_s(”%d”,&money); //注释⑴
getchar();//注释⑵
printf(“你帅不帅?(y)帅(n)不帅: “);
scanf_s(”%c”,&looks); //注释⑶,⑷
if(money>=1000000 || looks==‘y’)
{
printf(“可以嫁给你。\n”);
}
else
printf(“还得再考虑考虑。\n”);
getchar();//暂时停留,等待用户输入。
system(“pause”);
}
注释:
⑴//用户输入money后会按Enter键,它是换行符,换行符不会被money所保存。%d告诉编译器,忽略空白字符直接匹配数字。空白字符是指空格、换行符、制表符等显示为空白的字符。因此换行符没有被变量money所保存,而是保存在输入缓冲区,以便下次输入时使用。假如我们不把换行符从输入缓冲区提取出来,就会影响下次输入。
⑵// getchar()函数作用就是从输入缓冲区中提取换行符并切扔掉,使其不影响下次字符输入。如果没有getchar();无论输入什么,结果都是执行最后的打印输出语句,得出错误结论。//getchar()提取缓冲区的回车符并抛弃掉,以消除上次回车符对下次字符输入函数的影响。
⑶//%c告诉编译器,不要忽略任何字符。如果上面不调用getchar();函数,那么换行符就会被scanf_s();函数当作输入的内容提取出来,%c告诉编译器不要忽略该字符,因此会将其该字符保存到looks变量中,这显然不是本程序的目的。looks是用来保存y或n,因此为使looks不保存换行符,必须调用getchar();函数。%c只能用scanf(),而不能用scanf_s(),否则执行到scanf_s()时直接结束程序。
⑷%c区分大小写,只能小写。%C编译器不能检查出错误,但运行时报错。Run-Time Check Failure #2 - Stack around the variable ‘looks’ was corrupted.
3.逻辑非
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x;
printf(“请输入一个整数:”);
scanf_s(“%d”,&x);
if(!x0)//逻辑非的运算符优先级高于关系运算符
{
printf(“x不等于0\n”);
}
else
printf(“x等于0\n”);
system(“pause”);
}
3.括号改变优先级
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=1,y=0,z=0;
if(x0 && (y0|| z0))// 关系运算符的优先级高于逻辑与运算符.要想改变优先级,可加小括号;去掉(),改变了逻辑运算结果if(x0 && y0|| z0)。
{
printf(“条件满足\n”);
}
else
printf(“条件不满足\n”);
system(“pause”);
}
4.真与假
C语言中,是没有布尔类型的,只有真和假,0就是false,非0就是true。
0值— — 否,假;
非0值-----是,真;
Int x=0;
If(x) //小括号中的x是个表达式。如果X不为零,那么表达式的值为真,if条件满足;如果X为零,那么表达式的值为假,if条件不满足。 这是喜欢卖弄程序员的写法,不建议。
{
}
推荐 清晰写法。比如,if(x!=0),if(x0)
另外:if(!x) //小括号中的!x是个表达式。如果X为零,那么表达式!x的值为真,if条件满足;如果X不为零,那么表达式!x的值为假,if条件不满足。 这是喜欢卖弄程序员的写法,不建议。
#include<stdio.h>
#include<stdlib.h>
//int main()
//{
// int x=0;
// if(x==0) // if(!x)
// {
// printf(“x为假\n”);
// }
// else
// {
// printf(“x为真\n”);
// }
// system(“pause”);
//}
int main()
{
int x=0;
if(x!=0) //if(x)
{
printf(“x为真\n”);
}
else
{
printf(“x为假\n”);
}
system(“pause”);
}
5.三目运算符
1.三目运算符
编写一个求绝对值的函数:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x,y;
printf(“请输入一个整数:”);
scanf_s(“%d”,&x);
/if(x<0)
{
y=-x;
}
else
{
y=x;
}/
y=(x<0)?-x:x;
printf(“该数的绝对值为:%d\n”,y);
getchar();//getchar()提取缓冲区的回车符并抛弃掉,以消除上次回车符对下次字符输入函数的影响。此处可以省略getchar();函数。
system(“pause”);
}
编写一个求两个整数中的较大值函数:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x,y,max;
printf(“请输入第一个整数:”);
scanf_s(“%d”,&x);
printf(“请输入第二个整数:”);
scanf_s(“%d”,&y);
max=(x>y)?x:y;
printf(“%d和%d中较大的值是:%d\n”,x,y,max);
system(“pause”);
}
由于printf( )函数可以输出一个值,而三目运算符运算结果就是一个值,所以可以按照下面这样来做。
printf(“%d \n”,(x>y)?x:y);
2.三目运算符的优先级
多个三目运算符可以出现在同一行语句中。
#include<stdio.h>
#include<stdlib.h>//不加此预编译指令,语句system(“pause”);编译时会出错和警告
//出错2 IntelliSense: 未定义标识符 “system”
//警告 1 warning C4013: “system”未定义;假设外部返回 int
int main()
{
int x=1,y=2,z;
z=x>y?x:x>y?x:y;// 三目运算符的执行方向依次从右到左,该语句相当于
//z=x>y?x:(x>y?x:y);
printf(“z=%d\n”,z);
system(“pause”);
}
求三个整数中的最大值。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x=7,y=9,z=3,max;
max=(z>(x>y?x:y))?z:(x>y?x:y);// 三目运算符的执行方向依次从右到左
//
printf(“max=%d\n”,max);
system(“pause”);
}
3.灵活运用三目运算符
由于printf( )函数可以输出一个值,而三目运算符运算结果就是一个值,所以可以按照下面这样来做。
printf(“%d \n”,(x>y)?x:y);
求两个整数中的大数。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x,y;
printf(“请输入第一个整数:”);
scanf_s(“%d”,&x);
printf(“请输入第二个整数:”);
scanf_s(“%d”,&y);
/if(x>y)
{
printf(“大数是%d\n”,x);
}
else
{
printf(“大数是%d\n”,y);
}/
printf(“大数是%d\n”,(x>y)?x:y);
//如果x>y,三目运算式的值为x,否则三目运算式的值为y。
//printf(“大数是%d\n”,x>y?x:y);
system(“pause”);
}
4.三目运算符的操作数类型
三目运算符允许对不同类(型)别的值进行操作。
可以同时操作一个浮点型变量和一个整型变量。比如说:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a=1;
float b=2.1; //注释⑴
//float b=2.1f; //消除告警
printf(“%f\n”,(a>b)?a:b);//注释⑵转换为变量级别最高的类型
//float b=2.1;//编译器会把2.1当作double型, double型处理为float型,这就是报警原因。
//float b=2.1f;//编译器会把2.1当作float型,正好与b类型一致,这样,编译时就消除了警告。
//printf(“%d\n”,a>b?a:b);
system(“pause”);
}
注释:
⑴//编译时有告警。告警内容为:警告1 warning C4305: “初始化”: 从“double”到“float”截断。因为C语言编译系统会将浮点型常量作为双精度来处理。如果在浮点型常量末尾加上f,这样编译系统方才当作单精度来处理。
⑵//将a和b同时转换为它们级别最高的类型,也就是浮点数类型;然后才对它们进行求值操作,求出浮点型变量b的值,即整个三目运算式的值,接着用printf()函数输出在屏幕上。该程序编译后会告警。
5.三目运算符最常见的用法
表达式1?表达式1:表达式2
a>b?a:b
a>b?a:b>c?b:c 错误
即:a>b?a:(b>c?b:c) 错误
即:(a>b?a:b)>c? (a>b?a:b):c 正确
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a=12,b=9,c=13,max;
max=a>b?a:b>c?b:c;// 三目运算符的执行方向依次从右到左a>b?a:b>c?b:c
printf(“max=%d\n”,max);
system(“pause”);
}
max=12
请按任意键继续. . .
//结果错误。max=a>b?a:b>c?b:c;应该改写为:(a>b?a:b)>c? (a>b?a:b):c 正确
// a>b?a:b>c?b:c; 错误
// a>b?a:(b>c?b:c) 错误
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a=12,b=9,c=13,max;// 三目运算符的执行方向依次从右到左
max=a>b?a:b>c?b:c;// 错误
printf(“max=%d\n”,max);
printf(“max=%d\n”,a>b?a:(b>c?b:c));// 错误
printf(“max=%d\n”,(a>b?a:b)>c? (a>b?a:b):c);// 正确
system(“pause”);
}
max=12
max=12
max=13
请按任意键继续. . .
#include<stdio.h>
#include<stdlib.h>
int main()
{//如果是大写字母,就转换成小写字母。
char ch1,ch2;
printf(“请输入一个字母:\n”);
scanf_s(“%c”,&ch1); //?
printf(“%c\n”,ch2=(ch1>=‘A’&&ch1<=‘Z’)?(ch1+32):ch1);
system(“pause”);
}
6.switch语句
if语句中,如果选择条件过多,大量的if…else语句会使代码看上去更加混乱。
switch()语句是用来检查小括号中表达式的值是否与所有case后面表达式之一的值相等,如果相等则执行该case后面表达式相关联的语句。遇到break()语句就退出switch()语句。如果switch()语句小括号中表达式的值与所有case后面表达式的值都不相等,则执行默认分支default标号后面的语句。如果switch()语句小括号中表达式的值与所有case后面表达式的值都不相等,也没有默认分支default 语句,switch()语句自动结束。
#include<stdio.h>
#include<stdlib.h>
int main()
{
float a,b,result;//result=ab
char ch;
printf(“模拟运算小程序:\n”);
printf(“请输入第一个数:\n”);
scanf_s(“%f”,&a);
getchar();//注释⑴。//getchar()提取缓冲区的回车符并抛弃掉,以消除上次回车符对下次字符输入函数的影响。
printf("请输入运算符(±/):\n");
scanf(“%c”,&ch);//注释⑵
printf(“请输入第二个数:\n”);
scanf_s(“%f”,&b);
switch(ch)//注释⑶
{
case ‘+’:result=a+b; break;
case ‘-’:result=a-b; break;
case '':result=ab; break;
case ‘/’:
if(b!=0)
{
result=a/b; break;
}
else
{
result=0; break;
}
default:result=0.0f;
}
printf(“%.2f%c%.2f=%.2f\n”,a,ch,b,result);
system(“pause”);
}
注释:
⑴ 用户输入第一个数后会按下回车键,这个回车键会保存到输入缓冲区。为了不使回车键字符影响到下次输入(回车键字符对后面程序中的%c有影响),我们需要将回车键字符从输入缓冲区提取出来。直接调用getchar()函数,来提取输入缓冲区中的回车键字符而不赋给任何字符变量并抛弃掉,因回车键字符没有赋给任何字符变量,所以回车键字符被抛弃掉。//getchar()提取缓冲区的回车符并抛弃掉,以消除上次回车符对下次字符输入函数的影响。
⑵ 输入运算符保存到变量ch中;这里没有调用getchar()函数,是因为下面的%f会忽略回车键字符。输入%c时,如果用 scanf_s( );结果总是错误。(运算符的位置总是’a’,结果总是0)。即,此处只能用scanf(),而不能用scanf_s(),否则执行到scanf_s()时直接结束程序。
⑶ switch()语句检查ch的值是否等于某个case的值。比如,ch=+,执行+号之冒号后面的语句…,用break语句来退出switch()语句。
⑷ 默认分支,如果小括号中表达式的值与case后面所有常量表达式的值都不相等,那么执行default分支的语句。因为没有执行四则运算,所以设置result=0;假如,没有result默认分支,执行到这里时switch()语句自动结束。
#include<stdio.h>
#include<stdlib.h>
int main()
{//语文、数学、英语成绩YuScore、ShuScore、YingScore、YingChar
int YuScore,ShuScore,YingScore;
char result;
printf(“请输入各科成绩:”);
scanf(“%d\t%d\t%d”,&YuScore,&ShuScore,&YingScore);
//getchar();回车符只是对以后的%c有影响。而以后程序中没有输入函数的%c,故此getchar();可省略。
if(YuScore+ShuScore+YingScore>=270)
{
result=‘A’;
}
else if(YuScore+ShuScore+YingScore>=240)
{
result=‘B’;
}
else if(YuScore+ShuScore+YingScore>=210)
{
result=‘C’;
}
else if(YuScore+ShuScore+YingScore>=180)
{
result=‘D’;
}
else
{
result=‘E’;
}
switch(result)
{
case ‘A’:printf(“A优秀!\n”);break;
case ‘B’:printf(“B良好!\n”);break;
case ‘C’:printf(“C中等!\n”);break;
case ‘D’:printf(“D及格!\n”);break;
default:printf(“不及格!\n”);break;
}
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{//语文、数学、英语成绩YuScore、ShuScore、YingScore、YingChar
int YuScore,ShuScore,YingScore;
char YingChar,result;
printf(“请输入各科成绩:”);
scanf_s(“%d\t%d\t%c”,&YuScore,&ShuScore,&YingChar);//%c不能写成%C,否则:Run-Time Check Failure #2 - Stack around the variable ‘YingChar’ was corrupted.
getchar();//此处可以省略,因getchar();可以避免对以后字符输入函数的影响。
YingScore=(int)YingChar;
if((YuScore+ShuScore>=180)&&YingScore<=65)
{
result=‘A’;
}
else if((YuScore+ShuScore>=160)&&YingScore<=66)
{
result=‘B’;
}
else if((YuScore+ShuScore>=140)&&YingScore<=67)
{
result=‘C’;
}
else if((YuScore+ShuScore>=120)&&YingScore<=68)
{
result=‘D’;
}
else
{
result=‘E’;
}
switch(result)
{
case ‘A’:printf(“A优秀!\n”);break;
case ‘B’:printf(“B良好!\n”);break;
case ‘C’:printf(“C中等!\n”);break;
case ‘D’:printf(“D及格!\n”);break;
default:printf(“不及格!\n”);break;
}
system(“pause”);
}
18.去掉break的switch语句
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch;
printf(“请输入分数等级(A、B、C、D、E):”);
scanf(“%c”,&ch); //此处只能用scanf(),而不能用scanf_s(),否则执行到此处直接结束程序。
switch(ch)
{
case ‘A’:printf(“90~100分的有2人,\n”);
case ‘B’:printf(“80~89分的有12人,\n”);
case ‘C’:printf(“70~79分的有24人,\n”);
case ‘D’:printf(“60~69分的有18人,\n”);
case ‘E’:printf(“60分以下的有32人,\n”);
}
system(“pause”);
}
//如收入B,B被ch保存,switch(ch)检查ch的值,发现与case ‘B’:行的值相等,于是执行该行后面的语句,由于没有遇到break;语句,直到switch(ch)语句执行完为止。
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch;
printf(“请输入分数等级(A、B、C、D、E):”);
scanf(“%c”,&ch); //此处只能用scanf(),而不能用scanf_s(),否则执行到此处直接结束程序。
switch(ch)
{
case ‘A’:printf(“90~100分的有2人,\n”); break;
case ‘B’:printf(“80~89分的有12人,\n”); break;
case ‘C’:printf(“70~79分的有24人,\n”); break;
case ‘D’:printf(“60~69分的有18人,\n”); break;
case ‘E’:printf(“60分以下的有32人,\n”); break;
}
system(“pause”);
}
//如收入B,B被ch保存,switch(ch)检查ch的值,发现与case ‘B’:行的值相等,于是执行该行后面的语句,直到遇到break;语句才跳出switch(ch)分支语句。
switch(ch) //switch()语句检查ch的值是否等于某个case的值。比如,ch=B,执行该case语句后面相关联的语句…,用break语句来退出switch()语句。
第七章 循环语句
goto语句
是计算机最古老的语句之一,C语言也有此语句。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=1,sum=0;
number:sum+=i;
i++;
if(i<=100)
{
goto number;
}
printf(“从1加到100的和是:%d\n”,sum);
system(“pause”);
}
慎用goto语句
会导致许多不易察觉的错误,使程序看起来不那么严密、比较松散。
但是,有些地方使用goto语句会使程序流程更简洁、更清晰、效率更高。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=1;
if(i<10)
{
goto label;
}
printf(““);
i++;
goto label;
printf(”\n程序结束\n");
printf(“***********”);
label:;
system(“pause”);
}
程序什么也不执行而直接跳到label:; 此程序有两个label.
变换一下,仍然什么也不输出。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=1;
if(i>10)//原来是<号
{ //把用下面的两条语句替换掉goto label;语句。
printf("”);
i++;
}
else
goto label;
printf(“\n程序结束\n”);
printf(“***********\n”);
label:;
system(“pause”);
}
1、while语句
与if语句的区别是:if语句只执行一遍。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=1,sum=0;
while(i<=100)//表达式的值为真,执行循环体语句;直到i>100为止
{
sum+=i;
i++;
}
printf(“从1加到100的和是:%d\n”,sum);
system(“pause”);
}
2-1、带逻辑运算符的while语句
#include<stdio.h>
#include<stdlib.h>
int main()
{
//工资统计
float sum=0;//所有员工工资总和
float wage=0;//某个员工工资初始值. wage[weɪdʒ]n. 工资;代价;报偿
char choice=‘y’;// 'y’或’Y’表达式的值为真
int i=1;//员工编号
printf(“平均工资统计程序\n”);
while(choice==‘y’||choice==‘Y’)//表达式的值为真,执行循环体语句;直到i>100为止
{
printf(“请输入第%d名员工的工资:”,i);
scanf_s(“%f”,&wage);
getchar();//避免对下面输入函数中%c的影响. //getchar()提取缓冲区的回车符并抛弃掉,以消除上次回车符对下次字符输入函数的影响。
sum+=wage;
i++;
printf(“继续输入请按y,结束输入请按n:”);
scanf(“%c”,&choice);//此处只能用scanf(),而不能用scanf_s(),否则执行到scanf_s()时直接结束程序。
}
printf(“%d名员工的工资合计为:%.2f\n”,i-1,sum);
printf(“%d名员工的平均工资为:%.2f\n”,i-1,sum/(i-1));
system(“pause”);
}// 字符型输入只能用scanf(),而不能用scanf_s(),否则执行到scanf_s()时直接结束程序。
2-2、限定while循环的次数
#include<stdio.h>
#include<stdlib.h>
int main()
{
float sum=0;//所有员工工资总和
float wage=0;//某个员工工资初始值
int num;//员工总数
int i=1;//员工编号
printf(“平均工资统计程序\n”);
printf(“请输入参加统计的员工数目:”);
scanf_s(“%d”,&num);
printf(“总共需要输入%d名员工的工资:\n”,num);
while(i<=num)//表达式的值为真,执行循环体语句;直到i>100为止
{
printf(“请输入第%d名员工的工资:”,i);
scanf_s(“%f”,&wage);
getchar();//getchar();只是抛弃上次回车符。
sum+=wage;
i++;
}
printf(“%d名员工的工资合计为:%.2f\n”,num,sum);
printf(“%d名员工的平均工资为:%.2f\n”,num,sum/num);
printf(“员工总数num=i-1=%d\n”,i-1);
system(“pause”);
}
3、continue语句
执行到循环体的某处跳到循环的开始重新执行循环。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=0;
while(i<3)
{
i++;
if(i==1)
continue;//直接跳转到循环的开头,继续执行下次的循环,即或略后面的语句。
printf(“i的值为%d\n”,i);
}
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=0;
while(i<3)
{
i++;
if(i==1)
{
continue;//直接跳转到循环的开头,继续执行下次的循环,即或略后面的语句。
printf(“i的值为%d\n”,i);
}
}
system(“pause”);
}
总结:continue;不执行本次循环后面的语句,而是跳转到循环的开头,继续执行下次的循环。
4、reak语句
强制退出循环,转而执行循环体后面的语句。
break;只是退出循环不是退出程序,因此循环体后面的语句会继续执行。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=0;
while(i<3)
{
i++;
if(i1)
break;//强制退出循环,转而执行循环体后面的语句。
printf(“i的值等于%d\n”,i);
}
printf(“i的值为%d\n”,i);
system(“pause”);
}
5、exit函数
exit函数可终止程序的运行。直接退出整个程序。
Exit()函数是个库函数,要在stdlib标准库中声明。因此,要在程序开头的头文件中加一条#define<stdlib.h>预处理指令来包含exit函数。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=0;
while(i<3)
{
i++;
if(i1)
exit(0);//exit函数可终止程序的运行,直接退出整个程序,所以没有输出
printf(“i的值等于%d\n”,i);
}
printf(“i的值为%d\n”,i);
system(“pause”);//getchar(); return 0;运行效果都是一闪而过。getchar();只是抛弃上次回车符。老师的:没有输出。
}
注意:exit(0);和exit;的区别
exit();是个参数函数,至少要有一个参数0;
exit;会警告:警告 1 warning C4550: 表达式计算为缺少参数列表的函数
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i=0;
while(i<3)
{
i++;
if(i==1)
//exit(0);//exit函数可终止程序的运行,直接退出整个程序,所以没有输出
exit;// 会警告:警告 1 warning C4550: 表达式计算为缺少参数列表的函数
printf(“i的值等于%d\n”,i);
}
printf(“i的值为%d\n”,i);
system(“pause”);//getchar(); return 0;运行效果都是一闪而过。getchar();只是抛弃上次回车符。
}
6、查阅exit函数的声明
Exit(0)—传递0时,代表程序正常终止;
Exit(1) —传递1时,代表程序某处发生了错误;
Exit( )函数还有两个宏。
Exit(EXIT_SUCCESS) 和 Exit(EXIT_FAILURE)
选中—右键----转到定义处。
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
因此,可将EXIT_SUCCESS传递给Exit()函数,即Exit(0),代表程序正常终止;
也可以将EXIT_FAILURE传递给Exit()函数,即Exit(1), 代表程序某处发生了错误;
7、猜数字
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{//srand函数是随机数发生器的初始化函数。原型:void srand(unsigned int seed);
// srand和rand()配合使用产生伪随机数序列。seed [siːd] n. 种子
int i,j; // 设置种子
srand((unsigned)time(NULL)); // 随机数发生器的初始化函数。系统提供的生成伪随机数序列的种子。
for(i = 0; i < 10; i++ )/* 生成10个随机数 */
{
j= rand(); // 生成实际的随机数
printf(“随机数:%d \n” ,j );
}
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int i; // 设置种子
srand((unsigned)time(NULL)); //生成伪随机数序列的种子
for(i=0;i<10;i++) /* 生成10个随机数 */
{
printf(“%d\n”,rand()); // 生成实际的随机数
}
system(“pause”);
}
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
short number, guess=0; // [ges]
srand((unsigned)time(NULL));// 随机数发生器的初始化函数。系统提供的生成伪随机数序列的种子。
number=rand() % 100;//032767除100的余数在099之间。根据种子的值产生0~99之间的随机数
number++;//使得number在1~100之间
printf(“猜数字游戏\n”);
printf(“该数字在1到100之间\n”);
while(guess!=number)
{
printf(“请输入你所猜的数字:\n”);
scanf_s(“%d”,&guess);
if(guess<number)
{
printf(“小了:\n”);
}
if(guess>number) //此处若用else,即使猜对了,下面的打印输出语句也要执行一次,因此语句执行完以后,才能判断猜对与否。
{
printf(“大了:\n”);
}
}
printf(“猜对了,这个数字就是:%d\n”,number);
system(“pause”);
}
8、 永不休止的while循环
看视频(上述猜数字程序,如果没有输入语句就是死循环)
9、do…while循环
#include<stdio.h>
#include<stdlib.h>
int main()
{
int many;
printf(“你想看几次?\n”);
scanf_s(“%d”,&many);
/while(many>0)
{
printf(“奇迹多在厄运中出现–培根\n”);
many–;
}/
do
{
printf(“奇迹多在厄运中出现–培根\n”);
many–;
}while(many>0);
printf(“程序执行完毕,再见。\n”);
system(“pause”);
}
10、for循环
#include<stdio.h>
#include<stdlib.h>
int main()
{
int many,count;
printf(“你想看几次?”);
scanf_s(“%d”,&many);
/count=0;
while(count<many)
{
printf(“挫折其实就是迈向成功所应缴的学费。\n”);
count++;
}/
for(count=0;count<many;count++)
{
printf(“挫折其实就是迈向成功所应缴的学费。\n”);
}
printf(“程序执行完毕,再见。\n”);
system(“pause”);
}
11、 for循环的注意细则
for语句注意事项:
C90标准规定,循环变量的声明必须在循环语句之前。
C99标准变了,它允许在for循环的小括号中声明或定义循环变量。
在VS2010中,若for(int count=0;count<many;count++)将出现8条错误和1条警告。
你的编译器必须支持某一标准。
比如说:
visualC++6.0编译器就不支持C99标准。
Gcc编译器支持C99标准。Dec-C++是集成了Gcc的集成开发环境,当然就支持C99标准,网上可下载到。
如何安装—不说了。如何新建工程?
文件—新建—工程§—console Application(名称,单选工程)—确定-Create new project(文件名,保存类型)—保存—将先前VS2010中的代码复制过来。
编译错误:C99模式没有打开。----工具----编译选项----勾选:在编译时加入以下命令。-----加入命令:-std=c99----确定-----然后重新编译运行。“运行”®---- 编译运行( )
VS2010中使用C语言,VS2010编译器不支持C99标准。
#include<stdio.h>
int main()
{
int many,count;
printf(“你想看几次?”);
scanf_s(“%d”,&many);
for(count=0;count<many;count++)
{
printf(“挫折其实就是迈向成功所应缴的学费。\n”);
}
printf(“程序执行完毕,再见。\n”);
getchar();//上次回车符被保存在输入缓冲区,被getchar()函数提取了出来并被抛弃。类似退格键。
getchar();//这里是起到暂停的作用,等待输入字符。若没有此语句,程序一闪而过。因为,没有暂停。
}
//调用getchar();函数来接收用户输入的字符。此函数可起到暂停的作用。输入many时,输入的数字被保存在many中,回车键字符被保存在输入缓冲区,被getchar()函数提取了出来并被抛弃—即getchar()可消除上次回车符对下次字符输入函数的影响。。因此想要程序暂停一下,还要调用一次getchar()函数。第二次调用getchar();函数就是停留等待输入。
建议在for循环外面定义循环变量。
看视频
12、域
C语言规定每对{ }直接为一个域,每个域中可以声明或定义变量,该变量的作用域就是该对大括号之间。即,在一对大括号中声明或定义的变量只能在这对大括号中使用,不能在该对大括号外面使用。举例如下:
#include<stdio.h>
int main()
{
int i;
for(i=0;i<3;i++)
{
int j=100;
printf(“在for循环中,输出j的值:%d\n”,j);//如果在大括号外使用j,就会告警:没声明的标识符。
}
getchar();//getchar();函数的作用是暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
getchar();//getchar();函数的作用是暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
告警时程序:
#include<stdio.h>
int main()
{
int i;
for(i=0;i<3;i++)
{
int j=100;
}
printf(“在for循环中,输出j的值:%d\n”,j);//在大括号外使用j,出现错误:“j"没声明的标识符。未定义标识符"j”。
getchar();//getchar();函数的作用是暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
getchar();//getchar();函数的作用是暂时停留,等待用户输入。因为上面没有输入函数产生的回车符。
}
错误1 error C2065: “j”: 未声明的标识符
2 IntelliSense: 未定义标识符 “j”
16.灵活的for循环
for循环可以对多个循环变量进行赋值和增减运算;赋值表达式和增减表达式之间用逗号分隔。举例如下:
#include<stdio.h>
int main()
{
//for循环可以对多个循环变量进行赋值和增减运算;赋值表达式和增减表达式之间用逗号分隔。
int x,y,z;
for(x=0,y=0,z=0;x<3;x++,y++,z++)
{
printf(“x=%d,y=%d,z=%d\n”,x,y,z); //此大括号可以省略。
}
getchar();//等待输入字符
getchar();//等待输入字符
}
循环条件表达式也可以用逻辑表达式等表示。如,x<3,根据题意也可以是y<4&&x<3,或者y<4&&x<3&&z<5(结合方向是:自左至右;如果是y<2&&x<3&&z<5,根据自左至右,只能输出0和1,就改变了题意。)等,是几个条件同时满足的与表达式,结果不变;即,是几个集合的交集。若用或表达式,可用以下列出之一,x<3||z>4||y>4,x<3||z>3||y>3,(结合方向是:自左至右;前两个表达式中的z,y至少是大于3);z<3||x<3||y<3。
//x<3||z>0||y>4,x<3||z>1||y>4, x<3||z>2||y>4,无限循环;
//x<3||z>4||y>0,x<3||z>3||y>1, x<3||z>3||y>2,无限循环;
其它情况可用自己试试,多体会体会。
#include<stdio.h>
int main()
{
//for循环可以对多个循环变量进行赋值和增减运算;赋值表达式和增减表达式之间用逗号分隔。
int x,y,z;
for(x=0,y=0,z=0;x<3;x++,y++,z++)
printf(“x=%d,y=%d,z=%d\n”,x,y,z);//因for循环体只有一条语句,所以不用加上一对大括号。
getchar();//等待输入字符
getchar();//等待输入字符
}
17.条件为空的for循环
#include<stdio.h>
int main()
{
//for循环中的任一条件都可为空,只要在该处放一个封号即可。
int i=0;
for(;i<3;)//相当于while(i<3),执行的结果都是相同的。
{
i++;
printf(“去年的今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风!\n”,i);
}
getchar(); //等待输入字符
}
现在将for(;i<3;)中的i<3循环条件去掉,变成for(;😉。根据标准的写法可推知,第二个“;”之前的循环条件表达式为空,说明,不需要任何循环条件即可循环,所以是死循环。for(;;)相当于while(1)的死循环。
#include<stdio.h>
int main()
{
//for循环中的任一条件都可为空,只要在该处放一个封号即可。
int i=0;
for(;😉//相当于while(1)的死循环,执行的结果都是相同的。
{
i++;
printf(“去年的今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风!\n”,i);
}
}
这样的死循环有什么用呢?在制作导航菜单的时候会用到死循环。
1、导航菜单
配合永久循环,可以作出让用户选择的导航菜单,该菜单永不停止,直到用户激活某一CASE为止。举例如下:
#include<stdio.h>
int main()
{
int i;
for(i=0;i<3;i++)
{
int j=100;
printf(“在for循环中,输出j的值:%d\n”,j);
}
//printf(“在for循环中,输出j的值:%d\n”,j);//在大括号外使用j,出现错误:“j"没声明的标识符。未定义标识符"j”。
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
//for循环中的任一条件都可为空,只要在该处放一个封号即可。
int quit=0;//循环开关,值为0时执行循环,为1时终止循环–即跳出for循环。
for(;😉//for(;;)相当于while(1)的死循环。
{
char choice;//存储用户的输入。
printf(“(0)江苏台(1)湖北台(2)安徽台(3)浙江台(4)山东台(5)湖南台(6)宁夏台(q)退出程序:\n”);
scanf_s(“%c”,&choice);//调用scanf_s(),将用户输入的选择保存到choice中
getchar();//抛弃用户最后按下的回车字符。
switch(choice)
{
case ‘0’:printf(“江苏台正在播放《画皮》!\n”);
break;
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 ‘q’:quit=1;//退出开关打开。
break;//随后退出switch()语句。
default:printf(“您输入的不是0到6之间的有效数字。\n”);
//由于该语句在switch()语句的结尾,因此不用加break语句来跳出switch()语句.
}
if(quit1)//退出switch()语句后首先检查quit1?。
{
break;//quit==1跳出死循环
}
}
printf(“程序结束\n”);
system(“pause”);
}
2、执行为空的for循环
//for循环允许执行的语句为空。如,执行部分为封号(;)的一条空语句。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
for(i=0;i<5; printf(“i=%d\n”,i),i++)
{
;
}
system(“pause”);
}
// for循环等同于下面多种写法。首先,初始化在for中,分为5种
for(i=0;i<5; i++)
{
printf(“i=%d\n”,i);
}
// 也等同于
for(i=0;i<5;)
{
printf(“i=%d\n”,i); i++;
}
// 也等同于
for(i=0;i<5;)
{
printf(“i=%d\n”, i++);
}
// 也等同于
for(i=0;i<5; printf(“i=%d\n”, i++))
{
;
}
// 也等同于
for(i=0;i<5; printf(“i=%d\n”, i), i++)
{
;
}
// 也等同于初始化在定义处又分为至少5种。如:
{
int i=0;
for(;i<5; printf(“i=%d\n”,i++) )
{
;
}
system(“pause”);
}
{
int i=0;
for(;i<5; printf(“i=%d\n”,i++), i++)
{
;
}
system(“pause”);
}
{
int i=0;
for(;i<5; )
{
printf(“i=%d\n”,i++);
}
system(“pause”);
}
{
int i=0;
for(;i<5; )
{
printf(“i=%d\n”,i),i++;
}
system(“pause”);
}
{
int i=0;
for(;i<5; i++)
{
printf(“i=%d\n”,i);
}
system(“pause”);
}
对于for()循环,为便于理解,应写成通俗易懂的形式。如下:
int main()
{
int i;
for(i=0;i<5;i++)
{
printf(“i=%d\n”,i);//注意与printf(“i=%d\n”,i++);的区别,i++出现了2次。
}
system(“pause”);
}
输出结果都等同。都是:
printf(“i=%d\n”,i++);输出是:
3、 嵌套的for循环
If语句可以嵌套,for循环,while, do…while循环也可以嵌套。嵌套就是一个循环中包含另一个循环。
外面循环每执行一次,里面的循环都要完整的执行一次。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
for(i=1;i<6;i++)
{
for(j=1;j<6;j++)
{
printf(“*”);
}
printf(“\n”);
}
system(“pause”);
}
请按任意键继续. . .
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
for(i=1;i<7;i++)
{
for(j=1;j<7;j++)
{
if(i>=j)
{
printf(" “);//换成printf(”“);就是下一个图,互补成矩形。
}
else
printf(”“);//换成printf(” “);就是下一个图,互补成矩形。
}
printf(”\n");
}
system(“pause”);
}.
把上述程序中的if(i>=j)换成if(i+j>=7)
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
for(i=1;i<7;i++)
{
for(j=1;j<7;j++)
{
if(i+j>=7) // if(i+j<=7)
{
printf(" “);//换成printf(”“);就是下一个图,互补成矩形。
}
else
printf(”“);//换成printf(” “);就是下一个图,互补成矩形。
}
printf(”\n");
}
system(“pause”);
}
// if(ij) printf(“*”);打印副对角线。
//if(i+j7) printf(“");打印主对角线。
21.九九乘法表
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
printf(“输出九九乘法表:\n”);
for(i=1;i<10;i++)
{
for(j=1;j<=i;j++)
{
/
if(ij>=10)
printf("%d%d=%d “,j,i,ji);
else /
printf("%d%d=%d ",j,i,ji);
}
printf(”\n”);
}
system(“pause”);
}
矩形九九乘法表
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
printf(“输出九九乘法表:\n”);
for(i=1;i<10;i++)
{
for(j=1;j<10;j++)
{
/*
if(ij>=10)
printf("%d%d=%d “,i,j,ji);
else /
printf("%d%d=%d ",i,j,ji);
}
printf(”\n");
}
system(“pause”);
}
if(ij>=10) rintf("%d%d=%d ",j,i,ji); else printf("%d%d=%d ", j,i,j*i);
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,j;
printf(“输出九九乘法表:\n”);
for(i=1;i<10;i++)//外循环控制行数
{
for(j=1;j<10;j++)//内循环控制列数
{
printf(“%d*%d=%d\t”,j,i,j*i);//输出一个表达式,再输出一个制表符
}
printf(“\n”);
}
system(“pause”);
}
本章总结:
假如要无条件跳转到某条句执行,用goto语句;
假如要重复执行某些语句,并且能够确定执行的次数,用for语句;
假如不能够确定执行的次数,用while语句;
假如能够确定至少执行一次,用do…while语句;
另外continue语句能够使当前的循环结束并从循环的开始处继续执行下次循环;
Break语句会使循环直接结束;
Exit函数会使整个程序结束。
初级篇综合运用实例—DuBo机
1.分析 2.赌博规则
3.确定下注方式与赌注 4.掷出骰子
5.判断点数的大小 6.计算输赢的钱数
7.检查赌本够不够 8.主函数
9.抛弃kbhit产生的按键 10.解决第一个缺陷
11.解决第二个缺陷 12.解决窗口一闪而过的问题
数组越界问题
#include<stdio.h>
#include<stdlib.h>
int main()
{//50名学生的分数,打印高于80分的分数及人数。
int i,N[51],counter=0;
float G[51]={0.0,};//浮点型数组必须初始化;否则编译时出错—缺少}。
printf(“please input a student ID and score!\n”);
for(i=0;i<51;i++)
scanf(“%d\t%f”,&N[i+1],&G[i+1]);
for(i=0;i<51;i++)
{
if(G[i+1]>80)//G[0]~G[50]分配的内存空间,而G[51]越界。运行时出错:Run-Time Check Failure #2 - Stack around the variable ‘G’ was corrupted.(运行时检查失败#2 -堆栈周围的变量’G’已损坏)。
{
printf(“%f\t”,G[i+1]);
counter++;
}
if(counter%5==0)putchar(‘\n’);
}
printf(“%d\n”,counter);
system(“pause”);
}