C语言学习,这一篇就够了!(一)
根据C程序设计(第五版)以及相关题目复习!
1. 程序设计和C语言
1.1 Hello world
#include <stdio.h> //预处理指令
int main() { //定义主函数
printf("这是一篇复习博客"); //输出语句
return 0; //函数执行完毕
}
1.2 程序的结构
- 一个程序由一个或多个原程序文件组成
- 函数是C程序的主要组成部分,函数是程序的基本单位
- 一个函数包括两个部分,函数首部(
int max(int a, int b)
)和函数体(花括号中的部分) - 程序总是从
main
函数开始执行,无论main
函数在什么位置 - 程序中要求计算机的操作是由函数中的C语句完成的
- 在每个数据声明和语句的最后必须有一个分号
- C语言本身不提供输入输出语句,是通过库函数
scanf
和printf
提供的 - 程序应当包含注释,注释能大大的提升代码的可读性
对于长期打
js
代码的来说,分号真的是它容易忘记了!!
注意: 手写代码的时候一定要注意分号,以及注意双引号
1.3 运行 C 语言的步骤
编辑-编译-连接-执行
1.4 练习题
答案在习题后面噢~
第一题:
一个C程序的组成部分可以是( )。
A) 一个主函数和一至若干个其他函数 B) 一至若干个主函数
C) 一个主程序和一至若干个其他函数 D) 一个主程序和一至若干个子程序
第二题:
一个C程序的执行是从( )。
(A) 本程序的main函数开始,到main函数结束
(B) 本程序文件的第一个函数开始,到本程序文件的最后一个函数结束
© 本程序的main函数开始,到本程序文件的最后一个函数结束
(D) 本程序文件的第一个函数开始,到本程序main函数结束
第一题: A,第二题:A
2. 顺序、选择、循环结构
2.1 标识符
标识符的==命名规则==是:
- 只能由字母、数字和下划线组成,字母区分大小写。
- 第一个字符必须是字母或下划线,不能为数字。
C语言中标识符有以下3类
- 关键字。它们在程序中有固定的含义,不能另作他用。如
int
、for
、switch
等。 - 预定义标识符。预先定义并具有特定含义的标识符。如
define
、include
等。 - 用户标识符。用户自定义标识符,符合命名规则且不能与关键字冲突。
2.2 常量与变量
2.2.1 常量
常量是指在程序运行过程中,其值不能改变的量称为常量,常见的常量有以下几类:
- 整形常量:如
1000,12345,0,-345
- 实型常量:两种形式,小数和指数(
123.456和12.34e3
) - 字符常量:可以是一个普通的字符( 如
x
)、一个转义序列(例\t
),或一个通用的字符(如\u02C0
) - 字符串常量:如
"boy"
,"123"
等,用双撇号把若干字符括起来,字符串常量是双撇号里的全部字符 - 符号常量:用
define
指令,指定用一个符号名称代表一个常量,如#define PI 3.14
结尾没有分号
转义序列 | 含义 |
---|---|
\ | \ 字符 |
’ | ’ 字符 |
" | " 字符 |
? | ? 字符 |
\a | 警告 |
\b | 退格键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\o或\oo或\ooo其中o表示一个八进制数字 | 一到三位的八进制数 |
\xh[h…] | 一个或多个数字的十六进制数 |
\ooo 是对用三位八进制数转义表示任意字符的形象化描述。
例如
char ch = '\111';
等价于char ch = 0111;
(以0开头的表示八进制)
2.2.2 变量
int a = 3;
注意:变量必须先定义后使用,在变量取值时,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据
2.2.3 练习题
第一题:
下列定义变量的语句中错误的是______。
A、
int _int
B、double int_
C、char For D、float US$
答案:D
第二题:
以下不合法的用户标识符是______。
A、j2_KEY B、Double
C、4d D、
_8_
答案:C
2.3 数据类型
2.3.1 整数类型
注意:
-
int
short int
long int
是根据编译环境的不同,所取范围不同 -
int
的取值范围在于他占用的字节数 ,不同的编译器,规定是不一样。
2.3.2 浮点型
浮点数据根据精度的不同分为3种
注意:C语言中不存在字符串变量,字符串只能存在字符数组中
2.3.3 类型转换
1. 自动类型转换
自动转换发生在不同数据类型运算时,在编译的时候自动完成。
注意:
只有字节小的可以向字节大的自动转换,不可逆
#include <stdio.h>
int main()
{
char c1, c2;
c1 = 'A';
c2 = c1 + 32;
printf("%c\n", c2); // a
printf("%d\n", c2); // 97
}
如上,自动的将c1
转化为ASCII码再进行加法运算
2. 强制类型转化
强制类型转换是通过定义类型转换运算来实现的。其一般形式为:
//(转化类型)值
(double) a // 将a转化成double类型
(int) (x + y) //将x+y转化成int类型
如%
运算符要求其两侧均为整型量,若x
为float
型,则x % 3
不合法,则这时候就需要强制类型转化了,(int)x % 3
,因为强制类型转换运算符优先于%
运算,所以会先进行(int)x
运算再进行取余运算
3. tips
-
转换类型和表达式都必须加括号, 如把
(int)(x / 3 + y)
写成(int)x / 3 + y
则成了把x
转换成int
型之后再除3
再与y
相加了。 -
强制转换不存在四舍五入
-
强制类型转换时,得到一个所需类型的中间数据,而原来变量的类型未发生变化
2.4 运算符和表达式
2.4.1 基本算术运算符
假定A = 10, B = 20
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
– | 自减运算符,整数值减少 1 | A-- 将得到 9 |
2.4.2 自增和自减运算符
自加运算符
++
与自减运算符--
是单目运算符,运算的对象是变量。自增自减运算有两种一种前缀,一种后缀,两种表达式的值是有区别的,前缀是:先运算再取值,后缀是:先取值后运算
如:
#include<stdio.h>
int main() {
int i = 3;
printf("%d",++i); // 4
}
又如:可以很清楚的理解!
#include<stdio.h>
int main() {
int i = 3;
printf("%d",i++); // 3
}
2.4.3 逻辑运算符
假设变量 A 的值为 1,变量 B 的值为 0
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
|| | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 | !(A && B) 为真。 |
也就是说a并b有假则假,a或b有真则真
2.4.4 赋值运算符
简单赋值运算符为=
int a = 3;// 给a赋值为3
复合赋值运算符就是在简单赋值符之前加上其它运算符构成
例如+=
、-=
、*=
、/=
a += 3;等价于 a = a + 3
注意:复合运算符中运算符和等号之间不存在空格。
2.4.5 关系运算符
假设变量 A 的值为 10,变量 B 的值为 20
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 为假。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 为假。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 为假。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
2.4.6 三目运算符
三目运算符的格式为:
表达式1 ? 表达式2 : 表达式3;
如果表达式1为真则值为表达式2,否则为表达式3
如:
#include <stdio.h>
int main()
{
int a = 10;
int b;
b = (a == 4) ? 1 : 2;
printf("b 的值是 %d\n", b); // b 的值是 2
}
2.4.7 运算符优先级
初等运算符的优先级别最高,然后是单目运算符、算术运算符、关系运算符、逻辑运算符(除逻辑非!)、条件运算符、赋值运算符、逗号运算符。大多数都是自左向右结合,而单目运算符、条件运算符和赋值运算符自右向左结合
==运算符优先级及结合性汇总==自上向下优先级降低
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 AND | & | 从左到右 |
位异或 XOR | ^ | 从左到右 |
位或 OR | | | 从左到右 |
逻辑与 AND | && | 从左到右 |
逻辑或 OR | || | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %=>>= <<= &= ^= |= | 从右到左 |
逗号 | , | 从左到右 |
~菜鸟教程中的运算符优先级~
2.4.8 练习题
复习了这么多关于运算符的知识,来练几道题吧
第一题:
#include <stdio.h>
int main()
{
int a = 1, b = 2, c = 4, d = 8;
int e;
e = (a + b) * c / d;
printf("e的值是 %d\n", e);
}
//输出 :e的值是 1
第二题:
这题要好好思考噢
int main()
{
int x = 12, n = 5;
x %= (n % 2);
printf("%d", x);
}
// 输出: 0
n % 2
余数是1,12对1取余为0
第三题:
在C语言中,字符型数据在内存中的存储形式是
A)原码 B)补码 C)反码 D)ASCII码
答案: D
第四题:
若执下面程序时从键盘上输入5,
#include <stdio.h>
int main()
{
int x;
scanf("%d",&x);
if(x++ > 5) {
printf("%d", x);
}else {
printf("%d", x--);
}
}
则输出是______。
A、7 B、6 C、5 D、4
答案:B
第五题:
做对这题才算真真掌握噢~
设有语句int a = 3;则执行语句a += a -= a * a后,变量a的值是( )。
(A) 3 (B) 0 © 9 (D) -12
答案:D
上面的语句可以转换成:
int a = 3;
a -= (a * a);//*优先级高,先计算a*a为9,此时a -= 9;即 a = a - 9; a = -6
a += a // a = a + a; a = -6 + (-6),a = -12
2.5 C语句
2.5.1 if语句
if(表达式) { 执行内容 }
如果表达式为真,则执行{}
里的内容,否则将跳过不执行该code
2.5.2 if…else 语句
if(表达式) {
代码块1;
}else {
代码块2;
}
如果表达式的值为真,则执行代码块1,否则执行代码块2
注意
if
和else
后面都没有分号噢~
2.5.3 switch语句
switch (表达式)
{
case 情况1:
执行体1;
break;
case 情况2:
执行体2;
break;
default:
执行体3;
}
简单解释一下就是判断表达式的几种情况执行不一样的代码
注意:
case
后的情况不能相同- 每个
case
都需要有一个break
语句 switch
表达式只能是整型或者字符类型
重点:switch
语句最大的好处是它能够简化if
语句
2.5.4 while循环
while(表达式) {
循环体代码
}
当表达式为真时会执行循环体代码,执行体代码结束后,会再次判断表达式是否为真,循环往复,直至表达式为假
注意:循环体代码内应该改变循环变量的值,否则会出现死循环
2.5.5 do … while 循环
do{
循环体代码
}while(循环条件);
它先执行一次循环体代码,然后判断while
中的循环条件是否为真,如果为真则继续循环;如果为假,则终止循环。所以很重要的一点就是,do-while循环至少会执行一次循环体代码。
注意:while括号后必须有分号
2.5.6 for循环
for(表达式1;表达式2;表达式3) {
执行体代码;
}
for
循环是最最最最重要的一个内容了,在考试中常常会要用到!
- 执行表达式1,对变量进行初始化
- 判断表达式2,若为真,则执行
for
循环体中执行体代码,代码执行完毕 - 执行表达式3,对循环变量进行操作
- 再进行第二步,直至判断表达式为假
- 循环结束,程序继续向下执行。
#include <stdio.h>
int main ()
{
for( int a = 10; a < 20; a = a + 1 )
{
printf("a 的值: %d\n", a);
}
return 0;
}
/*输出:
a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 15
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19
*/
2.5.7 break语句
- 当 break 语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。
- 它可用于终止 switch 语句中的一个 case
#include <stdio.h>
int main()
{
int a = 5;
while (a < 10)
{
printf("a的值%d\n", a);
a++;
if (a == 7)
{
break;
}
}
return 0;
}
/*
a的值5
a的值6 */
正如上面的代码中当a == 7
时执行了break
语句跳出了while
循环,因此使得输出语句只有两条
2.5.8 continue语句
continue
会跳过当前循环中的代码,强迫开始下一次循环。
#include <stdio.h>
int main()
{
int a = 5;
while (a < 10)
{
a++;
if (a == 7)
{
continue;
}
printf("a的值%d\n", a);
}
return 0;
}
/* a的值6
a的值8
a的值9
a的值10 */
从上面的代码可以看出,在a==7
时遇到了continue
则后面的代码就不会再执行了,而是重新开始下一轮循环
区别:break会终止整个循环,而continue只是提前结束本轮循环。
2.5.9 goto语句
goto
语句可以将代码执行跳转到标记的位置,虽然这看起来很方便,但会使得程序得控制难以跟踪,所以不推荐使用goto
语句,仅作了解
goto here;
...
here:
2.5.10 练习题
答案在习题结束噢~
第一题:
若i为整型变量,则以下循环的次数是
for (i = 2; i == 0;) {printf("%d", i–); }
A) 无限次 B) 0次 C) 1次 D) 2次
第二题:
下面这段程序运行后
i
的值是( )A)11 B)13 C)12 D)14
#include <stdio.h>
int main()
{
int i = 10;
switch (i + 1)
{
case 10:
i++;
break;
case 11:
++i;
case 12:
++i;
break;
default:
i = i + 1;
}
}
第三题:
C语句for(;;){…}是指( )。
(A)无意义 (B)无限循环 ©循环执行1次 (D)循环执行0次
第四题:
#include <stdio.h>
int main()
{
int y = 10;
while(y--);
printf("y=%d",y);
}
以上程序执行后的输出结果是
A、y=0 B、y=-1 C、y=1 D、while构成无限循环
答案:B C B B
要点:第一题要注意for循环的过程,要先判断是否满足条件才会执行循环体。第二题要理解++i
和i++
的区别,同时也要注意case
后面没有break
的后果。
2.6 数据的输入输出
2.6.1 printf函数输出
格式为:printf(格式控制,输出列表)
。输出控制是用一对双引号括起来的,包含格式声明和普通字符。输出列表是程序需要在输出时原样输出的字符。
2.6.2 scanf函数输入
从键盘获得用户输入,格式为:scanf(格式控制,地址表列)
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a); // 输入:23
printf("%d",a); // 输出:23
}
和printf
非常相似,但注意点有很多
注意:
scanf
的变量前要带一个&
符号。&
叫做取地址符,也就是获取变量在内存中的地址。- 如果除了格式声明还写了其他东西,则在输入数据时在对应位置上输入与这些相同的字符,如:
scanf("a=%d,b=%d",&a,&b);
//输入格式:a=1,b=2
2.6.3 putchar函数输出
这个函数一次只会输出一个单一的字符,但是可以在循环内使用这个方法,以便输出多个字符。
#include <stdio.h>
int main()
{
char a = 'B';
putchar(a);
}
注意:一次只能输出一个字符,putchar()
括号中可以填写字符以及在ASCII内的整型
2.6.4 getchar函数输入
这个函数一次只会读取一个单一的字符
#include <stdio.h>
int main()
{
char a,b;
a = getchar();
b = getchar();
putchar(a);
putchar(b);
}
输入jc
输出jc
注意:在键入信息时,字符会暂存在缓存区中,只有在按下回车时,才会将输入的字符送往计算机,按顺序赋值
2.6.5 puts函数输出
用来输出字符串并换行
#include <stdio.h>
int main(){
char str[]="i am ljc";
puts(str); // i am ljc
return 0;
}
注意:
- 只能输出字符串,不能输出数值或格式转换。
- 会自动输出一个回车符
- 将字符串结束符
\0
转换成\n
2.6.6 gets函数输入
gets()
也存在缓冲区概念,当按下回车键时,就代表输入结束了,gets()
开始从缓冲区中读取内容。gets()
和 scanf()
的==主要区别==是:
scanf()
读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。gets()
中空格也是字符串中的一部分,只有遇到回车键时才会认定字符串输入结束,所以,不管输入了多少空格,只要没有回车,对gets()
来说就是一个完整的字符串。
2.7 练习题
第一题:
有以下程序
#include <stdio.h>
int main()
{
char c1 = '1', c2 = '2';
c1 = getchar();
c2 = getchar();
putchar(c1);
putchar(c2);
}
当运行时输入:a <回车> 后,以下叙述正确的是______。
A、变量C1 被赋予字符a,c2被赋予回车符
B、程序将等待用户输入第2个字符
C、变量c1被赋予字符a,,c2中仍是原有字符2
D、变量c1 被赋予字符a,c2中将无确定值
==答案:A==
第二题:
执行下列程序时输入:123<空格>456<空格>789<回车>,输出结果是______。
#include <stdio.h>
int main()
{
char s[100];
int c, i;
scanf("%c", &c);
scanf("%d", &i);
scanf("%s", s);
printf("%c,%d,%s \n", c, i, s);
}
A、123,456,789 B、1,456,789
C、1,23,456,789 D、1,23,456
==答案:D==
2.7 格式字符
2.7.1. d格式符
用来输出一个有符号的十进制整数
注意:可以在格式声明中指定输出数据的域宽,"%5d"
,指定输出数据占5列,输出的数据显示在此5列区域右侧
printf("%5d\n%5d\n",12, -345);
输出结果:
12(前3个空格)
-345(前1格空格)
2.7.2. c格式符
用来输出一个字符
char ch = 'a';
printf("%c",ch);// 输出a
同样的可以指定域宽printf("%5c",ch)
输出a前有4个空格
注意:在0-127
的整数也可以用%c
输出,在输出之前会转换成对应的ASCII码,如果整数比较大则输出第一个字节的信息对应的字符
short a = 121;
printf("%c", a); // y
当数比较大时
int a = 377;
printf("%c", a); // y
因为以%c
格式输出,所以只考虑第一个字节,a在内存中的存放方式是这样的,第一个字节所对应的十进制为121,对应y
2.7.3. s格式符
用来输出一个字符串
printf("%s","china");// 输出: china
2.7.4. f格式符
用来输出实数,以小数形式输出
- 基本型,
%f
不指定输出数据长度,由系统来决定数据所占的列数,一般是小数输出6位
double a = 1.0;
printf("%f",a/3);// 输出: 0.333333
输出了6个3
- 指定数据的宽度和小数位数,用
%m.nf
这里的意思是指定域宽为m,小数点后保留n位数字
double a = 1.0;
printf("%7.2f",a/3);// 输出: 0.33(前面有3个空格噢)
注意:
-
如果n为0,则不仅不输出小数,也不输出小数点
-
如果n的值过大,也不能保证全部输出,原因之一是double类型数据只能保证15位有效数字
- 输出的数据向左对齐,用
%-m.nf
当数据长度不超过m时,数据向左靠齐,右边补空格
2.7.5. e格式符
以指数形式输出
printf("%e",123.456);// 输出:1.234560e+002
如果不指定输出的宽度和数字部分的小数位数,将以小数部分6位,指数部分5位来定
2.7.6. 格式字符汇总
格式字符 | 说明 |
---|---|
d,i | 以带符号的十进制形式输出整数(正数无符号) |
o | 以八进制无符号形式输出整数(不输出前导符0) |
x,X | 以十六进制无符号形式输出整数(不输出0x) |
u | 以无符号十进制形式输出整数 |
c | 字符形式输出,只输出一个字符 |
s | 输出字符串 |
f | 以小数形式输出单,双精度,默认6位小数 |
e,E | 以指数形式输出实数,用e则出e,用E则显示E |
g,G | 选用%f或%e格式中输出宽度较短的一种格式,不输出无意义的0,用G时,若以指数形式输出,则指数以大写显示 |
2.7.7 练习题
第一题:
以下程序的输出结果是()
int a = 1234;
printf("%2d",a)
A) 12 B) 34 C)1234 D) 提示错误,无结果
==答案:C==
第二题:
已知字母A的ASCII码为十进制的65,下面程序的输出是______。
#include <stdio.h>
int main()
{
char ch1, ch2;
ch1 = 'A' + '5' - '3';
ch2 = 'A' + '6' - '3';
printf("%d,%c\n", ch1, ch2);
}
A、67,D B、B,C C、C,D D、不确定的值
==答案:A==
2.8 程序设计题目
第一题:
编写打印如下图形的程序(要求实现读取用户输入,打印几行图形,用循环实现),示例:输入4
输入5
#include <stdio.h>
int main()
{
int n, i, j;
scanf("%d", &n);
for (i = 0; i < n; i++)
{
for (j = 0; j < n - 1 - i; j++)
{
printf(" ");
}
for (j = 0; j < i + 1; j++)
{
printf("*");
}
printf("\n");
}
}
第二题:
经典题目:输入一个年份判断是闰年还是平年
#include <stdio.h>
int main()
{
int i;
printf("请输入一个年份:");
scanf("%d", &i);
if (i % 100 == 0)
{
if (i % 400 == 0)
{
printf("%d是闰年\n", i);
}
else
{
printf("%d是平年\n", i);
}
}
else if (i % 4 == 0)
{
printf("%d是闰年\n", i);
}
else
{
printf("%d年是平年", i);
}
return 0;
}
第三题:
编写程序:计算20到30的每个整数立方根之和(保留小数点后两位)
#include <stdio.h>
#include <math.h>
int main()
{
int i;
double s = 0;
for (i = 20; i <= 30; i++)
{
s = s + pow(i, 1.0 / 3); //如果平方根改为s=s+sqrt(i);
}
printf("%.2f\n", s);
return 0;
}
- 点赞
- 收藏
- 关注作者
评论(0)