上一篇文章:C语言程序设计概述+C语言简介+算法概述
/*This is the first C program!*/
#include //编译预处理命令
main() //主函数
{
printf("This is the first C program!\n"); //调用printf()函数打印要输出的语句
}
/*
解读:
第一行是注释,C语言中使用两个斜杠中间加两个星号进行注释,注释内容放在星号中间。也可以用双斜杠的形式进行单行注释,注释内容放在双斜杠后面,注意双斜杠只能进行单行注释。
双斜杠加星号可以进行多行注释
*/
main()
是主函数,编译器在编译代码的时候都是从主函数开始编译的。后面的花括号括起来的内容为主函数的语句,称为主函数的函数体。C语言中的每条语句都要以分号结尾,如果缺少分号,系统会报错的。注意一定不能少了分号,这个是初学者经常犯的错误。且分号一定要是英文状态下的分号。\n
反斜杠n是转义字符,它的意思是回车换行。好了,我们的第一个C语言程序讲完了。但是代码书写不规范,现在我们再把它改一下,代码如下:
#include
int main(void)
{
printf("This is the first C program!\n");
return 0;
}
在第二行,我们加了一个int,这个是主函数的函数类型,函数类型与它的返回值有关,int是整型,当不写int时,默认为int整型。return 0;
是函数返回值,因为它没有返回值,所以直接返回0,也可以省去,因为我们只是打印一句话。括号里面的是主函数的参数,因为这个主函数没有参数,所以我们用void(空),也可以直接省去。
对于初学者要注意编程规范,语法要规范。因为有些编译器对语法要求严格,不这样写会出错,有些编译器则不会要求这么严格。具体情况具体看待。
#include
int main()
{
int n=3;
printf("%d",n);
return 0;
}
int n;
就是定义一个变量n,int是变量的类型,n为变量名。a=3*b;
这是一个算术表达式,表达式中的3就是一个常量,它是一个整型常量,*
号的意思是乘,就是3乘b并把乘得的结果赋给变量a。a=3.0*b;
此时常量为3.0,加上了小数点的常量默认为double型。int n=3;
定义一个整型数据,并给他赋初始值为3printf("%d",n);
引号里面的是要输出的内容,%d
是要输出的整型数据,这个语句的意思是直接输出n的值。#include
int main()
{
int a,b,c,d=3,e=1;
a=b=c=5;
printf("%d,%d,%d,%i,%i\n",a,b,c,d,e);
return 0;
}
int a,b,c,d=3,e=1;
定义abcde五个变量,并给d赋初始值3,e赋初始值1。a=b=c=5;
给abc三个变量赋值5。=为赋值符号,右结合性,所谓右结合性,即从右往左运算,左结合性反之。printf("%d,%d,%d,%i,%i\n",a,b,c,d,e);
这行代码的意思是按照abcde变量的顺序输出对应的变量值。%d
和%i
都是整型的占位符#include
int main()
{
float a=3.14159;
double b=5.324352,c=343.324;
printf("%f,%f,%f",a,b,c);
return 0;
}
#include
int main()
{
int a,b;
float c,d;
double e;
scanf("%d%i%f%f%lf",&a,&b,&c,&d,&e);
printf("%d,%d,%f,%f,%f",a,b,c,d,e);
return 0;
}
请按照顺序看完后,最后再看这个计算机计算误差
//Enter A Number To Find The Factorial(输入一个数求阶乘)
#include
int factorial(int a);
int main(void)
{
int n;
scanf_s("%d", &n);
printf("%d\n", factorial(n));
return (0);
}
int factorial(int a)
{
int i, fact = 1;
for (i = 1; i <= a; i++)
{
fact = fact * i; //花括号要上下对齐,格式美观,提高可读性,避免代码过多,可读性下降,也不利于后期维护
}
return (fact);
}
定义一个变量n,从键盘输入一个数赋给变量n,在printf();
中调用子函数,将n的值传递给子函数的参数a,由a代替n在子函数中参与运算,运算结果存入变量fact,再将fact的值返回主函数调用该子函数的地方,然后printf();
函数输出n的阶乘结果。
函数类型 函数名 (参数表);
不写函数类型默认为int整型 定义无返回值的函数时,函数类型应为void。例如只实现打印功能的子函数无返回值。参数表中要写参数类型,且定义参数时只能一个一个定义,不能同时定义多个。例如:int ZiHanShu(int a,int b,double e);
而int ZiHanShu(int a,b,double e);
是不对的,因为a和b不能同时定义。子函数中的参数及变量与主函数中的变量互相独立,互不干扰。子函数与主函数之间通过参数及返回值互相沟通联系。 子函数的返回值的类型与子函数的类型保持一致子函数名称(想要传入的值);
,例如factorial(n);
,factorial是函数名称,n是我想要传入的值。注意:上面代码,子函数具体代码是在主函数下面写的,所以必须要在主函数前面声明,不声明无法正常使用。如果我将子函数具体代码写在主函数前面,则不需要提前声明。 就像这样:#include
int factorial(int a)
{
int i, fact = 1;
for (i = 1; i <= a; i++)
{
fact = fact * i;
}
return (fact);
}
int main(void)
{
int n;
scanf_s("%d", &n);
printf("%d\n", factorial(n));
return (0);
}
for(语句一; 语句二; 语句三;)
{
循环体;
}
i
为循环变量,赋初始值为1。i
的值是否满足语句二的循环终止条件,若满足循环终止条件,则结束循环;若不满足循环终止条件,则执行循环体语句,然后执行语句三,改变循环变量的值,再判断是否满足循环终止条件,以此往下类推,直到结束为止。fact
变量在执行循环前必须初始化,否则循环无法执行,很多初学者都容易犯这样的错误。例如:上面的代码fact在定义的时候就已经赋了初始值。建议初学者不要这样写,容易忘记给它赋初始值。建议循环变量的赋值放在循环外面单独一行或几行(循环变量多的时候一行赋一个)//Enter A Number To Find The Factorial(输入一个数求阶乘)
#include //编译预处理命令
int factorial(int n); //这是一个子函数,调用前要提前声明
int main(void) //int可以省略,不写int默认为整型,void可以省略
{
int n; //定义一个变量n
scanf_s("%d", &n); //使用scanf()不会检查输入边界,可能造成数据溢出。scanf_s()会进行边界检查。
//scanf("%d",x); 指从键盘给x输入一个int整形数据;scanf("%f",x); 指从键盘给x输入一个float或double实型(即小数)数据
//printf("%d",x); 指按整型数据输出x中的值
//后缀_s更安全,传入一个和参数有关的大小值,避免引用到不安全(漏洞)黑掉系统。
//scanf("%s",&name,n); 整型n为name类型的大小,如果name是数组,那n就是该数组的大小
//注意scanf_s()函数只能在VS编译器中使用,是VS编译器对scanf()函数的一个特殊修改,标准C中并没有scanf_s函数,所以如果你使用的是其他编译器,要把scanf_s改为scanf
printf("%d\n", factorial(n)); //这里调用了子函数,把子函数中的值输出
return (0); //返回值可以加括号,也可以不加括号,通常情况下是不加的,了解一下就行了
}
int factorial(int n) //这里是子函数的具体内容,不写int默认为整型
{
int i, fact = 1; //这里是子函数中定义的变量
for (i = 1; i <= n; i++) //这里是一个for循环
/*如果for循环后面只有一条语句,那么花括号可以省略*/
fact = fact * i; //for循环里面的一条语句
return (fact); //返回值可以加括号,也可以不加括号,通常情况下是不加的,了解一下就行了
}
一个好的程序编写规范是编写高质量程序的保证。清晰、规范的源程序不仅仅方便阅读,更重要的是能够便于检查错误,提高调试效率,从而最终保证程序的质量和可维护性。
#define CLASS 5 /*定义常量*/
int m_iClass; /*定义整型成员变量*/
int iNumber; /*定义普通整型变量*/
int * pClass; /*定义指针变量*/
函数命名可以采用“FunctionName”的形式。注意首字母要大写,其后的字母大小写混合。
#int AddTwoNum(int num1,int num2);
(1)标识符由字母、数字和下划线组成:
第一个字符不能是数字只能是字母或下划线
区分大小写:大写字母与小写字母不同
C语言规定了一个标识符允许的字符个数,即标识符的前若干个字符有效,超过的字符将不被识别,定义标识符最大长度为8。
(2)C语言的标识符可分为关键字、预定义标识符和用户标识符三类
(3)预定义标识符
即预先定义并具有特定含义的标识符
(4)用户标识符:由用户根据需要定义的标识符称为用户标识符,用来给变量、函数、数组等命名
C语言预先规定了一批标识符,它们在程序中都代表着固定的含义,不能另作他用,这些字符称为关键字,例如:int
、double
、if
、else
、while
、for
等
#define 标识符 常量数据
例如:
#define PI 3.14
定义了符号常量PI
,在程序中所有需要用到3.14
的地方,全部都可以写成PI
C语言中建议符号常量名使用大写,以区分于变量
符号常量一经定义,在程序中不得再次赋值
常量定义的举例:
//利用子函数求圆柱体的体积
#define _CRT_SECURE_NO_WARNINGS //宏定义
#include
const double PI = 3.1415926;//用const定义常量,也可以#define PI 3.1415926
double cylinder(double r,double h);//r和h是形参
int main()
{
double radius, height;
printf("Enter radius and height:");
scanf("%lf%lf",&radius,&height);
printf("%.3f",cylinder(radius,height));//子函数调用的时候用实参
return 0;
}
double cylinder(double r, double h)
{
return PI * r * r * h;
}
解读:第一行宏定义,只在VS中使用,在其他编译器去掉第一行宏定义
最小的储存单位:bit,位
8bit=1byte(字节)
1024byte=1kb(千字节)
1024kb=1mb(兆字节)
1024mb=1gb(吉字节)
1024g=1tb(太字节)
往后还有很多更大的,这里不写了
在C语言中整型常量可以以十进制、八进制、十六进制等形式出现
(1)十进制形式
(2)八进制形式:在数码前加数字0。例如:012
、034
等,其中012
=1乘8的1次幂+2乘8的0次幂=10(十进制)
(3)十六进制形式:在数码前加0x(数字0和字母X或x)。例如:0x12
、0x3e
、0xff
等,其中0x12
=1乘16的1次幂+2乘16的0次幂=18(十进制)
十六进制的数码除了数字0到9外,还使用英文字母a到f(或A到F)表示10~15
int占4个字节
short int 简称 short
long int 简称 long
singed 与 unsigned 有符号和无符号 与int、short、long自由组合
有符号就是有正负号,无符号就是没有正负号
整型变量有值域,具体值域要看编译器的种类
不同整型变量的值域是不同的,与其所占的字节数有关
定义整型变量:
int a,b;
short c=2,d;
unsigned long m,n;
整型变量值交换:
#include
main() //函数类型不写默认位整型
{
int a,b,c;
printf("输入a和b的值:");
scanf("%d%d",&a,&b);
c=a;
a=b;
b=c;
printf("a=%d,b=%d\n",a,b); //单纯的打印输出功能的函数,可以没有返回值
//最后c的值为0
}
如果忘记了某个类型的变量占多少个字节,可以用sizeof()
来求出该类型所占的字节数:
知道某个数据类型所占的字节数的情况下,我们就可以计算这个类型的变量所能存储的数据范围,例如:int型变量,刚刚在上面的图中我们已经求出了它占四个字节,一个字节等于8位,所以int型变量总共有32位,每个位上要么是1要么是0,最左端是符号位,1是正数,0是负数,因为int型是有符号的,所以去掉一个符号位,还剩31位,所以将这个31位最大的二进制数转换为十进制数:2^31-1=2147483647
,2147483647就是有符号型int变量所能存储的数据的最大范围。
十进制小数形式:由数字和小数点组成
实型常量不能用八进制或十六进制形式表示
小数点不能单独出现
一般对于非常大或非常小的数值,常用指数形式表示,其表现形式为:
十进制小数 e(或E) 十进制整数
13.5e-6
表示 0.0000135
0.3E3
表示 300
e或E的两边必须有数,且其后面必须为整数
浮点型变量的储存形式
分为 符号
||阶码
||尾数
三个部分
符号决定正负号
阶码决定取值范围
尾数决定精度
使用浮点型变量的时候尽量使用double型的,float型的变量精度没有double的精度高,float型的容易出错
#include
main()
{
float a,b;
a=1235578550.456789;
b=a+20;
printf("a=%f,b=%f\n",a,b);
}
'A'
'1'
'?'
等'a'
是正确的,而'ab'
是错误的'a'
与'A'
是不同的。大小写对应字母的ASCII值相差32'
也是字符常量,不过单引号不能像其他字符一样简单地用单引号括起来,如‘'’
的形式是错误的,而是使用转义字符来实现'1'
与数字1不是等价的,字符'1'
的ASCII值为49//转义字符的举例
#include
main()
{
printf(" ab\tde\rf\n");//\n为回车换行;\t为横向跳8个格;\r回到本行开头,输出f,覆盖一个空格;\\单反斜杠字符;\'为单引号;\"双引号
return 0; //\v为竖向跳格;\f为换页符;\b为退格符
}
程序运行结果为:
f ab de
说明:字符ab前有两个空格,故ab在第三列输出;在遇到\t
时横向跳8个格,输出de;之后遇到\r
执行一个回到本行开头的操作,本行开头输出的是空格,所以字符 f 覆盖了一个空格;最后的\n
为回车换行操作
'A'
的ASCII值为65,65的二进制数为1000001)char 变量名1,变量名2,变量名3 ... ;
char c1,c2; //定义了两个字符型变量
//字符型变量的输出
#include
main()
{
char c1='A',c2;
c2=c1+2;
printf("c1=%d,c2=%d\n",c1,c2);
printf("c1=%c,c2=%c\n",c1,c2);
}
这个程序运行的结果如下:
c1=65,c2=67
c1=A,c2=C
//大小写字母的转换
#include
main()
{
char c1='A',c2;
c2=c1+32;
printf("c1=%c,c2=%c\n",c1,c2);
}
运行结果:
c1=A,c2=a
扩展的ASCII码中含256个字符集,值在0~255之间,若超过了255,则将该数对256取余数。
"Hello world"
+
-
*
(乘)/
(除)%
(取余数运算符)++
(自增运算符)--
(自减运算符)<
(小于)>
(大于)<=
(小于等于)>=
(大于等于)!=
(判断是否不等于)==
(判断是否等于)!
逻辑非&&
逻辑与||
逻辑或~
按位求反运算符&
按位与运算符按位求与
后为00010000,即16的二进制数^
按位异或运算符,异或规则和求与规则类似,参见二进制位逻辑运算符真值表a^=b^=a^=b;
|
按位或运算符,规则参见二进制位逻辑运算符真值表<<
左移位>>
右移位a>>b
表示将a的二进制值右移b位,a<表示将a的二进制值左移b位。要求a和b都是整型,b只能为整数,且不能超过机器字所表示的二进制位数
注意区别位逻辑运算和逻辑运算
移位运算具体实现有三种方式:
循环移位:移入的位等于移出的位
逻辑移位:移出的位丢失,移入的位取零
算术移位:在算术移位(带符号)中,移出的位丢失,左移入的位取0,右移入的位取符号位即最高位代表数据符号,保持不变。
C语言中的移位运算方式与具体的C语言编译器有关,通常实现中,左移位运算后右端出现的空位补0,移至左端之外的位则舍弃;右移运算与操作数的数据类型是否带有符号有关,不带符号位的操作数右移位时,左端出现的空位补0,移至右端之外的位则舍弃,带符号位的操作数右移位时,左端出现的空位按符号位复制,其余的空位补0,移至右端之外的位则舍弃
假设a=58=00111010,a<<2的值为:
11101000=232=58*4
左移一位相当于乘2,左移两位相当于乘4;右移同样的道理,只不过把乘改为了除
注意移位运算不会改变原操作数的值,除非使用a<<=2;
即a=a<<2;
(位逻辑运算有些晦涩难懂,这里简单了解一下,在后面的文章中,会做详细介绍)
指针运算符
*
取内容符
&
取地址符
其他运算符
()
、[]
、->
、.
求字节长度运算符
sizeof()
强制类型转换符
(类型符)
赋值运算符以及复合赋值运算符
=
、+=
、-=
、*=
、/=
等等
a+=b;
相当于a=a+b;
条件运算符
表达式1 ? 表达式2 : 表达式3
逗号运算符
,
自左向右进行运算
例如:printf("%d",(int a=1,b=2,c=3));
最后的输出结果为3,逗号运算符最右边的数。逗号运算符在后面的博客中会补充。
++i
、--i
前置,先执行i=i+1(i=i-1),再把表达式的值参与其他运算
i++
、i--
后置,先把表达式的值参与其他运算,再执行i=i+1(i=i-1)
int i=3,y;
y=-i++;
y=-3,i=4
#include
main()
{
int x=3,y,z;
y=x++;
z=++x;
printf("x=%d,y=%d,z=%d",x,y,z);
}
结果是:x=5,y=3,z=5
同样的,x++看成一个整体,整体表达式的值为x的值,也就是3,将整体表达式的值赋给y,再执行x=x+1,x的值变为4。++x先执行x=x+1,x的值变为5,然后将5作为++x整体表达式的值赋给z。
关系运算符主要用于比较运算,比较后要么为真要么为假,如果为真结果为1,如果为假结果为0
<
、>
、<=
、>=
这四种关系运算符的优先级相同,并且这四种关系运算符的优先级高于==
、!=
。==
和!=
的优先级相同
不要把==
和=
混淆,==
是判断两端的操作数是否相等,而=
是将右侧操作数的值赋给左侧操作数。
逻辑表达式的值只能为真或者假,用0表示假,用1表示真。
!
逻辑非
&&
逻辑与
||
逻辑或
举个例子:
int a=2,b=5;
!a
对a取反,a的值为2,代表真,取反后结果为假,值为0
!(a+3>b)
先算a+3>b,值为0,对零取反后值为1
!
的优先级最高,其次是&&
,最后是||
C语言中复合赋值运算符有以下10个:
*=
、/=
、%=
、+=
、-=
、<<=
、>>=
、&=
、^=
、|=
举个例子:
x*=y
相当于x=x*y
x*=z+y
相当于x=x*(z+y)
按照优先级从高到低排序:
()
!
-
、+
、++
、--
、(类型名强制数据类型转换)
、sizeof()
*
、/
、%
+
、-
<
、<=
、>
、>=
==
、!=
&&
||
表达式1 ? 表达式2 : 表达式3
(条件运算符)=
、+=
、-=
、*=
、/=
、%=
,
(运算符优先级最低的是逗号运算符)表达式1 ? 表达式2 : 表达式3;
max=x>y?x:y;
#include
main()
{
int sales;
float tc;
printf("please input sales\n");
scanf("%d",&sales);
tc=(sales>20000?sales*0.1(sales>10000?sales*0.8:sales*0.5));
printf("tc=%f\n",tc);
return 0;
}
sizeof()
是一个单目运算符,作用是求得变量或某种数据类型在在内存中的字节数。sizeof 变量名
sizeof (变量名)
sizeof (类型名)
//求字节运算符的举例
#include
main()//不写int默认为整型
{
int a,b,e,g; //int是4个字节
float x; //float是4个字节
double y; //double是8个字节
short c; //short是short int的简写,short是2个字节
b = sizeof c;
long int d; //在这个编译器中long int是4个字节
e = sizeof(d);
long long f; //long long是long long int的简写,它有8个字节//注意长整型数据输出时为了避免出错,最好以%ld的格式字符输出
g = sizeof f;
printf("%d,%d,%d,%d,%d,%d\n",sizeof a,sizeof x,sizeof(y),b,e,g);//sizeof后面可以加括号也可以不加括号
printf("%i,%i\n",sizeof(int),sizeof(float));//%i和%d是一样的
return 0;
}
5+'a'/2.0+14.0/2;
'a'
转换为整型97(类型名)(表达式)
例如:
float a=2.7;int b;
b=(int)(a+2.4)%2;
如果写成了b=(int)a+2.4%2;
,只是对a进行强制类型转换
强制类型转换时,只是得到所需类型的中间变量,原来变量的类型不会改变。
三目的条件运算符,三个操作数中如果有一个是double型的,两个整型的,那么根据自动转换规则,由低级到高级转换,两个整形的会转换成double型的。例如:
int n;
(n>0)?2.9:1;
如果n等于10,那么表达式的值为2.9
如果n等于-10,那么表达式的值为1.0,即由整型的1转换为1.0
它的原型为:
int printf(char * format [,argument,…]);
功能:向系统指定的输出设备按指定的格式输入任意个任意类型的数据,并返回实际输出的字符数,若出错,将返回负数。
格式字符:以%为引导,后跟各种格式字符,用来指定输出项的输出格式,如类型、形式、长度、小数等
普通字符:原样输出
格式字符串:不同数据类型在输出时需要指定不同的输出格式,所使用的格式字符也就不同。格式字符串的一般形式为:
%[flag][width][.prec][F|N|h|l]Type
标志字符有“+”“-”“#”和空格四种,分别代表的含义为:
+:对于正数符号位输出为正号“+”,对于负数输出负号“-”
空格:对于正数符号位输出空格,对于负数输出负号“-”
-:输出时左对齐,右侧补空格
#:如果加在格式字符c、s、d、u前时,对输出结果无影响,只有加在代表输出八进制的类型字符o前时才有意义。
例如:
int x=12;
printf("%o",x);
将十进制的12转化为八进制输出,输出结果为14
例如:
int x=12;
printf("%#o",x);
将十进制的12以八进制的形式输出,输出结果为014,前面的0是八进制数的标志
用十进制整数来表示输出的最少位数。若实际的位数多于指定的宽度,则按实际位数输出。当实际的位数少于指定的位数,则补以空格或0
精度格式以.
开头,后跟十进制整数
F|N|h|l
表示指针是否是远指针或整数是否是长整数
F:表示远指针
N:表示近指针
h:短整型或单精度浮点数
(这个并不实用,知道这么回事就可以了)
还是要注意一点,上面这个图片中,输出的是1.123457而不是1.123456,因为小数点后的第七位大于5,所以进1,如果小数点后第七位小于或等于5,则不会进1
l:长整型或双精度浮点数
常用的类型指示符有以下几种:
用来输出带符号的十进制整数形式。使用形式有三种:
%d
或%i
:按十进制整数的实际长度输出%md
:按指定长度m输出十进制整数,如果实际数据的位数小于m,则左端补空格,若大于m,按实际位数输出。%ld
:输出长整型数据整数部分全部输出,并输出6位小数部分
以指数的形式输出十进制数,输出的宽度为标准宽度13位,其中尾数部分中整数部分占1位,小数点占一位,小数部分占六位,e占一位,指数部分正负号占一位,指数占3位
以指数输出实数时,也可以使用宽度控制符%m.ne的形式,整个数宽度至少占m位,n为尾数部分的小数部分,不足在左端补空格,多出的按实际位数输出。
用来输出实数,可以根据实数的大小自动选择以小数形式f或指数形式e输出,选择的标准是输出时占宽度较小的一种,且不会输出无意义的0,如:123.400000,输出时为123.4
输出字符
原样输出一个字符串
例如:printf("%s","hello world");
%ms
,以宽度m输出字符串,如果字符串长度小于m,在左端补空格(右对齐)%-ms
,上面类似,只不过字符串长度小于m时,在右端补空格(左对齐)%m.ns
,右对齐的形式输出字符串,只输出字符串的前n个字符%-m.ns
,左对齐的形式输出字符串,只输出字符串的前n个字符%d和%i都是输出整数
%o转化为八进制形式输出
%u以无符号的十进制形式输出
%X或%x以十六进制的形式输出
%c输出单个字符
%s输出字符串
%f以小数的形式输出实数
%E或%e以指数的形式输出
%G或%g自动选择%f和%e中宽度最小的形式输出实数,且小数点后面无意义的0自动省去(著:如果想输出%,则需要连续两个%%)
#include
int main()
{
int a=3;
printf("%i%%\n",a);
}
输出结果为
3%
C语言中printf()函数可以完成所有的输出操作,但如果要输出单个字符的话使用putchar()函数更为简单
函数原型:int putchar(int ch);
原型:int scanf(char *format [,argument,…]);
(1)地址列表:地址列表是若干个变量地址的列表,可以是变量地址、字符数组名及指针变量等。两个地址之间用‘逗号进行分隔。变量首地址的表示方法:&变量名。其中&是地址运算符。scanf()函数执行时将输入的数据流按指定格式转换为数据,存入相对应的存储单元中。
例如:
scanf("%d%d",&a,&b);
(2)格式字符:
格式字符串以%引导,其形式为:
%[*][width][F|N|h|l]type
各部分介绍如下:
int a,b,c;
scanf("%2d%2d%3d",&a,&b,&c);
#include
main()
{
char c1,c2,c3;
scanf("%3c%3c%3c",&c1,&c2,&c3);
printf("c1=%c,c2=%c,c3=%c",c1,c2,c3);
}
执行程序输入abcdefghijk123,对于类型c,只读入单个字符,加上宽度指示符后,第一个%3c读取三个字符abc,赋给字符变量c1,但char变量类型的c1中只能存放一个字符,所以c1中只能存放字符a,b和c省略。往后以此类推。
输出为:c1=a,c2=d,c3=g
*
int a,b,c;
scanf("%2d%*3d%2d%2d",&a,&b,&c);
printf("a=%d,b=%d,c=%d\n",a,b,c);
执行后若输入1234567890
a=12,b=67,b=89
当遇到*时被抑制,不进行赋值操作,舍去了345
(3)普通字符:scanf()函数中的普通字符必须原样输入,否则值会错误。知道就行,强烈不建议使用。
(4)scanf()函数的数据输入操作
要点一:当scanf()函数中的格式字符串中出现转义字符(如\n),系统并不把它当作转义字符来解释,从而产生一个控制操作,将其视为普通字符,所以也要原样输入。
要点二:输入数据时,遇到一下情况,系统认为该数据输入结束:
1.遇到空格,或者Enter键,或者按Tab键
2.遇到输入宽域结束,例如"%3d",只取3列
3.遇到非法输入。如在输入数值数据时,遇到字母等非数值符号,结束输入
4.使用格式说明符"%c"输入单个字符时,空格和转义字符均作为有效字符被输入。
函数的原型:
int getchar (int ch);
函数功能:从标准输入设备(键盘)输入一个字符,并返回输入字符的ASCII值。
使用方法:ch=getchar(void);
如果只是想输入一个字符并输出,也可以在putchar()函数中嵌入getchar()函数,例如:putchar(getchar());
scanf()函数中float型(单精度浮点型)是%f
,double型(双精度浮点型)是%lf
或%le
,字母l
是英文单词long
的首字母,其中%le
是以指数的形式输入
printf()函数中float型和double型都是%f
的形式,当以指数的形式输出时用%e
1的补码是:(以15位为例)0000000000000001
127(2的7次方减一):(以15位为例)0000000001111111
两个字节的存储单元能表示的最大正数是2^15-1,即32767
32767的补码是:0111111111111111 (第一位0是符号位)
(1)原码:符号位是1,其余各位表示数值的绝对值
(2)反码:符号位是1,其余各位对原码取反
(3)补码:反码加1
-1的原码是:1000000000000001
-1的反码是:1111111111111110
-1的补码是:1111111111111111
同理-32767的补码是:1000000000000001
-32767减一-32768
-32768的补码是:1000000000000000
'A'
在ASCII码中的值为65,对应的二进制数为1000001循环有for循环,while循环,和do-while循环,其中for循环在前面已经说过了,这里只简单说一下while循环和do-while循环:
while(表达式)
{
...
};//最后的这个分号可要可不要
先判断表达式的值是否为真,判断的结果只有两个,要么为真,要么为假。真为1,假为0。如果为真,执行循环体中的语句,然后继续判断表达式的值是否为真,再次循环,以此往复,直到表达式的值为假时,不再进行循环。
do
{
...
}while(表达式);//最后的这个分号一定不能少
先进行循环体中的语句,然后计算表达式的值是否为真,如果为真继续执行循环体中的语句,再次进行判断,以此往复,直到表达式的值为假的时候不再进行循环。
break;
语句,立马退出循环。break;
语句常与if
判断语句结合使用,用if
语句进行判断,达到某个条件的时候退出循环。当while语句后面括号中的判断语句为数字1时,即while(1)
,表示判断条件永远为真,永远进行循环,直到碰到break;
语句时退出循环。先来看一个利用子函数和%求余数的举例
#include
int fun(int a) //子函数写在主函数前面
{
int m;
m = a % 10; //a除以10取余数,我们会得到它的个数位的值,并赋给m
return m; //返回m值
}
main()
{
int a, b;
printf("please input a:\n"); //提示输入一个数
scanf_s("%d", &a);//scanf_s只用在VS编译器中,其他编译器用scanf
b = fun(a); //子函数的调用,把返回的m值赋给b
printf("%d", b); //输出b的值
}
这里的子函数直接写在主函数前面,所以不需要进行子函数声明
进入正题:
重组一个三位数,输入三个数,取a的个位数作为新数字的百位数,b的个位数作为新数字的十位数,c的个位数作为新数字的个位数,输出重新组成的三位数
//RecombineAThreeDigitNumber
#include
int fun(int a, int b, int c) //C/C++语言标准库中没有fun函数,fun函数是自定义函数,是用来举例或作语法演示的,也可换成别的名称如abc等
{
int m;
m = a % 10 * 100 + b % 10 * 10 + c % 10; //a除以10取余数乘以100+b除以10取余数乘以10+c除以10取余数
return m;
}
main(void) //主函数完成数据输入以及结果输出部分,而fun函数实现对数据处理功能
{
int a, b, c, d;
printf("please input a & b & c:\n");
scanf_s("%d%d%d", &a, &b, &c);//scanf_s只用在VS编译器中,其他编译器用scanf
d = fun(a, b, c);
printf("d=%d\n", d);
}
输入样例:
34
56
233
输出样例:
463
计算个人所得税
#include
#include
int main()
{
int money, year;
double rate, sum;
printf("Enter money:");//输入金额
scanf_s("%d",&money);//scanf_s只用在VS编译器中,其他编译器用scanf
printf("Enter year:");//输入年限
scanf_s("%d",&year);//scanf_s只用在VS编译器中,其他编译器用scanf
printf("Enter rate:");//输入利率
scanf_s("%lf",&rate);//scanf_s只用在VS编译器中,其他编译器用scanf
sum = money * pow(1 + rate, year);//用sum来保存计算金额
printf("sum=%.2f\n",sum);//保留两位小数输出.2f意识是保留两位小数
return 0;
}
平方根函数sqrt(x) 计算根号下x sqrt(4.0)=2.0
绝对值函数fabs(x) 例如 fabs(-23)=23
幂函数pow(x,n) 例如 pow(2,10)=1024
指数函数exp(x) e的x次方
以e为底的对数函数log(x) 计算ln(x)
代码优化:
//CommonMathematicalFunctions
#include
#include //包含数学函数的头文件
int main()
{
int money, year;
double rate, sum;
printf("Enter the amount,year and exchange rate in turn:\n");
scanf_s("%d%d%lf", &money, &year, &rate); //顺序必须对应
sum = money * pow(rate + 1, year);
printf("sum=%.2f\n", sum); //%.2f 意思是保留两位小数
return 0;
}
//CalculatingPiecewiseFunctions
#include
int main()
{
double x, y;
printf("Enter x (x>=0):\n");
scanf_s("%lf",&x); //scanf_s 里面的 %f 为float型, %lf 为double型
if (x <= 15) {
y = 4 * x / 3;
}
else {
y = 2.5 * x - 10.5;
}
printf("y=f(%f)=%.2f\n",x,y); //%.2f保留两位小数
//printf里面的%f即为float型和double型
return 0;
}
//碰到if 为假,没有else 的情况时,直接跳过if语句执行后面语句
//用科学计数法表示较大或较小的数
#include
int main()
{
int a;
double b;
a = 1.389e3;
b = 2.70098E-2;
printf("%d%15.6f", a, b); //15为宽度,数据填不满宽度时用空格补,.6f保留6位小数
return 0;
}
//输出华氏度-摄氏度转换表
#include
int main(void)
{
int fahr, lower, upper;
double celsius;
printf("Enter lower:");//输入华氏度的下限
scanf_s("%d", &lower);
printf("Enter upper:");//输入华氏度的上限
scanf_s("%d", &upper);
if (lower <= upper)//判断输入的数据是否可行
{
printf("fahr celsius\n");
for (fahr = lower; fahr <= upper; fahr++)//用for循环实现转换表的打印输出
{
celsius = (5.0 / 9.0) * (fahr - 32);
printf("%4d %6.1f\n", fahr, celsius);
}
}
else
printf("Invalid Value!\n");//不可行时输出不合法数据
return 0;
}
//输入一个数求阶乘
#include
int main()
{
int i, n, x;
printf("Enter n:");
scanf_s("%d", &n);
x = 1;
for (i = 1; i <= n; i++)
{
x = x * i;
}
printf("阶乘为%d", x);
return 0;
}
//Judging the parity of a number
#include
int main()
{
int num;
printf("Enter a number:\n");
scanf_s("%d",&num);
if (num%2==0)//该数除以2取余数是否为0
{
printf("The number is even.\n");//为0该数是偶数
}
else
{
printf("The number is odd.\n");//否则该数为奇数
}
return 0;
}
//四则运算
#include
int main()
{
double value1, value2;
char op;//定义一个字符型变量
printf("Type in an expression:");
scanf_s("%lf", &value1);
op=getchar();//用getchar函数输入操作符
scanf_s("%lf", &value2);
if (op == '+')//判断操作符
printf("=%.2f", value1 + value2);
else if (op == '-')//判断操作符
printf("=%.2f", value1 - value2);
else if (op == '*')//判断操作符
printf("=%.2f", value1 * value2);
else if (op == '/' && value2 != 0)//判断操作符,操作符为除号,且除数不为零
printf("=%.2f", value1 / value2);
else
printf("操作错误!");
return 0;
}
#include
main()
{
float a, b, c;
printf("input the length of triangle:\n");
scanf_s("%f%f%f",&a,&b,&c);
if (a + b > c && a + c > b && b + c > a)
printf("Can form a triangle!");
else
printf("Can not form a triangle!");
}
//判断输入的字符是不是英文字母
#include
int main()
{
char ch;
printf("Enter a character:");
ch = getchar();
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
printf("It is a letter.\n");
else
printf("It is not a character.\n");
return 0;
}
连续输入多个英文字母,以回车作为结尾,进行大小写字母互相转换。
#include
int main(void)
{
char ch;
printf("input characters:");
scanf("%c",&ch);
while (ch != '\n')
{
if (ch >= 'A' && ch <= 'Z')
ch = ch - 'A' + 'a';
else if (ch >= 'a' && ch <= 'z')
ch = ch - 'a' + 'A';
putchar(ch);
scanf("%c",&ch);
}
return 0;
}
第二种写法:
#include
int main()
{
char ch;
printf("input characters:");
while ((ch=getchar()!=\n)
{
if (ch >= 'A' && ch <= 'Z')
ch = ch - 'A' + 'a';
else if (ch >= 'a' && ch <= 'z')
ch = ch - 'a' + 'A';
putchar(ch);
}
return 0;
}
#include
main()
{
int year;
printf("Please input year:\n");
scanf_s("%d",&year);
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
printf("%d is leap year!\n", year);
else
printf("%d is not leap year!\n",year);
}
#define _CRT_SECURE_NO_WARNINGS//宏定义,只在VS中使用,为了能够使用scanf函数,而不使用scanf_s
#include
int main()
{
double value1, value2;
char op;
printf("Type in an expression:");
scanf("%lf%c%lf",&value1,&op,&value2);
switch (op)//switch括号里面的是我们要判断的对象
{
case '+': //如果op是加号,则执行该语句
printf("=%.2f\n", value1 + value2);
break;//执行完后用break来跳出switch语句
case '-': //如果op是减号,则执行该语句
printf("=%.2f\n", value1 - value2);
break;
case '*': //如果op是乘号,则执行该语句
printf("=%.2f\n", value1 * value2);
break;
case '/': //如果op是除号,则执行该语句
if (value2 != 0)
printf("=%.2f\n", value1 / value2);
else
printf("ERROR\n");//如果除数为零,输出错误
break;
default: //如果op以上情况都不是
printf("Unknown operator!\n");//输出未知操作
break;
}
return 0;
}
用switch语句完成以下功能:输入一个百分制整数成绩,如果成绩为90-100,则等级为A;如果成绩为80-89,则等级为B;如果成绩70-79,则等级为C;如果成绩为60-69,则等级为D;如果成绩为0-59,则等级为E。
#include
int main()
{
int g;
printf("请输入一个0到100到成绩:");
scanf("%d",&g);
g/=10; //对成绩进行除10运算,去掉个位数
switch (g)
{
case 9:case 10:
printf("A");
break;
case 8:
printf("B");
break;
case 7:
printf("C");
break;
case 6:
printf("D");
break;
case 5:case 4:case 3:case 2:case 1:case 0:
printf("E");
break;
default:
printf("Input Error");
}
return 0;
}
#include
main()
{
int i = 2, f = 1, n;
double s = 1, t;
printf("input n:\n");
scanf_s("%d",&n);
a1: //做一个记号
t = 1.0 / (2 * i - 1);//1.0C语言中带小数点的常量默认为double型小数
f = -f;
s = s + f * t;
i++;
if (i <= n)
goto a1; //配合if语句实现循环,回到记号处再次执行
printf("s=%7.5f\n",s);
}
/*
continue语句,在循环中如果碰到了continue语句,则跳过循环中continue以下的语句,进行下一次循环;如果碰到了break语句,则跳出循环。注意区分二者。
*/
#include
#include
int main()
{
int denominator, flag;
double item, pi;
//循环初始化
flag = 1;
denominator = 1;
item = 1.0;
pi = 1.0;
while (fabs(item) >= 0.0001)//精确度为0.0001,当某项的值大于等于0.0001的时候执行while循环体语句,什么时候不大于等于了,什么时候结束循环
{
item = flag * 1.0 / denominator;
pi = pi + item;
flag = -flag;
denominator = denominator + 2;
}
pi = pi * 4;
printf("%.4f",pi);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int n, i, j;
printf("请输入等腰三角形的高度:");
scanf("%d",&n);
for (i = 1; i <= n; i++)//外层循环控制三角形的层数
{
for (j = 1; j <= n - i; j++)//第一个循环打印该层的空格数,空格数与i值即层数有关
printf(" ");
for (j = 1; j <= i; j++)
printf("c ");//打印c加一空格
putchar('\n');//输出换行打印下一行
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int i, j, n;
printf("请输入倒等腰三角形的高度:");
scanf("%d",&n);
for (i = 1; i <= n; i++)//与打印倒三角是同样的道理
{
for (j = n+1-i; j >= 1; j--)
printf("c ");
putchar('\n');
for (j = 1; j <= i; j++)
printf(" ");
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int count, num;
printf("Enter a number:\n");
scanf("%d",&num);
//经常忘记循环前变量初始化
count = 0;
while (num != 0)//代码很简单,自己理解一下
{
num = num / 10;
count++;
}
printf("%d",count);
return 0;
}
#include
#include //产生随机数需要的头文件
#include //产生随机数需要的头文件
int main()
{
int count = 0, flag, mynumber, yournumber;
srand(time(0));
mynumber = rand() % 100 + 1;//产生的随机数很大,所以对100取余数,得到0到99之间的数,再加一得到1到100之间的数
flag = 0;//循环变量初始化
while (count < 7)//只能猜7次,7次猜不中就输了
{
printf("Enter your number:");
scanf_s("%d",&yournumber);
count++;//记下猜了多少次
if (yournumber == mynumber)
{
printf("Lucky you!\n");
flag = 1;
break;
}
else
if (yournumber > mynumber)
printf("Too big\n");
else
printf("Too small\n");
}
if (flag == 0)
printf("Game Over!\n");
return 0;
}
#include
int main()
{
int mark, max;
printf("Enter marks:");
scanf_s("%d", &mark);
max = mark;
do
{
if (max < mark)
max = mark;
scanf_s("%d", &mark);
}while (mark >= 0);//while语句后面的分号可要可不要,但是do-while语句后的分号不能省去
printf("Max=%d\n", max);
return 0;
}
#include
int main()
{
int i, j;
double sum, item;
sum = 0;
for (i = 1; i <= 100; i++)
{
item = 1;
for (j = 1; j <= i; j++)
{
item = item * j;
}
sum = sum + item;
}
printf("1!+2!+3!+4!+... ...+100!=%e",sum);//%e以指数的形式输出最后的结果
return 0;
}
#include
double fact (int n);//声明一个子函数,结尾必须以分号结尾
//double为子函数的类型//fact为子函数名称
//括号里面的是参数,可以有一个或多个,也可以没有
//double为子函数返回值的类型,可以有返回值,也可以没有返回值
//没有返回值用void声明函数;如果什么都没有默认为整型
int main()
{
int i;
double sum;
sum = 0;//不要忘记循环初始化
for (i = 1; i <= 100; i++)
{
sum = sum + fact(i);//子函数的调用,函数名加(传入的参数i)
}
printf("1!+2!+3!+4!+... ...+100!=%e",sum);//%e是以科学计数法的形式输出,所以sum必须用双精度浮点型double来定义,否则结果会出错
return 0;
}
double fact (int n)//传入的参数i的值给了n
{
int i;
double result;
result = 1;//不要忘记循环初始化
for (i = 1; i <= n; i++)
result = result * i;
return result;//函数返回值,值的类型与函数类型保持一致
}
#include
int main()
{
int n, digit;
printf("Enter n:\n");
scanf_s("%d",&n);
while (n != 0)
{
digit = n % 10;
n /= 10;
printf("%d",digit);
}
return 0;
}
#include
#include
int main()
{
int i, j, n, count;
count = 0;
for (i = 2; i <= 100; i++)
{
n = sqrt(i);
for (j = 2; j <= n; j++)
if (i % j == 0)
break;
if (j > n)
{
printf("%6d",i);
count++;//对输出的个数进行计数
if (count % 10 == 0)//每行输出的个数等于10个,则换行
printf("\n");
}
}
return 0;
}
(DEV C++里面运行正常,VS里面会提示有病毒)
#include
int main()
{
int child, men, women;
for (men = 0; men <= 45; men++)
for (women = 0; women <= 45; women++)
for (child = 0; child <= 45; child++)
if (men + women + child == 45 && men * 3 + women * 2 + child * 0.5 == 45)
printf("men=%d,women=%d,child=%d\n", men, women, child);
/*使用三个for循环把所有可能的情况都循环一遍,把满足要求的数输出*/
return 0;
}
(三个for循环的嵌套计算量太大,对于第一版的优化)
#include
int main()
{
int child, women, men;
for (men = 0; men <= 15; men++)
for (women = 0; women < 22; women++)//不要忘记后面的花括号,否则遍历循环之后,没有进行数据的输出,到最后程序运行的结果什么都没有
{
child = 45 - women - men;
if (men * 3 + women * 2 + child * 0.5 == 45)
printf("men=%d,women=%d,child=%d\n", men, women, child);
}
return 0;
}
#include
#include
int prime(int m);
int main(void)
{
int count, m;
count = 0;
for (m = 2; m <= 100; m++)
{
if (prime(m) != 0)
{
printf("%6d", m);
count++;
if (count % 10 == 0)
printf("\n");
}
}
return 0;
}
//注意for循环语句的执行顺序,先执行循环变量初始化,再执行进行循环的判断条件,符合条件,继续执行循环体语句,
//不符合条件,则不进行循环体语句。
int prime(int m)
{
int i;
for (i = 2; i <= sqrt(m); i++)
{
if (m % i == 0)
return 0;
}
return 1;
}
#include
#include
double funpi(double e);
int main()
{
double e, pi;
printf("Enter e:\n");//提示用户输入精度
scanf_s("%lf",&e);
pi = funpi(e);
printf("pi=%f",pi);
return 0;
}
double funpi(double e)
{
int denominator, flag;
double item, sum;
denominator = 1;
flag = 1;
item = 1;
sum = 0;
while (fabs(item) >= e)
{
item = flag * 1.0 / denominator;
sum = sum + item;
flag = -flag;
denominator = denominator + 2;
}
return sum * 4;
}
#include
#include
int fun_1(int a)
{
int c;
c = 0;
while (a != 0)
{
a /= 10;
c++;
}
return c;
}
int fun_2(int a, int b)
{
int i, digit, er;
er = 0;
for (i = 1; i <= b; i++)
{
digit = a % 10;
a /= 10;
if (digit % 2 == i % 2)
er = er + 1 * pow(10, i - 1);
}
return er;
}
int fun_3(int a)
{
int num, count, i, digit;
count = fun_1(a);
num = 0;
for (i = 1; i <= count; i++)
{
digit = a % 10;
a /= 10;
num = num + digit * pow(2, i - 1);
}
return num;
}
int main()
{
int n, count, two, ten;
scanf_s("%d", &n);
if (n >= 0 && n <= 1000000)
{
count = fun_1(n);
two = fun_2(n, count);
ten = fun_3(two);
printf("%d", ten);
}
return 0;
}
#include
#include
int main()
{
int n, x, z, w = 0;
scanf_s("%d", &n);
for (int i = 1; n >= 1; i++)
{
x = n % 10;
n /= 10;
if (x % 2 == 0)
{
if (i % 2 == 0)
z = 1;
else
z = 0;
}
else
{
if (i % 2 == 1)
z = 1;
else
z = 0;
}
if (z == 1)
w += pow(2, i - 1);
}
printf("%d", w);
return 0;
}
#include
#include
#include
int main()
{
char a[10000];
int len, i;
int sum = 0;
scanf_s("%s",&a);
len = strlen(a);
for (i=1;i<=len;i++)
{
int t;
int x;
t = a[len - i] - 48;
if ((t + i) % 2 == 0)
x = 1;
else
x = 0;
sum = pow(2, i - 1) * x + sum;
}
printf("%d\n",sum);
return 0;
}
#include
int main()
{
int num, a = 1, digit = 0, count = 1;
scanf_s("%d",&num);
do
{
if ((num + count) % 2 == 0)
{
digit += a;
}
count++;
num /= 10;
a *= 2;
} while (num > 0);
printf("%d",digit);
return 0;
}
#include
#include
int main()
{
int n,sum=0;
scanf("%d",&n);
while (n>=0&&n<=1000000)
{
for(int i=1;i<8;i++)
{
if(n%10%2==i%2)
sum+=1*pow(2,i-1);
n/=10;
}
printf("%d",sum);
break;
}
return 0;
}
#include
int main()
{
int n,er=1,sum=0,a=1;
scanf("%d",&n);
while(n>0)
{
if(n%10%2==a%2)
sum+=er;
n/=10;
er*=2;
a++;
}
printf("%d",sum);
return 0;
}
还可以有很多种做法,只要能实现就可以。关键是取得代码的简洁易懂。
特别注意:在标准C语言中,变量必须定义在函数体的最顶部,但是在C++中可以把变量的定义放在函数的中间。现在大多数编译器都是同时支持C和C++的,所以可以把变量定义在函数体中间位置。如下代码for循环
中的循环变量i
就是定在for循环复合语句中的:
int main()
{//函数体开始
int n;//n的使用范围限制在main函数体内部
n = 10;
for(int i; i <= n; i++)//这里的循环变量i定义在for循环内部,所以其有效使用范围限制在该for循环中
{
...
}
//可以在复合语句内部直接嵌套复合语句
{ //复合语句开始
int a=2; //复合语句内的局部变量
...
} //复合语句结束
}//函数体结束
#define _CRT_SECURE_NO_WARNINGS
#include
float cash;//定义全局变量,用来保存金额值
void income(float number), expend(float number);//函数声明,一个函数类型名后面可以声明多个函数,每个函数中间用逗号隔开
int main()
{
int choice;
float value;
cash = 0;
printf("Enter operate choice (0--end, 1--income, 2--expend):");
scanf_s("%d", &choice);
while (choice != 0)
{
if (choice == 1 || choice == 2)//判断是否等于用==,不要用错成=,||是逻辑或,&&是逻辑与
{
printf("Enter cash value:");
scanf_s("%f", &value);
if (choice == 1)
income(value);
else
expend(value);
printf("current cash:%.2f\n",cash);
}
printf("Enter operate choice (0--end, 1--income, 2--expend):");
scanf_s("%d",&choice);
}
return 0;
}
void income(float number)//无返回值函数,但可以用全局变量来保持子函数与主函数之间的联系
{
cash = cash + number;//改变全局变量
}
void expend(float number)
{
cash = cash - number;
}
变量是保存变化数据的单元,计算机用内存单元来对应实现。一旦在程序中定义变量,计算机在执行过程中就会根据变量类型分配相应的内存单元供变量保存数据。
主函数从一开始运行就给主函数中所有的局部变量分配了存储单元,到主函数运行结束,分配的存储单元被回收。而主函数中未被调用的子函数里面的变量(包括形参在内)未被分配存储单元,直到子函数被调用时,子函数里面被定义的变量(和形参)才被分配存储单元;一旦子函数调用结束,在子函数中定义的所有形参和局部变量将不复存在,相应的存储单元由系统收。根据这种特性,局部变量被称为自动变量。变量从定义开始分配存储单元,到运行结束存储单元被回收,整个过程称为变量生存周期。
C语言把保存所有变量的数据区分成动态存储区和静态存储区。它们的管理方式完全不同,动态存储区是使用堆栈来管理的,适合函数动态分配与回收存储单元。而静态存储区相对固定,管理较简单,它用于存放全局变量和静态变量。
在静态存储区中,除了全局变量外,还有一种特殊的局部变量——静态局部变量。生存周期持续到程序结束。由于存储单元被保留,一旦含有静态局部变量的函数再次调用,则静态局部变量会被重新激活,上一次函数调用后的值仍然保存着,可供本次调用使用。
#include
int f = 1;//定义全局变量,并赋初始值为1
void fact_s(int n);//定义无返回值函数,必须要写void,不写默认为整型
int main()
{
int i, n;
printf("Input n:");
scanf_s("%d",&n);
for (i = 1; i <= n; i++)
{
fact_s(i);//无返回值函数的调用
printf("%3d!=%d\n", i, f);
}
return 0;
}
void fact_s(int n)
{
f = f * n;
}
#include
int main()
{
int x, j = 0, k = 0;
printf("Enter x:");
while (scanf_s("%d", &x))
{
if (x < 0)
break;
else if (x % 2 == 0)
j++;
else
k++;
}
printf("偶数有%d个\n", j);
printf("奇数有%d个", k);
return 0;
}
注意,当输入了一串数字之后需要输入一个非数字的字符来结束这个while循环
#include
int main()
{
int sales;
float tc;
printf("please input sales:\n");
scanf_s("%d", &sales);
tc = sales > 20000 ? sales * 0.1 : (sales > 10000 ? sales * 0.08 : sales * 0.05);
printf("%g", tc);//自动判断是%f还是%e,判断标准为占宽度最小的一种,且会省去小数点后无意义的0
return 0;
}
三目运算符前面说过,这个代码也出现过,只是做了一个小小的修改
#include
int main()
{
float a = 2.7;
int b;
b = (int)(a + 2.4) % 2;//把a+2.4的值强制转换成整型
printf("%i",b);
return 0;
}
#include
int main()
{
int x = 12;
printf("%o\n",x);//将十进制12转换为八进制数输出
printf("%#o\n",x);//将十进制数12转换为八进制,然后以八进制的形式输出,八进制数开头第一个数为0,作为八进制的标志//0x为十六进制
return 0;
}
前面出现过这个代码,
#include
#include
int main()
{
double a,b,c;
printf("请分别输入一个二元一次方程aX^2+bX+c=0的a、b、c的值:\n");
scanf("%lf%lf%lf",&a,&b,&c);
(a==1) ? printf("方程X^2%+gX%+g=0的解为:\n",b,c) : printf("方程% gX^2%+gX%+g=0的解为:\n",a,b,c);
if (a==0&&b!=0) //a=0,b不等于0的情况
printf("X=%g",-c/b);
else if (b==0&&a==0) //a=b=0的情况
printf("X无解!");
else if (b*b-4*a*c>=0) //b的平方减4ac大于等于0有解的情况
(-b+sqrt(b*b-4*a*c))==(-b-sqrt(b*b-4*a*c)) //三目运算符,判断两个解是否相等
?
printf("X=%g",(-b+sqrt(b*b-4*a*c))/(2*a)) //两个解相等时,直接输出x的解
:
printf("X1=%g\nX2=%g",(-b+sqrt(b*b-4*a*c))/(2*a),(-b-sqrt(b*b-4*a*c))/(2*a)); //两个解不相等,分别输出x1和x2
else //以上情况都不是的情况,即b的平方减4ac小于0无解的情况
printf("X无解!");
return 0;
}
#include
int main()
{
int a, b, x, n, i;
scanf_s("%d",&n);
a = b = 1;
if (n == 1)
printf("1");
if (n >= 2)
{
for (i = 1; i < n; i++)
{
x = a + b;
a = b;
b = x;
}
printf("%d",x);
}
return 0;
}
#include
#include
int main()
{
int er, ge, i, sum;
i = 0;
sum = 0;
printf("请输入二进制数\n只能由1和0组成(输入的二进制数最大为1111111111):");
scanf_s("%d", &er);//该段代码经过我精心调试过,输入的二进制数最大为十个1
while (er != 0)
{
ge = er % 10;
sum = sum + ge * pow(2, i);
er /= 10;
i++;
}
printf("%d\n", sum);
return 0;
}
该段代码经过我精心调试过,输入的二进制数最大为十个1超出范围的二进制数转换后并不正确。
#include
int main()
{
int n,i,j;
printf("请输入一个十进制数,(该十进制数最大为2147483647):");
scanf_s("%d",&n);
static int str[31];
for (i = 0; i <= 30; i++)
{
str[i] = n % 2;
n /= 2;
}
for (j = 30; j >= 0; j--)
{
printf("%d",str[j]);
}
return 0;
}
#include
#include //二进制转换为十进制需要数学函数
int main()
{
static int er[31]; //定义一个静态的一维数组,系统会自动给每个数自动赋值0
int i, j, count, sum, k, m;
char digit; //定义一个字符变量,我们要往里面输入数字
printf("请输入一个二进制数(该二进制数最大为1111111111111111111111111111111):\n");
count = 0; //用count来统计二进制数的位数
for (i = 0; i <= 30; i++) //用for循环往数组里面输入数值,一次只输入一个一位数
{
digit = getchar(); //输入操作
if (digit == '1') //如果输入的字符为‘1’,就给数组赋值为1
{
er[i] = 1;
count++; //统计一下位数
}
else if (digit == '0') //如果输入的字符为‘0’,就给数组赋值为1
{
er[i] = 0;
count++; //统计一下位数
}
else if (digit == '\n') //如果输入了回车,则结束循环
break;
else //如果输入了0、1和回车以外的字符,则输出“输入错误!”
{
printf("输入错误!\n");
goto a; //同时利用goto语句跳过下面的转换十进制的语句,提前结束主函数
}
}
sum = m = 0; //循环初始化
for (k = count - 1; k >= 0; k--) //之前统计的二进制位数会在这里用到
{
sum = sum + er[k] * pow(2, m); //转换公式
m++;
}
printf("%d",sum); //输出转换结果
a: return 0;
}
int型变量sum能存储的最大十进制正数为2147483647,对应的二进制数为1111111111111111111111111111111,总共有31位数,所以不能用整型变量来存储这么大的数字,只能用一个长度为31的数组来存储,每个存储单元中只存储一个数字,分别对这些数字进行处理。静态的数组可以自动给每个数自动赋值为0。
在上图中,我用scanf()函数输入了110和100分别给了speed和limit,然后我用printf()函数输出speed的值,因为double型显示到小数点后六位,所以输出的是110.000000,然后我再输出limit乘11(数据类型自动转换,11为整型,转换为limit的double型)再除以10(同样涉及到数据类型的自动转换),输出的结果也为110.000000。然后将limit乘11再除以10的值赋给x,比较x与speed之间的大小,如果speed小于x则输出1,否则不输出。运行结果也看到了,并且根据数学运算结果,肯定不小于,所以也没有输出1。这没毛病,但是我把代码改一下,问题就来了。
同样的代码,我只是改了1.1,可是运行的结果却不同。这个就涉及到浮点数精度的问题。输出的结果都相同,并且根据数学运算的结果也相同,但是在计算机中运算的结果却不相同。那么计算机中这个运算的误差为多少呢?
通过上面这两个案例,我们就可以看出运算结果的误差介于10的负13次方到10的负14次方之间。