考试月来临,划水划了大半学期,想起来我已经几个月没有打过C的代码了,C语言是刚开学的时候自学的,学院下学期才开设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';
(以0开头的表示八进制)
char ch = 0111;
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;
}
复制
3. 数组
数组是一组具有相同类型的数据的集合,这些数据称为数组元素。
3.1 一维数组
格式为:
类型符 数组名[常量表达式]
。数组的所占字节数为元素个数与基类型所占字节数的乘积。
3.1.1 一维数组的初始化
三种方式
-
int array[5] = {1,2,3,4,5}
-
int array[] = {1,2}
-
int array[2]; a[0] = 1;a[1]=2;
注意:
- 下标从0开始
- 数组内元素的个数不能大于声明的数组长度
- 当元素个数小于数组的长度时,多余的数组元素初始化为0
3.1.2 引用一维数组元素
数组元素可以通过数组名称加索引进行访问,格式为:数组名[下标]
int a = b[1];
复制
3.1.3 遍历一维数组
通过循环的方式可以写入和访问数组元素,而不用人为的每次获取指定某个位置上的元素
#include <stdio.h>
int main()
{
int i, a[10];
for (i = 0; i <= 9; i++)
{
a[i] = i;
}
for (i = 9; i >= 0; i--)
{
printf("%d ", a[i]);
}
return 0;
}
复制
上面的程序实现了给数组
a
赋值0-9,再按照下标大到小输出这10个元素
注意:
- 避免数组越界访问,循环变量
不要超过数组的长度i
- C语言中不存在
方法?,需要通过length
来计算数组长度sizeof
int length = sizeof(arr) / sizeof(arr[0])
复制
3.1.4 利用数组输出斐波那契数列
输出斐波那契数列的前20项,每5个换行
#include <stdio.h>
int main()
{
int i;
int f[20] = {1, 1}; //斐波那契数列前两位赋初值
for (i = 2; i < 20; i++)
{
f[i] = f[i - 2] + f[i - 1];
}
for (i = 0; i < 20; i++)
{
if (i % 5 == 0)
{
printf("\n");
}
printf("%d ", f[i]);
}
return 0;
}
复制
输出:
3.2 二维数组
多维数组中最简单的就是二维数组,二维数组有两个下标,用来确定它在数组中的位置。二维数组可以被认定为是一个由行列组成的方阵,但是在内存中是线性的,按行依次来进行存放
格式为:
类型说明符 数组名[常量表达式] [常量表达式]
3.2.1 二维数组的初始化
第一种
int num[2][3] = {{1,2,3},{4,5,6}};
复制
第二种
int num[2][3];
num[1][1] = 2;
复制
第三种
int a[2][3] = {1,2,3,4,5,6}
复制
注意:
- 由于系统会根据数组中元素的总个数来分配空间,所以当知道元素总个数以及列的维数后,会计算出行的维数
- 二维数组定义时可以不指定行,但是一定要指定列
3.2.2 引用二维数组元素
格式为:数组名[下标] [下标]
如:
a[1][2]
注意:
- 数组元素可以出现在表达式中,可以被赋值
b[1][2] = a[2][3]/2
- 在引用数组元素时,下标应在已经定义的数组大小的范围内
int a[3][4],但是不存在a[3][4]元素噢~
3.2.3 遍历二维数组
遍历二维数组采用的方式是双重
for
循环,变量
i
用来遍历行,
j
用来遍历列
#include <stdio.h>
int main()
{
int num[2][3] = {{1, 2, 3}, {4, 5, 6}};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d", num[i][j]);
}
}
}
复制
3.2.3 练习题
第一题
#include <stdio.h>
int main()
{
int i;
int x[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for(i = 0;i<3;i++) {
printf("%d ",x[i][2-i]);
}
}
复制
上面程序的输出结果是
A、1 5 9 B、1 47 C、3 5 7 D、3 6 9
答案:C
第二题
以下能正确定义数组并正确赋初值的语句是______。
A、
int N=5,b[N][N]
;
B、
int a[1][2]={{1},{3}}
;
C、
int c[2][]={{1,2},{3,4}}
;
D、
;
int d[3][2]={{1,2},{3,4}}
答案:D
3.3 字符数组
在C语言中没有字符串类型,也没有字符串变量,字符串是存放在字符型数组中的。
我们把用来存放字符数据的数组称为字符数组,数组中的每一个元素内存放着一个字符
3.3.1 字符数组初始化
-
char 字符串名称[长度] = "字符串"
-
char 字符串名称[长度]= {'字符','字符'}
注意:
-
中的长度可以省略不写[]
- 采用第二种方式定义数组,最后一个元素必须为
\0
- 如果初值个数小于数组长度,则后面自动补为
,\0
为字符串结束的标志\0
3.3.2 遍历输出字符数组中的元素
#include <stdio.h>
int main()
{
char c[] = "I am ljc";
for (int i = 0; i < sizeof(c) / sizeof(c[0]); i++)
{
printf("%c", c[i]);
}
return 0;
}
复制
先定义一个字符数组,然后通过for循环来访问输出字符数组中的字符
3.3.3 字符串的结束符
- 在存储字符串时,系统会自动在其尾部加上一个空值
,同时要占用一个字节,因此字符串\0
需要占四个字节。ljc
- 因此字符数组的大小要比它将要实际存放的字符串多一个元素,用来存放
\0
char c[] = "i am\0 ljc";
printf("%s\n",c);
复制
由于
\0
为字符串的结束标志,在输出字符串数组时遇到
\0
就会停止输出,因此只会输出
i am
3.3.4 字符串的输入输出
- 逐个字符输入输出,采用格式符
输入或输出一个字符%c
- 将整个字符串输入输出,采用
格式符,如%s
printf("%s\n",c);
注意:
- 输出的字符中不包括
\0
- 通过
输出时,输出表列填写的是数组名称,而不是数组元素%s
- 遇到第一个
就结束\0
- 在采用scanf输入字符串时,直接使用数组名称,不需要采用取地址符,因为数组名代表了数组的起始地址
特别注意
char str[13];
scanf("%s",str);
复制
对于上面的代码,当输入
i am ljc
时,只会把
i
存入数组当中。这是因为系统把空格当作了字符串之间的分隔符
3.3.5 练习题
若有定义和语句:
则结果是(以下u代表空格) ______。
A、输出abcd B、输出a
C、输出abcduuuuu D、编译不通过
char s[10];
s = "abcd";
printf("%s\n",s);
复制
答案:D
3.4 字符串处理函数
在使用之前需要引入头文件
string.h
序号 | 作用 |
---|---|
strcpy(s1, s2); | 复制字符串 s2 到字符串 s1。 |
strcat(s1, s2); | 连接字符串 s2 到字符串 s1 的末尾。 |
strlen(s1); | 返回字符串 s1 的长度。 |
strcmp(s1, s2); | 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。 |
strchr(s1, ch); | 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
strstr(s1, s2); | 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
3.4.1. strcat函数
字符串连接函数,它的作用是把两个字符数组中的字符串连接起来
使用方法
strcat(字符数组1,字符数组2)
下面程序输出
i am ljc i am 18
#include<stdio.h>
#include <string.h>
int main() {
char str1[] = "i am ljc ";
char str2[] = "i am 18";
printf("%s",strcat(str1,str2));
}
复制
3.4.2. strcpy函数
字符串复制函数,作用是将字符串2复制到字符数组1中
使用方法
strcpy(字符数组1,字符数组2)
输出:china
#include<stdio.h>
#include <string.h>
int main() {
char str1[] = "ljc";
char str2[] = "china";
printf("%s",strcpy(str1,str2));
}
复制
该方法会覆盖原来的字符串,并且不能拷贝字符串常量
注意:可以使用
strncpy
函数来指定复制字符串的字符数,例如
strncpy(str1,str2,2)
,作用是将
str2
中的前2个字符复制到
str1
中原有的前两个字符,
输出:chinajc
#include<stdio.h>
#include <string.h>
int main() {
char str1[] = "nameljc";
char str2[] = "china";
printf("%s",strncpy(str1,str2,5));
}
复制
3.4.3. strcmp函数
字符串比较函数,作用是比较字符串1和字符串2
比较的规则:将两个字符串自左向右逐个字符按照ASCII码值大小比较,直到出现不同的字符或者遇到
\0
结束
- 如果全部字符相同则认为两个字符串相等
- 若出现不相同的字符,则以第一对不相同的字符的比较结果为准
比较结果由函数值带回
- 如果字符串1和字符串2相同,则函数值为0
- 如果字符串1大于字符串2,则函数值为1个正整数
- 如果字符串1小于字符串2,则函数值为1个负整数
使用方法
下面的程序输出1,表示字符串1小于字符串2
#include<stdio.h>
#include <string.h>
int main() {
char str1[] = "nameljc";
char str2[] = "china";
printf("%d",strcmp(str1,str2));// 1
}
复制
3.4.4. strlen函数
测字符串长度的函数,作用是检测字符串长度
使用方法
strlen(str)
输出:5,可见输出的是字符串的实际长度,不包括
\0
#include<stdio.h>
#include <string.h>
int main() {
char str[] = "china";
printf("%d",strlen(str));
}
复制
3.4.5. strlwr函数
将大写转换为小写的函数
使用方法
strlwr(字符串)
输出:ljc
#include<stdio.h>
#include <string.h>
int main() {
char str[] = "LJC";
printf("%s",strlwr(str));
}
复制
3.4.6. strupr函数
将小写转换为大写的函数
使用方法
strupr(字符串)
输出:
I AM LJC
#include<stdio.h>
#include <string.h>
int main() {
char str[] = "i am ljc";
printf("%s",strupr(str));
}
复制
3.4.7 练习题
函数调用:strcat(strcpy(str1,str2),str3)的功能是______。
A、将串str1复制到串str2中后再连接到串str3之后
B、将串str1连接到串str2之后再复制到串str3之后
C、将串str2复制到串str1中后再将串str3连接到串str1之后
D、将串str2连接到串str1之后再将串str1复制到串str3中
答案:C
博主累了,码了几天,已经码了上万字了,自己也是一边复习一边整理,感觉还不错噢,相信你也一定能够学到很多噢!挂科不存在的!