Bootstrap

C语言期末复习|最后的总结

 

目录

(一)C程序

(二)main(主)函数问题

(三)自定义标识符

(四)变量/形参/实参

(五)表达式

(六)数据类型

(七)注释

(八)预处理命令

(九)语句

(十)输出

(十一)return(返回)

(十二)(自定义)函数

(十三)循环

(十四)字符常量

(十五)字符串常量

(十六)转义字符

(十七)运算符及其优先级

(十八)数组

(十九)分支结构

(二十)字符(串)函数

(二十一)指针

(二十二)字节数

(二十三)宏名

(二十四)链表+文件

(二十五)结构体

(二十六)逻辑值

(二十七)不同进制

(二十八)递归

--------------------------------------------------------------------------------------

(一)判断闰年的条件。

1.编写一个函数 isLeapYear,该函数接收一个整数 year 作为参数,判断该年份是否为闰年。如果是闰年返回 1,否则返回 0。

2.编写一个程序,计算从 startYear 到 endYear(包括 startYear 和 endYear)范围内的闰年数量。

4.计算某一日是某一年中的第几天

(二)一维的比较

1.输出a,b,c中的最大值:

2.求两个整数中的较大者

3.将a,b,c,按从大到小顺序输出:

(三)排序的基本结构

1.冒泡排序

2.选择排序

(四)1-1/2+1/3-1/4+...+1/99-1/100。

(五)递归求阶乘

(六)删除s字符串中的c字符:

(七)把两个字符串连在一起:

(八)把大写字母转换成小写字母:

 (九)素数

1.判断是否为素数

2.输出指定范围内的素数

(十)斐波那契数列

(十一)两个正整数的最大公约数和最小公倍数

(十二)汉诺塔

(十三)反序问题

1.字符串反序

2.数组反序

3.整数反序

(十四)把数组右移几位

(十五)用结构写学生的成绩并排序,包括名字,学号,两个以上的学科

(十六)打印乘法口诀表

(十七)计算数字的每位数字之和


(一)C程序

1.C程序由函数所组成。

2.程序设计语言必须具备数据表达和流程控制的功能。

3.程序与数据一样,共同存储在存储器中。当程序要运行时,当前准备运行的指令从内存被调入CPU中,由CPU处理这条指令。这种将程序与数据共同存储的思想就是目前绝大多数计算机采用的(冯•诺伊曼 )模型的存储程序概念。

4.一个C程序必须一个或一个以上的函数组成。

5.结构化程序设计的3种结构是( )。顺序结构,选择结构,循环结构

6.C 语言源代码需要经过编译过程才能转换为机器语言。

7.系统默认的C语言源程序扩展名为.c,需经过_____编译、连接_____后,生成.exe文件,才能运行。

8.C语言兼有高级语言和低级语言的双重特点,执行效率高

9.C语言既可以用来编写应用程序,又可以用来编写系统软件

10.C语言是一种结构式模块化程序设计语言

11.C 语言具有较好的可移植性。

12.完成C源程序编辑后,到生成执行文件,C语言处理系统必须执行的步骤依次为( 编译、连接)

13..在计算机内部,一切信息(包括数值、字符、指令等)的存储、处理与传送均采用二进制的形式。

(二)main(主)函数问题

1.main函数是C程序的主函数。

2.所有的C程序都有且只有一个main函数。

3.C程序是main函数开始执行的,到main函数结束

4.main函数可以放在任意位置。

(三)自定义标识符

在 C 语言中,自定义标识符是由程序员为变量、函数、结构体、联合体、枚举、宏、标签等命名时使用的名称。

1.大小写字母含义不同。APH 和 aph 代表不同的变量。

2.C语言的标识符由字母、数字和下划线组成。

3.第一个字符必须是字母或下划线。

4.第一个字符不能是数字。9ab是非法的用户标识符。

5.C语言中的变量名属于标识符。

6.C 语言的关键字(保留字)是具有特殊含义的标识符,它们被 C 语言的编译器保留,不能用作变量名、函数名等普通标识符。

7.main 是 C 语言程序的入口函数,但它不是关键字。可以将 main 函数命名为其他名称,但这样会导致程序无法正常执行,因为编译器默认从 main 函数开始执行程序。

(四)变量/形参/实参

1.不同类型的变量,在内存中占用不同大小的空间。

2.C 语言中的变量名区分大小写。

3.变量生命周期是指变量从定义开始分配存储单元到运行结束存储单元被回收的整个过程。

4.变量的作用域是指变量在程序中可以被访问的范围。

6.寄存器类变量的作用域和寿命与自动类变量的相同。

7.静态局部变量的作用域是其声明所在的函数内部,不是整个文件。

8.当变量的存储类型缺省时,系统默认为变量的存储类型为 auto 类型。auto 类型的变量是分配在栈区,而不是静态区。

9.实参向形参进行数值传递时,数值传递的方向是单向的,即形参变量值的改变不影响实参变量的值。

10.函数形参的作用域是函数内部,只在函数被调用并执行时存在,并且仅在该函数内部可见。

11.在函数内定义的变量称为局部变量。

12.形参是函数定义时声明的参数,而实参是函数调用时传递给函数的实际参数。

13.实参和形参的命名可以重复,因为它们处于不同的作用域。

14.自动变量(通常是在函数内未加 static 关键字声明的变量)如果没有显式赋值,其值是未定义的。这意味着该变量可能包含任意的随机值,而不是自动赋为 0。

15.静态局部变量如果没有显式赋值,其存储单元会被自动初始化为 0(对于数值类型)或 '\0'(对于字符类型)。

16.函数定义时,括号中的参数是形式参数;而函数调用时括号中的参数是实际参数。

17.全局变量和函数内的局部变量可以同名,但在函数内部,局部变量会屏蔽全局变量,即在函数内部访问该名称时,优先使用局部变量。

18.函数形参的存储单元是动态分配的。

19.函数的实参可以是常量,变量或表达式。

20.函数调用结束后,形式参数释放内存

21.如果在一个函数的复合语句中定义了一个变量,则该变量只在该复合语句中有效,在该复合语句外无效

22.下面函数调用语句含有实参的个数为( 2)

func((a,b,c,d),(e,f,g));

在 C 语言中,逗号运算符 , 用于分隔多个表达式,并从左到右依次计算这些表达式的值,整个逗号表达式的值是最后一个表达式的值。实际上相当于 func(d, g);

23.从变量的存储类型来看,不能对变量进行初始化的是extern

24.在C语言中,表示静态存储类别的关键字是: static

25.C语言的全局变量的初始化是在以下哪个阶段完成的:main()函数开始前

26.在一个C源程序文件中,如要定义一个只允许本源文件中所有函数使用的全局变量,则该变量需要使用的类型修饰是:static

27.如果一个变量在整个程序运行期间都存在,但是仅在说明它的函数内是可见的,这个变量的存储类型应该被说明为:静态变量

28.凡是函数中未指定存储类别的局部变量,其隐含的存储类型为自动(auto)

29.将一个函数说明为static后,该函数将只能被同一源文件中的函数调用,不能被其他源文件中的函数调用

30.在一个源文件中定义的全局变量的作用域是从定义该变量的位置开始到本文件结束。

31.若用数组名作为函数调用的实参,传递给形参的是数组的首地址

32..若使用一维数组名作函数实参,则以下正确的说法是在被调函数中,与该实参相对应的形参必须是指针型变量

33.当函数的参数是数组名时,实际上传递的是数组的首地址,而不是在函数中新建一个数组。

34.若有以下变量定义double x, *y;

x 是 实型变量,y 是 实型指针.

35.以数组名作函数参数时,实参数组与形参数组都不必定义长度,因为实参与形参的结合方式是地址结合,与数组长度无关。

36.直接访问就是直接利用变量的地址直接进行访问。

37.int **pp; 定义了一个指针,该指针是一个指向指针的指针。可以用来存储另一个 int * 类型指针的地址。

38.语句int *p; *p = 50;执行时,定义了一个 int * 类型的指针 p但它未被初始化,此时 p 的值是不确定的,它可能指向任意的内存位置。由于 p 未被初始化,它指向的内存位置是不确定的,向一个不确定的内存位置写入数据会导致未定义行为。这可能会导致程序崩溃、数据损坏或其他意外结果。

39.在C程序中,变量须遵循先定义后使用的原则,使用指针变量前,必须先对它们进行定义。

40.

全局变量:定义在函数外部的变量

局部变量:定义在函数内部的变量,包括形参。

作用域  生命周期 默认值
全局变量从定义开始到整个文件结束程序运行创建,程序结束才销毁默认为0(不要使用)
局部变量只在本函数内部使用从进入函数创建,函数结束就销毁默认值无效(随机值)

static:静态,修饰变量或者函数。

作用域 生命周期 默认值
(普通)局部变量只在本函数内部使用从进入函数创建,函数结束就销毁默认值无效
静态局部变量只在本函数内部使用从第一次进入函数创建,程序结束才销毁默认值为0

static可以改,创建后不死。static那一行代码只有第一次调用的时候才会运行,其他时候是直接跳过这一句。

存储类别:自动的(auto),静态的(statis),寄存器的(register),外部的(extern)

auto:在C语言里面是默认自动的,在c++里面会用。

register:建议编译器对这个变量进行优化,这个变量会多次使用,建议把他从内存器加载到寄存器。

(五)表达式

表达式是由操作数和运算符组成的式子,其结果的类型和值取决于操作数的类型和运算符的性质。

1.任何表达式语句都是表达式加分号组成的。

2.增1减1运算符的前缀运算和后缀运算的表达式值是不同的。

3.类型有算术表达式,逻辑表达式,关系表达式,赋值表达式,所以表达式的值不一定是什么。

4.关系表达式是指使用关系运算符(如 ==!=<><=>=)将两个表达式连接起来,其结果为布尔值(在 C 语言中,通常用 0 表示 false1 表示 true)。

5.表达式 ( (ch = getchar() ) != '\n') 是关系表达式。

6.表达式 a = 3, 5 符合 C 语言语法。逗号运算符会依次计算其分隔的表达式,将最后一个表达式的值作为整个表达式的结果,但在 a = 3, 5 中,通常只关心 a = 3 的赋值操作,而 5 的结果被忽略。

7.在条件表达式(exp)?a:b中,表达式(exp)与表达式(exp!=0)完全等价。

先计算 exp 的值。如果 exp 的值为非零(即 true),则整个表达式的值为 a。如果 exp 的值为零(即 false),则整个表达式的值为 b

当使用 (exp) 时,它等价于 (exp!= 0),因为:如果 exp 的值为非零,(exp) 为 true,同时 (exp!= 0) 也为 true。如果 exp 的值为零,(exp) 为 false,同时 (exp!= 0) 也为 false

8.表达式1&&表达式2:都为真,才为真。注意短路现象,如果表达式1为假,表达式2不计算。

表达式1||表达式2:只要有一个为真就为真。注意短路现象,如果表达式1为真,表达式2不计算。

(六)数据类型

1.C语言中,当int型与double型数据进行算术运算时,数据类型由int型向double型转换。

2.C语言中的基本数据类型包括整型。字符型。浮点型。

3.在 C 语言中,常量 10.0 是双精度浮点类型(double)的数据,而不是单精度浮点类型(float)。要使用单精度浮点常量,可使用后缀 f 或 F,以明确表示 float 类型,避免不必要的隐式类型转换。

4.double a = 5E-3;  是一个合法的语句,使用科学计数法表示浮点数。表示将浮点数 a 的值初始化为5*10^-3,3E4表示为3*10^4.

5.C语言中,字符型数据可以和整型数据进行相互转换。

6.在C 语言中,常量和变量都有数据类型。

7.在C语言中,数字029是一个非法数

8.在 C 语言中,(double)x 是一种类型转换操作,将 x 的值转换为 double 类型。但是,这种类型转换操作并不会改变 x 本身的类型。

9.若有int a=10; 则执行完表达式a+=a-= a*a后,a的值为

赋值运算符(包括复合赋值运算符,像 `+=`、`-=` 等)的优先级低于算术运算符(如乘法 `*`),并且复合赋值运算符是从右到左结合的。

先计算 `a * a`因为 `a` 的初始值为 `10`,所以 `a * a` 的结果是 `10 * 10 = 100`。

`a -= 100` 等价于 `a = a - 100`,此时 `a` 的值为初始的 `10`,经过计算可得:`a = 10 - 100 = -90`。

`a += -90` 等价于 `a = a + (-90)`,此时 `a` 的值已经变为 `-90` 了,再进行计算:`a = -90 + (-90) = -180`。

所以,执行完表达式 `a += a -= a * a` 后,`a` 的值为 `-180`。

(七)注释

1.在程序中插入适当的注释,用来说明程序的功能,可以使程序容易被人理解。

2.程序编译时,不会对程序的注释进行处理。

3.C 风格的注释,也称块注释或多行注释,以 ▁▁▁ 开始,以 ▁▁▁ 结束。/* 和 */

4.C程序中的注释部分不会参与程序的编译和执行。

5.注释可以位于程序的任何位置,并不必须位于语句之后。

(八)预处理命令

1.调用printf函数前,应使用编译预处理命令#include <stdio.h>。

2.C语言的编译预处理功能包括()。文件包含。宏定义。条件编译。

3.C语言中的预处理命令都以“#”开头

4.在 C 语言中,#include <stdio.h> 和 #include "stdio.h" 都是正确的预处理指令,但它们的查找文件的方式有所不同。

(九)语句

1.除了复合语句,C语言中的所有语句都必须以分号结束。

2.空语句是由一个分号 ; 组成的语句。空语句在某些情况下是有用的,例如在循环或条件语句中,当你不需要执行任何操作时,可以使用空语句。

3.在 C 语言中,一行可以写多条语句,只要每条语句以分号 ; 结束即可。

(十)输出

1.C语言中可以用printf函数输出字符。

2.printf 函数根据格式控制符来解释传递给它的参数并输出相应的内容。它并不自动进行数据类型转换,而是期望传递给它的参数类型与格式控制符匹配。

3.调用printf函数,%s的格式输出字符串时,字符数组名、字符指针和字符串常量都可以作为输出参数。

5.其中整数的宽度为10,左对齐,并且数字的前面带正负号;实数的宽度为20,其中小数3位;字符不做特别要求。

printf("a=%+-10d,b=%20.3f,c=%c", a, b, c);

6.用float 和%f即可输出六位小数:

(十一)return(返回)

1.return 语句可以出现在函数的任何地方

2.函数的返回类型包括基本数据类型、指针类型、结构体类型、联合体类型、枚举类型或 void(表示不返回任何值)。基本数据类型:int,longshortlong long,float,double,char。

3.如果函数的返回类型是指针,不可以返回函数内部任意变量的地址。

4.函数通常使用 return 语句返回一个值,该值的类型在函数声明时指定。所以不可以返回两个以上的值。

5.函数返回值的类型是由在定义函数时所指定的函数类型。

6.如果函数的返回类型没有明确指定,那么默认返回类型是 int

7.如果有函数char *func(char *p, char ch),则下面说法错误的是( C)

A.函数返回一个字符指针

B.可以通过语句"return NULL;"返回函数结果

C.可以通过语句"return -1;"返回函数结果

D.可以通过语句"return p;"返回函数结果

8.函数执行时遇到return,不管其内是否还有未执行的代码,都会结束函数调用;

(十二)(自定义)函数

1.函数定义可以在主函数前面也可以在主函数后面。

2.函数的调用顺序和定义顺序无关。(只要在调用之前进行了函数声明即可,可以不在调用之前定义,可以把定义放在后面,但一定要有声明前提)

3.函数名代表该函数的入口地址。因此,可用函数名给指向函数的指针变量赋值。

4.C 语言不允许在一个函数内部定义另一个函数。函数定义不能嵌套在其他函数的内部

5.虽然不能在函数内部定义函数,但可以在一个函数内部调用其他函数,这被称为函数调用的嵌套。

7.将一个函数说明为static后,该函数将 只能被同一源文件中的函数调用,不能被其他源文件中的函数调用

8.函数调用不可以做一个函数的形参。

9.sizeof 是 C 语言中的一个运算符,而不是函数。它用于计算数据类型或表达式在内存中所占的字节数。

10.getchar 函数的主要功能是从标准输入读取一个字符。它每次调用只返回一个字符,并且返回值是 int 类型,通常可以存储在 char 类型的变量中(考虑到返回的是字符的 ASCII 码)。所以不能用它输入一个字符串。

11.scanf()函数在读不到数据时返回EOF

12.函数声明时,可以不声明形参的变量名,但不能不声明类型。

13.如果函数定义出现在函数调用之前,可以不必加函数原型声明。

14.C语言中有两种类型的函数,分别是标准库函数与自定义函数

15.函数调用可以出现在执行语句、表达式和作为另一个函数的实参,但不能作为一个函数的形参。

17.要通过函数调用来改变主调函数中某个变量的值,可以把指针作为函数的参数。

18.在用数组名作函数参数时,下面两种函数声明是无区别的。
①void fun(int arr[], int n);
②void fun(int *arr, int n) ;

19.在说明语句“ int *f( );”中,标识符 f 代表是(一个返回值为指针型的函数名 )

20.若有函数max(a,b),并且已使函数指针变量p指向函数max,当调用函数时,正确的调用方法是((*p)(a,b);)。

21.若有函数max(a,b),为了让函数指针变量p指向函数max,正确的赋值方法是( p=max;)。

(十三)循环

1.在for(表达式1;表达式2;表达式3)中,如果表达式2为空,表示循环条件默认为真。

2.break语句可以用在循环体和switch语句中,但continue语句只可以用在循环体中。

3.c语言中三种循环语句可以相互嵌套。

4.while 和 for 语句的循环体不一定至少执行一次。可能一次都不执行。do-while 语句的循环体至少会执行一次。

5.continue 语句只能用于循环语句中。

6.在if语句的三种形式中,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用{}括起来组成一个复合语句。

7.if(a=5) 是允许的。

8.else 总是与它上面最近的且尚未配对的 if 配对。

9.在c程序中,else的个数不能多于if的个数。

10.continue 语句的功能是结束本次循环的执行,而不是终止整个循环。当 continue 语句被执行时,程序将跳过本次循环中 continue 语句之后的代码,直接进入下一次循环的迭代。

11.在多层循环中, 一个break语句只向外跳一层。

12.do-while 循环的语法结构为:

do {
    // 循环体语句
} while (表达式);

while 后面的分号 ; 是 do-while 循环语法的一部分,不能省略。

13.执行以下while语句,将出现死循环。(对)

s = 0;i = 1;

while(1){  if(i > 10){   continue;   } s = s + i; i++;}

14.对for(表达式1;;表达式3)可理解为for(表达式1;1;表达式3)。

15.在 C 语言的嵌套循环结构中,break 语句只能结束其所在的那一层循环,而不能结束整个嵌套循环的执行。

16.要求通过 while 循环不断输出字符,当读入字母 N 时结束循环。若变量已正确定义,下列程序段正确的是

while ( (ch = getchar( )) != 'N')

printf("%c", ch);

 17.while语句的一般形式如下,当表达式的值为“真”时,循环执行,直到表达式的值为“假”,循环中止并继续执行while的下一条语句。

while (表达式)

    循环体语句

18.for语句的一般形式如下,若表达式2的值为“假”,则结束循环。

for (表达式1; 表达式2; 表达式3)

    循环体语句

19.break语句不能与以下哪个语句配对使用if…else

(十四)字符常量

1.C语言中的字符常量指单个字符,用一对单引号及其所括起的字符来表示。

2.'A' 是一个字符常量,它表示字符 A。在内存中,它存储的是字符 A 的 ASCII 码值,对于 ASCII 字符集,'A' 的值是 65(十进制)。它是一个单字节的数据,可以存储在 char 类型的变量中。

3. 若有定义:char ch='\105’;则变量ch中包含1个字符。在 C 语言中,\ 后面跟三位八进制数字表示一个字符的八进制 ASCII 码值。对于 char ch = '\105';,这里的 \105 是一个字符的八进制表示char ch = '\105'; 表示将八进制 ASCII 码为 105 的字符存储在 ch 中。\105 是一个八进制数,转换为十进制是69,十进制 69 对应的 ASCII 字符是 E

4.C语言中,字符型数据可以和整型数据进行相互转换。

5.在 C 语言中,字符型变量使用 char 数据类型来表示。一个 char 类型的变量在内存中占用 1 个字节,通常用于存储一个字符。所以一个字符型变量中不可以存放多个字符。

(十五)字符串常量

1."A" 是一个字符串常量,它表示包含字符 A 和字符串结束符 '\0' 的字符串。在内存中,它占用两个字节,第一个字节存储 A 的 ASCII 码值(65),第二个字节存储 '\0'。它是一个字符数组,存储在静态存储区,通常使用 char* 或 char[] 来表示。

2.字符串常量在内存中的存放位置由系统自动安排。

3.字符串常量实质上是一个指向该字符串首字符的指针常量。

4.判断字符串a和b是否相等的表达式为if (strcmp(a, b) == 0)

5.字符串常量就是用一对双引号括起来的字符序列,它有一个结束标志 '\0'。

6.char c2[3]="123";而这里定义的字符数组 c2 长度为 3,字符串 "123" 加上末尾的 '\0' 实际需要 4 个字符的存储空间

7.字符串常量赋值要用strcpy(s,"123456");

10.读取一行字符:while((ch=getchar())!='\n')

(十六)转义字符

1.转义字符只占用一个字节,表示一个字符。

2.转义字符 \101 是一个八进制转义序列,它表示一个字符。\101 是用八进制数 101 表示的字符,对应的 ASCII 码字符是 A。

3.C语言中的转义字符‘\n’表示的功能是换行。

5.在 C 语言中,\t是一个转义字符,它代表水平制表符(tab),制表位通常是每 8 个字符位置一个(这是一种常见的设置,但不是绝对的)。

6.%4d(右对齐):当使用%4d进行输出时,输出结果会占据 4 个字符的宽度。因为5本身只占 1 个字符位置,所以在前面会填充 3 个空格,输出结果是 5(这里用空格来表示填充的字符)。

7.%-4d(左对齐):与%4d(右对齐,前面填充空格)不同,%-4d把整数放在输出区域的左边,剩余的宽度用空格在右边填充。

8.%.2f:保留两位小数。

9.%6.2f:这个数一共占6位,小数点后2位。

(十七)运算符及其优先级

1.可以使用圆括号改变运算符的运算次序。

2.C语言中的移位运算符(如<<、>>)只能用于整型(如int、short、long、char等),不能用于浮点型(如double、float)。

3.sizeof 是 C 语言中的一个运算符,而不是函数。它用于计算数据类型或表达式在内存中所占的字节数。

4.在 C 语言中,运算符 “+” 可以作为单目运算符使用。

5.c语言中运算符%的优先级高于&&。

6.求余数运算符 % 只能用于整型数据(如 intlong 等)。不是实型数据,像float 或 double就不可以。

7.在逻辑运算符中,逻辑非(!)的优先级别最高。

8.以下运算符优先级按从高到低排列正确的是算术运算、关系运算、赋值运算

9.C/C++语言中,要求运算对象只能为整数的运算符是%

10.假设某段C语言程序中定义了三个变量a、b和c并且三个变量都不为0,则表达式a / b * c和a * c / b是等价的,其值不同。对于整数,/ 是整数除法,会截断结果。对于浮点数,结果可能相同,但运算过程是浮点数运算,结果的精度更高。

11.a=2++(++和别的符号不能放在一起)a=a+1=3(不能连等)12.3%4(% 取模运算符只能用于整数类型)

(十八)数组

1.数组定义中,数组名后是用方括号括起来的常量表达式,不能用圆括号。

2.数组定义后,数组名的值是一个地址,但不可以被修改。

3.C语言里数组元素的下标是从0开始的。

4.数组的下标可以是一个表达式,但是表达式计算得到的值必须是一个整数。

5.在C语言中,数组名是一个常量(指针常量),不能被赋值。

6.对于已正确定义的二维数组a, *(a[i]+j)与a[i][j]的含义相同a[i][j] 表示第 i 行第 j 列的元素。

*(a[i] + j) 的含义a[i] 本身是一个指针,它指向二维数组 a 的第 i 行的首元素。当使用 a[i] + j 时,得到的是指向第 i 行第 j 列元素的指针。然后使用 * 运算符进行解引用,就可以得到第 i 行第 j 列的元素。

7.对于二维数组,在声明时必须明确指定列数,行数可以根据初始化元素的数量和列数来推断。

8.对于一维数组,例如:int arr[3]; 则arr[3]表示它包含 3 个元素。

9.对于结构数组 s,不仅可以引用数组的元素 s[i],还可以引用 s[i] 中的结构成员。

10.二维数组定义的一般形式如下,其中的类型名指定数组中每个元素的类型。

类型名 数组名[行长度][列长度];

11.对二维数组初始化时,也可以采用如下顺序赋初值的方式,即在定义数组时,根据数组元素在内存中的存放顺序,把初值表中的数据依次赋给元素。

类型名 数组名[行长度][列长度] = {初值表};

12.在对二维数组全部元素赋初值时,可以省略行数,但不能省略列数。

14.数组的长度必须是常量表达式,不能是变量。

15.当数组初始化时,如果初始值的个数小于数组元素的个数,未初始化的元素会被自动初始化为 0(对于数值类型)或 '\0'(对于字符类型)。

16.数组定义后,数组名表示该数组所分配连续内存空间中第一个单元的地址,即首地址,是一个常量,不能被修改。

17.字符串比较的规则是对两个字符串自左至右逐个字符相比(按ASCII码值大小比较),直到出现不同的字符或遇到'\0'为止。

18.对于 char s[80]; 这样的字符数组,不能直接使用 s = "hello"; 这样的赋值语句。要用strcpy(s, "hello");

 19.在对全部数组元素赋初值时,可以不指定数组长度。

20.一个数组中的每个成员都必须具有相同的数据类型,用数组名加不同的序号即下标来区分数组中的各元素。

21.一维数组的元素实质上就是一个变量,代表内存中的一个存储单元

22.在C/C++语言中引用数组元素时,数组下标的要求,下列选项中最合适的是( 整型表达式) 。

23.c语言对数组下标越界不作检查。 

24.在C语言中,数组名是一个常量,不能被赋值。

25.char s[6] ; s="ABCDE";是错误的

s 是一个数组名,它在 C 语言中代表的是数组的首地址,并且是一个常量,不能作为左值进行赋值操作。

数组名本身是一个不可修改的常量,它在程序的编译阶段就已经被确定了地址,不能被重新赋值为另一个地址。

26.若有定义char *cc[2]={"1234","5678"};以下叙述中正确的是( A)。

A.cc数组的两个元素中各自存放了字符串"1234"和"5678"的首地址。cc[0] 存储字符串 "1234" 的首地址,cc[1] 存储字符串 "5678" 的首地址。

C.cc是指针变量,它指向含有两个数组元素的一维字符数组。cc 是一个数组,不是指针变量,数组元素是指针。

D.cc数组元素的值分别是"1234"和"5678"。cc 数组元素存储的是字符串的首地址,而不是字符串本身。

27.根据声明int (*p)[10], p是一个指针

28.若有定义“int k[ 2][3], * pk[ 3];”, 则下列语句中正确的是(B)。

A.pk =k; k 是一个二维数组,pk 是一个指针数组,它们的类型不匹配,不能直接赋值。

B.pk[0] =&k[1][2]; pk[0] 是 int * 类型的指针,&k[1][2] 是 k[1][2] 的地址,将 k[1][2] 的地址赋给 pk[0] 是合法的。

C.pk= k[0]; k[0] 是一个指针,指向 k[0][0],但 pk 是一个数组,不能直接赋值。

D.pk[1]=k;k 是一个二维数组,pk[1] 是一个指针,类型不匹配。

29.若有定义int a[2][3]={2,4,6,8,10,12};则*(&a[0][0]+2*2+1)的值是12,*(a[1]+2)的值是12。

*(&a[0][0]+2*2+1) 的分析

&a[0][0] 是 a[0][0] 的地址。2*2+1 表示将地址向后移动 5 个元素位置(从 a[0][0] 开始)。*(&a[0][0]+2*2+1) 是对移动后的地址所指向元素的间接引用。

*(a[1]+2) 的分析

a[1] 是一个指向 a[1][0] 的指针。a[1]+2 表示将 a[1] 指针向右移动 2 个元素。*(a[1]+2) 是对移动后地址所指向元素的间接引用。

30.若有语句 int a[][3]={1,2,3,4,5,6,7}; ,则a数组高维的大小是3

由于初始化列表中的元素个数为 7,而列数(低维)是 3。那么行数(高维)可以通过元素总数除以列数来计算,但由于元素总数可能不完全是列数的倍数,会自动补充 0 直到满足二维数组的存储要求。这里元素总数可以按列数 3 来划分,有 3 组,因此高维的大小是 3。

(十九)分支结构

1.在switch语句中不一定有default语句。

2.在switch语句中,不一定使用break语句。

3.switch 语句可以形成多个分支,而不局限于三个。

4.switch语句中多个case标号可以共用一组语句。可以这样写:case 9:case 10:k=5;break;

5.switch语句中,每一个case的冒号后面都允许跟有多条语句。

6.switch 语句中的表达式 x 只能是整型表达式,包括 int 类型、char 类型(因为 char 可以隐式转换为 int)以及枚举类型。

7.switch 语句的case 后面只能是常量表达式

8.C语言中要实现多分支结构, 除了用嵌套的if语句实现外, 还可以用if-else | if else语句和switch-case | switch case | switch | if-switch | if switch语句实现。

(二十)字符(串)函数

1.函数调用strcat(strcpy(str1,str2),str3)的功能是将字符串str2复制到str1中,然后再将字符串str3连接到str1之后。

2.字符串一定要记得给‘\0’留个位置。如char str[5]="good!"这样赋值是错误的,没有给‘\0’留位置

3.比较两个字符串的大小并不要求它们的字符个数相同。

4.判断字符串a是否大于b,可以表示为 if (strcmp(a,b)>0)

(二十一)指针

1.语句int *p;和printf("%d",*p);中的*p含义不同。

2.专门存放地址的变量,称为指针变量

3.如果声明了一个指针变量但没有给它赋值,它不会自动指向程序的开始部分。

4.指针变量可以用来存储数组的地址,通过指针变量可以访问和操作数组元素。

5.定义指针函数变量后,将一个函数名赋值该指针变量,要求函数的参数个数、类型一致。

6.指针所占内存的大小并不由其指向的数据类型的大小决定。指针的大小由操作系统和编译器决定,通常取决于地址总线的宽度。不同类型的指针(如 int*char*double*)在相同的系统和编译器环境下通常具有相同的大小。

7.指向结构体变量的指针可以作函数参数,实现传址调用。

8.可以通过指针运算使指针指向数组的任意元素,并不只可指向数组的首元素。

9.若有定义char* p="computer";p 的值是字符串 "computer" 存储在内存中的首地址,而不是字符串本身。

10.若要用下面的程序片段使指针变量p指向一个存储浮点型变量的动态存储单元:

float *p;

p=____(float *)______ malloc( sizeof(float));

12.如果有声明 int a[] = {2, 4, 6, 8, 10},*p = a;a 的值是数组的首地址,那么 *(p++) 的值是2.

对于 int a[] = {2, 4, 6, 8, 10};a 的值是数组的首地址。*p = a; 表示 p 是一个指向数组 a 的指针,p 也指向数组的首地址。*(p++) 表示先取 p 所指向的元素的值,然后将 p 指针向后移动一个元素的位置。初始时 p 指向 a[0]*(p++) 首先取 p 指向的元素的值,即 a[0] 的值,为 2。然后 p 指针向后移动一个元素的位置,指向 a[1]

13.指针变量中保存的肯定是一个地址。

14.指针变量的使用方法与普通变量一致,都可以进行赋值和取值操作。

16.*p = &i; 是错误的。首先,p 是一个指针,但未被初始化,它可能指向任意的内存地址,使用未初始化的指针会导致未定义行为。其次,*p 是对 p 所指向的内存进行解引用操作,而 &i 是 i 的地址,这里将 i 的地址赋给 p 指向的内存是错误的,应该将 i 的地址赋给 p 本身,而不是 *p

17.对于基类型相同的两个指针变量,不能进行的运算是+。因为指针表示的是地址,地址相加不能明确表示某个有用的信息,所以 C 语言不允许这样的操作。

18.执行语句“char c[10]={"abcd"},pc=c;”后,表达式“(pc+4)”的值是'd'

在 C 语言中,对于 char c[10]={"abcd"};c 是一个字符数组,存储字符串 "abcd"pc = c; 表示 pc 是一个指向 c 数组的指针,初始时 pc 指向 c[0]pc + 4 表示将指针 pc 向后移动 4 个元素位置。pc + 4 是一个指针,指向 c[4] 的地址。*(pc + 4) 才是取 pc + 4 所指向元素的值,即 c[4] 的值。

19.若有以下定义和语句,则表达式“p2-p1”的值是5

int a[10], *p1,*p2;
p1=a;
p2=&a[5];

p2 - p1 计算两个指针之间的距离,以元素个数为单位。

20.对于下面代码,*p 是什么?5

int a[5] = {2, 3, 4, 5, 6}, *p = &a[2] + 1;

在 C 语言中,对于 int a[5] = {2, 3, 4, 5, 6};,这是一个整型数组。*p = &a[2] + 1; 表示将 p 指针初始化为 &a[2] + 1&a[2] 表示 a[2] 的地址,即数组中元素 4 的地址。&a[2] + 1 表示将指针向后移动一个元素的位置,指向 a[3] 的地址。*p 是对 p 所指向元素的引用。

21.设有定义:int  a[3]={1,2,3},*p,b;p=a;(*p)++;p++;b=*p;

a[0]的值为  2,b的值为  2,p+1指向元素a[2]

(*p)++ 表示先对 p 所指向的元素(即 a[0])进行解引用,然后将该元素的值加 1。所以 a[0] 的值从 1 变为 2。p++; 表示将指针 p 向后移动一个元素的位置,此时 p 指向 a[1]b = *p; 表示将 p 所指向的元素(现在是 a[1])的值赋给 b,所以 b 的值为 2。初始时 p 指向 a[0],经过 p++; 后,p 指向 a[1],那么 p + 1 将指向 a[2]

22.指针数组的每个元素都是一个指针变量。

23.p[i]还可以用*(p+i)指针形式来表示

24.对于定义int a[5],*p=a;后,*(p+1)和*(a+1)的值是相同的。

25.int (*p)[4] 并不表示 p 是一个指针数组。它表示 p 是一个指针,该指针指向一个包含 4 个整型元素的数组。

26.char *s="C Language";表示s是一个指向字符串的指针变量,把字符串的首地址赋予s。

27.数组的基地址是在内存中存储数组的起始位置,数组名本身就是一个地址即指针值。

28.int *p[5]; 表示 p 是一个数组,数组包含 5 个元素,每个元素是一个 int * 类型的指针。p[0] = &a; 等语句将指针元素分别指向不同的整型变量。*(p[i]) 用于获取指针 p[i] 所指向的元素的值。

29.定义一个指针数组并初始化赋值若干个字符串常量,则指针数组并不存放这些字符串,而仅仅指向各个字符串。

30.以下哪个定义中的p不是指针,请选择恰当的选项:C

A.char **p; 这是一个指向指针的指针。

B.char (*p)[10]; 这是一个指针,指向一个包含 10 个字符的数组。

C.char *p[6]; 这是一个数组,数组的元素是指针。

D.给出的三项中,p都是指针

31.设有变量定义:int a[5]={5,4,3,2,1}, ∗p=a; 则执行语句 p+=2;后,∗p的结果是3

32.变量的指针是指变量的( 地址)。

33.若有语句“int a[3][4]={{1,3,5,7},{2,4,6,8}};”,则 *(*a+1) 的值为( 3) 。

*a 等价于 a[0],它是一个指向 a[0][0] 的指针。*a + 1 表示将 *a 指针向后移动一个元素的位置,即指向 a[0][1]*(*a + 1) 是对 *a + 1 所指向元素的间接引用,即 a[0][1] 的值。

34.若有语句int a[3][4], *p=&a[0][0]; 则与*(*(a+1)+2)等价的是 ( a[1][2])。

a + 1 表示将 a 指针向下移动一个包含 4 个元素的行,即指向 a[1] 行。*(a + 1) 等价于 a[1],是一个指向 a[1][0] 的指针。*(a + 1) + 2 表示将 *(a + 1) 指针向右移动 2 个元素,即指向 a[1][2]*(*(a + 1) + 2) 是对 *(a + 1) + 2 所指向元素的间接引用,即 a[1][2] 的值。

35.若有语句“int a[3][4];”,则与*(a+1)+2等价的是 (&a[1][2] )。

a + 1:将 a 指针向下移动一个包含 4 个元素的行,即指向 a[1] 行。*(a + 1):等价于 a[1],是一个指向 a[1][0] 的指针。*(a + 1) + 2:将 *(a + 1) 指针向右移动 2 个元素,此时它指向 a[1][2] 的地址。

36.执行语句char a[10]={"abcd"}, *p=a;后,*(p+4)的值是( '\0')。

*p = a; 表示 p 是一个指向 a 数组的指针,初始时 p 指向 a[0]p + 4 表示将指针 p 向后移动 4 个元素位置。*(p + 4) 是对 p + 4 所指向元素的间接引用。

37.若变量已正确定义并且指针p已经指向变量x,则*&x相当于(x )。

在 C 语言中,&x 表示取变量 x 的地址。* 是解引用运算符,用于访问指针所指向的变量。

38.若有定义int a[2][3];则对a数组的第i行第j列元素值的正确引用是( *(*(a+i)+j))

a + i:将 a 指针向下移动 i 个包含 3 个元素的行,即指向 a[i] 行。*(a + i):等价于 a[i],是一个指向 a[i][0] 的指针。*(a + i) + j:将 *(a + i) 指针向右移动 j 个元素,此时它指向 a[i][j] 的地址。*(*(a + i) + j):是对 *(a + i) + j 所指向元素的间接引用,即 a[i][j] 的值。

39.若有定义int (*p)[4]; 则标识符p(是一个指针,它指向一个含有四个整型元素的一维数组 )

40.若有定义int a[4][5];下列语句中(++a )是存在语法错误的。

++a 是错误的,因为 a 是一个数组名,虽然在某些情况下它会被当作指针使用,但它不是一个可以修改的左值。数组名 a 代表数组的首地址,是一个常量指针,不能进行自增操作

41.若有定义int s[4][5],(*ps)[5]=s;则对s数组元素的正确引用是( ps[0][2])。

(*ps)[5] = s; 表示 ps 是一个指针,它指向一个包含 5 个整型元素的数组,并且将 ps 初始化为指向 s 的首行。ps[0] 等价于 *(ps + 0),即 s[0],它是一个指向 s[0][0] 的指针。ps[0][2] 等价于 *(ps[0] + 2),即 *(s[0] + 2),也就是 s[0][2],用于访问 s 数组中第 0 行第 2 列的元素。

42.定义指针函数变量后,将一个函数名赋值该指针变量,要求函数的参数个数、类型一致。

43.char *s="C Language";表示s是一个指向字符串的指针变量,把字符串的首地址赋予s。

44.可以用一个指针变量指向一个函数,然后通过该指针变量调用此函数。

45.对于 int **pp; 这样的二级指针:它是一个指针,专门用于存储一级 int * 类型指针的地址。

二级指针只能指向同类型的一级指针变量。

46.语句int *pa[6];定义了含有6个元素的一维数组pa,每个元素是一个指向整型对象的指针变量。

47.语句int (*pb) [6];定义了一个指针变量pb,它是一个指向数组的指针,指向的是长度为6的int型数组。

48.定义一个指针数组并初始化赋值若干个字符串常量,则指针数组并不存放这些字符串,而仅仅指向各个字符串。

49.在使用结构指针时,->被称为指向运算符。

50.若有以下说明: int w[3][4]={{0,1},{2,4},{5,8}}; int(*p)[4]=w; 则数值为4的表达式是p[1][1]

对于 int(*p)[4]=w;p 是一个指针,它指向一个包含 4 个整型元素的数组,并且 p 被初始化为指向 w 的首行。p[1] 等价于 *(p + 1),它将指针 p 向下移动一行,指向 w[1] 行。p[1][1] 等价于 *(p[1] + 1) 或 *(*(p + 1) + 1),用于访问 w[1][1] 的元素。

51.若有定义int a[2][3];则对a数组的第i行第j列元素地址的正确引用是(a[i]+j)。

52.若有定义int(*p)();标识符p可以( 指向函数的入口地址)

53.若有定义“int k[ 2][3], * pk[ 3];”, 则下列语句中正确的是(pk[0] =&k[1][2];)

54.已知有声明“char a[]="program",*p=a+1;”,则执行以下语句不会输出字符a的是 putchar(*p+4);

对于 char a[] = "program";,这是一个字符数组,存储了字符串 "program"。对于 *p = a + 1;p 是一个指针,它指向 a[1],即字符 'r'*p 表示 p 所指向的字符,即 'r'*p + 4 表示将 'r' 的 ASCII 值加 4。'r' 的 ASCII 值是 114,加 4 后为 118,对应的字符是 'v'

55.如有语句“int x,y=0,z,*p[3]; p[0]=&x; p[1]=&y; p[2]=&z;”,以下表达式中有语法错误的是 p++

p 是一个指针数组,它包含 3 个元素,每个元素是 int * 类型的指针。p 是一个数组名,数组名代表数组的首地址,在 C 语言中,数组名是一个常量指针,它不能被修改。p++ 试图修改 p 的地址,将其向后移动一个位置,但这是不允许的,因为 p 是常量,不允许自增操作。

56.设有如下定义,则对data中的a成员的正确引用是( B)。
struct sk { int a; float b; } data, p = &data;

A.(*p).data.a

p 已经指向 data*p 就是 data,不需要再使用 .data 来访问 data 自身,这是多余的,会导致错误。

B.(*p).a

*p 得到 data(*p).a 就是访问 data 的 a 成员。

C.p->data.a

p 指向 data,使用 p->a 可以访问 data 的 a 成员,不需要 ->data,这样会导致错误。

D.p.data.a

p 是指针,应该使用 -> 而不是 . 来访问其指向结构体的成员。

57.语句int (*pb) [6];定义了一个指针变量pb,它是一个指向数组的指针,指向的是长度为6的int型数组。

58.若有定义char *str[]={“Python”, “SQL”, “JAVA”, “PHP”, “C++”}; 则表达式*str[1] > *str[3]比较的是:字符S和字符P

str[1] 指向字符串 "SQL" 的首字符,即 'S'str[3] 指向字符串 "PHP" 的首字符,即 'P'*str[1] 等价于 str[1][0],即取 "SQL" 的第一个字符 'S'*str[3] 等价于 str[3][0],即取 "PHP" 的第一个字符 'P'。因此,*str[1] > *str[3] 比较的是字符 'S' 和字符 'P' 的大小。

59.

类型类型
                        int arr[4]                 int brr[3][4]
arrint*x;brrint(*x)[4]
首元素的地址相当于第一行的地址,把每一行看做一个元素
arr+1int*x;brr[0]int*x;
相当于第一行的元素地址,也就是一维数组的地址,和arr差不多
arr[0]int x;brr+1int(*x)[4]
brr[0]+1int*x;
brr[0][0]int
brr[0][0]+1int

(二十二)字节数

1.char 类型通常占用 1 个字节的内存空间。数组定义 char a[10]; 占内存10个字节.

2.sizeof(a) 将返回数组 a 所占用的字节数。

3.通常 int 类型占用 4 个字节

4.通常 double 类型占用 8 个字节

5.对于数组定义 char array[] = "hello";,数组 array 所占的空间不是 5,而是6.结尾的 '\0' 字符。

6.short 是一种有符号短整型,通常占用 2 个字节(16 位)。当给 short 类型变量赋值时,会发生截断操作。short bi = 0x12345678L; 尝试将一个长整型(L 后缀表示长整型)的值赋给 short 类型的变量 bi。由于 short 类型只占 2 个字节,会将 0x12345678 的低 16 位存储在 bi 中。因此,bi 的值实际上是 0x5678,因为 0x12345678 的低 16 位是 0x5678

7.短整型(short):通常占 2 个字节(16 位)

8.长整型(long):通常占 4 个字节(32 位)

9.可存储范围一般是-2^(n-1)到2^(n-1)-1,n为数据类型所占的位数。一个字节等于八位。

10.单精度实数 float 类型的变量占用 ▁▁4▁▁▁ 字节内存空间。

11.若表达式sizeof(int)的值为2,则int类型数据可以表示的最大整数为()。

因为字节数是2,一个字节占八位,2*8=16,所以是2的15次方-1. 

12.字符串 "ABCD" 长度为4个字符,占用内存 5个字节,这些字节的值依次是65,66,67,68,0。

13.对于定义 char str[] = "abc\000def\n"(注:其中0为数字零),求字符串str的长度len和数组str的大小size,len和size分别是:3 ,9

字符串长度是指从字符串的第一个字符开始,到第一个 '\0'(字符串结束标志)的字符个数,不包括 '\0'strlen 函数计算字符串的长度。对于 str[] = "abc\000def\n";,字符串遇到 \000 就认为结束了,因为 \000 是 '\0' 的八进制表示,所以字符串长度 len 是 3。

数组大小是指整个数组所占用的字节数,包括存储的所有字符和字符串结束符 '\0'sizeof 操作符计算数组的大小。对于 str[] = "abc\000def\n";,字符串 "abc\000def\n" 包含 8 个可见字符,再加上一个字符串结束符 '\0',所以数组大小 size 是 9。

14.设char cs[20]="\ta\017bc";则函数strlen(cs)的返回值为(5 )

15.设有数组定义:char carray[]="hello";则数组carray所占的空间为( 6个字节)

16.int arr[10].&arr与&arr+1相差40个字节。

(二十三)宏名

1.宏名并不必须用大写字母表示。

2.宏是通过 #define 预处理指令来定义的,它可以用来定义常量、函数式宏或条件编译等。

3.宏的名称可以由字母、数字和下划线组成,且首字符不能是数字。

4.已知如下定义:

#define s(a) a*a

则s(2+3)的值为11

以宏定义#define SQUARE(x) (x * x)为例,当代码中有SQUARE(3 + 2)时,预处理器会将x替换为3 + 2,得到(3 + 2 * 3 + 2)。这里需要注意运算顺序问题,按照运算符优先级,结果可能不是预期的(3 + 2)*(3 + 2)

(二十四)链表+文件

1.用链表代替数组进行数据操作时,查询并不会更加方便。

2.C系统的标准输出文件stdout是指显示器。

3.当以 "a" 模式打开文件时,文件指针指向文件的末尾

4.一般不能用任何一个文本编辑器打开二进制文件进行阅读。

5.当fopen函数打开文件失败时,返回给文件指针的值是NULL。

6.文件的扩展名只是文件名的一部分,不会影响文件的存储和读取方式。

7.二进制文件读写函数 fread 和 fwrite 的操作主要依赖于文件的打开模式("rb" 或 "wb")和文件指针的状态,而不是文件的扩展名。可以使用任何扩展名保存二进制文件,文件扩展名主要是为了方便用户和程序识别文件,不会影响二进制文件的读写操作。

8.头文件的扩展名通常是 .h

9.枚举类型中的元素都具有一个整型值

10.调试就是在程序中查找错误并修改错误的过程。

11.设置断点并观察变量,是程序调试的常用方法之一。

12.单步跟踪(Trace Step by Step)是常用的程序调试方法,即一步一步跟踪程序的执行过程,同时观察变量的变化情况。

13.typedef可以简化声明:比如定义typedef unsigned long long* ulp_t;之后unsigned long long* a, b;可以简写成ulp_t a, b;(错)

这声明了 a 是 unsigned long long* 类型,而 b 是 unsigned long long 类型。这将 a 和 b 都声明为 ulp_t 类型,即 unsigned long long* 类型,与 unsigned long long* a, b; 的声明结果不同。

(二十五)结构体

1.结构体类型本身不占用内存空间,结构体变量占用内存空间。

2.结构体中的成员变量可以是数组。

3.在定义结构类型时,关键字struct和它后面的结构名共同组成一个新的数据类型名。

4.结构体变量可以作数组元素。

5.指向结构体变量的指针可以作函数参数,实现传址调用。

6.结构是变量的集合,可以按照对同类型变量的操作方法单独使用其成员变量。

7.C语言中的结构体类型属于一种构造类型

8.一个结构体类型中的各个成员的类型可以不同。

9.在定义结构类型时,关键字struct和它后面的结构名共同组成一个新的数据类型名。

10.在对结构变量操作时,.被称为成员或者分量运算符。

11.结构体成员的类型可以不是基本数据类型。

12.一个结构体类型可以由多个称为成员(或域) 的成分组成

13.结构体类型中的成员可以是C语言中预先定义的基本数据类型,也可以是数组和结构。

14.结构体类型中各个成员的类型可以是不一致的

15.仅仅是定义了一种数据结构,即告诉编译器这个结构体包含哪些成员以及它们的类型,而没有为其分配内存空间。只有当你声明一个结构体变量时,编译器才会为其分配内存空间。

(二十六)逻辑值

1.在 C 语言中,逻辑运算的结果只有两种:"真" 和 "假"。

2.对于逻辑表达式,任何非零值都被视为 "真",而零值被视为 "假"。

3.表达式(x == 0)与表达式(!x)等价。对于布尔值判断,表达式 (x == 0) 检查 x 是否等于 0。表达式 (!x) 使用逻辑非运算符 !,它对 x 的值进行取反操作。当 x 为 0 时,!x 的结果为 1(在 C 语言中,非零值表示 true,零值表示 false)。当 x 不为 0 时,!x 的结果为 0。它们都用于判断 x 是否为 0,只是 (x == 0) 是直接比较,而 (!x) 是通过逻辑非运算符来实现判断。

4.表达式 (3==x==3) 的值恒为0。首先计算 3 == x,其结果是一个布尔值(在 C 语言中,0 表示 false1 表示 true)。然后将这个结果与 3 进行 == 比较。

5.表达式(a^a)的值恒为0(对)因为对于 a 的每一位,与自身进行异或操作,相同位异或结果必然为 0。

6.如果要求在if后一对括号中的表达式在表示a 不等于 0 的时候的值为“真”,则能正确表示这一关系的表达式为a.因为当 a 不为 0 时,它的值为非零,在 if 语句中会被视为 true

(二十七)不同进制

1..C语言中以 %x 开头的数不是十六进制整数。(%x是格式化说明符,并不是数字的开头)

2.八进制整数是以数字 0 开头的数字序列,且数字序列中的数字只能是 0 到 7。例如 012 表示十进制的 10。

3.十六进制数使用 0x 或 0X 作为前缀,由数字 0-9 和字母 A-F(或 a-f)组成,其中 A-F 分别表示 10-15。十六进制数0x11的十进制数是17。例如 0xe 表示十进制的 140xFF 表示十进制的 255

(二十八)递归

1.递归调用算法与相同功能的非递归算法相比,主要问题在于重复计算太多,而且调用本身需要分配额外的空间、传递数据和控制,所以时间和空间开销通常都比较大。

2.递归的执行速度并不快,但递归代码比较紧凑,并且比相应的非递归代码更易于编写与理解。

3.在调用一个函数的过程中又出现直接或间接地调用该函数本身,这称为函数的递归调用。

4.递归函数的两个要素是边界条件、递归方程

--------------------------------------------------------------------------------------

(一)判断闰年的条件。

year能被4整除但是不能被100整除,或者,能被100整除且能被400整除(能被400整除就一定能被100整除)

1.编写一个函数 isLeapYear,该函数接收一个整数 year 作为参数,判断该年份是否为闰年。如果是闰年返回 1,否则返回 0。

int leapyear(int year)
{
	if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
		return 1;
	else
		return 0;
}

2.编写一个程序,计算从 startYear 到 endYear(包括 startYear 和 endYear)范围内的闰年数量。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int leapyear(int year)
{
	if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
		return 1;
	else
		return 0;
}
int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	int count = 0;
	for (int i = a; i <= b; i++)
	{
		if (leapyear(i) == 1)
		{
			printf("%d  ", i);
			count++;
		}
	}
	if (count == 0)
		printf("没有闰年");
	else
		printf("\n共有%d个闰年", count);
	return 0;
}

4.计算某一日是某一年中的第几天

#include<stdio.h>
struct date
{
	int year;
	int month;
	int day;
};
int leapyear(int y)
{
	if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
		return 1;
	else
		return 0;
}
int main()
{
	struct date a;
	scanf("%d %d %d", &a.year, &a.month, &a.day);
	int monday[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
	if (leapyear(a.year) == 1)
		monday[1] = 29;
	int d = 0;
	for (int i = 0; i < a.month-1; i++)
	{
		d += monday[i];
	}
	d += a.day;
	printf("%d", d);
	return 0;
}

(二)一维的比较

1.输出a,b,c中的最大值:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	int a, b, c;
	scanf("%d %d %d", &a, &b, &c);
	if (a < b)
	{
		int d = a;
		a = b;
		b = d;
	}
	if (b < c)
	{
		int e = b;
		b = c;
		c = e;
	}
	if (a < b)
	{
		int p = a;
		a = b;
		b = p;
	}
	printf("最大值:%d", a);
	return 0;
}

2.求两个整数中的较大者

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	if (a >b)
		printf("最大值:%d", a);
	else
		printf("最大值:%d", b);
	return 0;
}

3.将a,b,c,按从大到小顺序输出:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	int a, b, c;
	scanf("%d %d %d", &a, &b, &c);
	if (a < b)
	{
		int d = a;
		a = b;
		b = d;
	}
	if (b < c)
	{
		int e = b;
		b = c;
		c = e;
	}
	if (a < b)
	{
		int p = a;
		a = b;
		b = p;
	}
	printf("排序后:%d>%d>%d", a,b,c);
	return 0;
}

(三)排序的基本结构

1.冒泡排序

#include<stdio.h>
int main()
{
	int arr[10];
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", &arr[i]);
	}
	for (int i = 0; i < 10 - 1; i++)/*循环的轮数*/
		/*切记有几个数,那么循环轮数就是几-1*/
	{
		for (int j = 0; j < 10 - 1 - i; j++)/*每一轮循环都是从第一个数开始,与后一个数两两比较*/
			/*第一轮结束,最大的那个数已经在最后边了,下一次就是从第一个数两两比较一直到倒数第二个数,所以是10-1-i*/
		{
			if (arr[j] > arr[j + 1])/*改题目运用的是从小到大排序,所以把最大的那个往后放*/
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%4d", arr[i]);
	}
	return 0;
}

2.选择排序

#include<stdio.h>
int main()
{
	int arr[10];
	int min = 0;
	for (int i = 0; i < 10; i++)
	{
		scanf("%d", &arr[i]);
	}
	for (int i = 0; i <10-1; i++)/*循环的轮数*/
		/*思路为:第一轮:十个数里面先找到最小的那一个,把最小的放在最前面*/
		/*第二轮:在剩下的九个数里面找到最小的那一个,把最小的放在这九个数的最前面,也就是所有数的第二个*/
		/*第三轮是8个数比较,第四轮7,5.6.6.5.7.4.8.3.9.2,所以一共需要九轮*/
	{
		min = i;/*每一轮中先设定此轮的比较数内第一个为最小值*/
		for (int j = i + 1; j < 10; j++)/*所以从第二个数往后历遍所有数并依次与比较min比较*/
		{
			if (arr[min] > arr[j])
			{
				min = j;
			}
		}
	   int temp = arr[min];/*把一开始设定的最小值与比较完之后的最小值交换*/
	   arr[min] = arr[i];
	   arr[i] = temp;
			
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%4d", arr[i]);
	}
	return 0;
}

(四)1-1/2+1/3-1/4+...+1/99-1/100。

#include<stdio.h>
int main()
{
	int sign=1;
	double sum=0.0;
	for (int deno = 1; deno <= 100; deno++)
	{
		sum += sign*1.0 / deno;
		sign=-sign;
	}
	printf("%lf", sum);
	return 0;
}

(五)递归求阶乘

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int face(int n)
{
	if (n == 0)
		return 1;
	else if (n == 1)
		return 1;
	else
		return n * face(n - 1);
}
int main()
{
	int n;
	scanf("%d", &n);
	printf("%d", face(n));
	return 0;
}

(六)删除s字符串中的c字符:

#include <stdio.h>
void squeeze(char s[], int c);
int main() {
    char s[100];
    char c;
    int i;

    scanf("%s %c", s, &c);

    squeeze(s, c);
    for (i = 0; s[i] != '\0'; i++)
        putchar(s[i]);
    putchar('\n');
    return 0;
}
void squeeze(char s[], int c)
{
    int i, j;
    c = (char)c;(注意c的类型,一定要变成char型)
    for (i = 0, j = 0; s[i] != '\0'; i++)
    {
        if (s[i] != c)
        {
            s[j++] = s[i];
        }
    }
    s[j] = '\0';
}

(七)把两个字符串连在一起:

#include <stdio.h>

void strcat(char s[], char t[]);

/* the length of a string */
int main(){
    char s[100], t[10];
    int i;

    scanf("%s%s", s, t);

    strcat(s, t);
    for (i = 0; s[i] != '\0'; i++)
        putchar(s[i]);
    putchar('\n');

    return 0;
}

/* 请在这里填写答案 */

void strcat(char s[], char t[])
{
    int i=0,j=0;
    while(s[i]!='\0')
    {
        i++;
    }也算是一种算数组长度的方法
    while(t[j]!='\0')一定要判断循环条件
    {
    s[i++]=t[j++];
    }
    s[i]='\0';
}

(八)把大写字母转换成小写字母:

#include <stdio.h>

int lower(int c);

int main()
{
    char c;

    c = getchar();

    printf("%c", lower(c));

    return 0;
}
/* 请在这里填写答案 */

int lower(int c)

{

if (c>='A'&&c<='Z')

c= c+('a'-'A');等号右侧不是’c',若是'c'则输出的左边内容应该是字符码而不是字符or字母。

return c;

}

 (九)素数

1.判断是否为素数

#include<stdio.h>
#include<math.h>
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 2; i <= sqrt(n); i++)
	{
		if (n % i == 0)
		{
			printf("%d 不是素数\n", n);
			return 0;
		}
	}
	printf("%d 是素数\n", n);
	return 0;
}

2.输出指定范围内的素数

#include<stdio.h>
#include<math.h>
int main()
{
	
	int n;
	for (n = 100; n <= 200; n++)
	{
		int s = 1;
		for (int i = 2; i <= sqrt(n); i++)
		{
			if (n % i == 0)
			{
				s =0;
			}
		}
		if (s==1)
		{
			printf("%d  ", n);
		}
	}
	return 0;
}
#include<stdio.h>
#include<math.h>
int main()
{
    int a, b;
    int i = 0;
    scanf("%d %d", &a, &b);
    int first = 1;
    for (i = a; i <= b; i++) {
        int s = 1;
        for (int j = 2; j <= sqrt(i); j++) {
            if (i % j == 0) {
                s = 0;
                break; 
            }
        }
        if (s == 1) {
            if (!first) {
                printf(",");
            }
            printf("%d", i);
            first = 0;
        }
    }
    printf("\n");
    return 0;
}

#include<stdio.h>
#include<math.h>
int sushu(int n)
{
	int a=1;/*n=1是素数*/
	for (int i = 2; i <= sqrt(n); i++)
	{
		if (n % i == 0)
			a = 0;/*如果存在一个i能被n整除,那么n就不是素数*/
	}
	return a;
}
int main()
{
	int n;
	scanf("%d", &n);
	int m = sushu(n);
	if (m == 1)
		printf("%d是素数\n", n);
	else
		printf("%d不是素数\n", n);
	return 0;
}

(十)斐波那契数列

#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{
	int f1 = 1, f2 = 1;
	printf("%d\n%d\n", f1, f2);
	int f3;
	for (int i = 0; i < 10; i++)
	{
		f3 = f1 + f2;
		printf("%d\n", f3);
		f1 = f2;
		f2 = f3;
	}
	return 0;
}

(十一)两个正整数的最大公约数和最小公倍数

最小公倍数的实现方式:用两数的乘积除以最大公约数

#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{
	int m, n;
	int a,b;
	int i;
	int j = 1;
	scanf("%d %d", &m, &n);
	if (m > n)
	{
		a = m;
	}
	else
	{
		a = n;
	}
	if (m > 0 && n > 0)
	{
		for (i = 1; i <= a; i++)
		{
			if (m % i == 0 && n % i == 0)
			{
				b = i;
			}
		}
		printf("%d\n", b);
		printf("%d", m * n / b);
	}
	return 0;
}

(十二)汉诺塔

#include<stdio.h>
#include<string.h>
#include<math.h>
void hanoi(int n, char a, char b, char c)
{
	if (n == 1)
		printf("%c->%c\n", a, c);
	else
	{
		hanoi(n - 1, a, c, b);
		printf("%c->%c\n", a, c);
		hanoi(n - 1, b, a, c);
	}
}
int main()
{
	int n;
	char a;
	char b;
	char c;
	scanf("%d", &n);
	hanoi(n,'a','b', 'c');/*注意单引号*/
	return 0;
}

(十三)反序问题

1.字符串反序

#include<stdio.h>
#include<math.h>
void fanxu(int arr[],int n)
{
	for (int i = 0; i <= n / 2 - 1; i++)
	{
		int temp;
	    temp=arr[i];
		arr[i] = arr[n - 1 - i];
		arr[n - 1 - i] = temp;
	}
	
}
int main()
{
	int arr[] = { 0,1,2,3 ,4};
	fanxu(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d", arr[i]);
	}
	return 0;
}

2.数组反序

int main()
{
	int arr[10] = { 1,3,5,7,9,11,13,15,17,19 };
	int* p = &arr[9];
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *p);
		p--;
	}
	return 0;
}

3.整数反序

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	int number;
	scanf("%d", &number);
	int a = 0;
	while (number > 10)
	{
		a = a * 10 + number % 10;
		number /= 10;
	}
	a = a * 10 + number;
	printf("%d", a);
	return 0;
}

(十四)把数组右移几位

#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{
	int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int m;
	scanf("%d", &m);
	for (int i = 0; i < m; i++)
	{
		int temp = a[9];
		for (int j = 9; j>0; j--)
		{
			a[j] = a[j - 1];
		}
		a[0] = temp;
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%2d", a[i]);
	}
	return 0;
}

(十五)用结构写学生的成绩并排序,包括名字,学号,两个以上的学科

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
struct student
{
	char name[20];
	int a;
	int b;
};
int main()
{
	struct student arr[3];
	for (int i = 0; i < 3; i++)
	{
		scanf("%s %d %d", &arr[i].name, &arr[i].a, &arr[i].b);
	}
	for (int i = 0; i < 3 - 1; i++)
	{
		int max = i;
		for (int j = i + 1; j < 3; j++)
		{
			if (arr[max].a < arr[j].a)
				max = j;
		}
		struct student temp;
		temp = arr[max];
		arr[max] = arr[i];
		arr[i] = temp;
	}
	for (int i = 0; i < 3; i++)
	{
		printf("%s %d %d\n", arr[i].name, arr[i].a, arr[i].b);
	}
	return 0;
}

(十六)打印乘法口诀表

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			printf("%dX%d=%d\t", i, j, i * j);
		}
		printf("\n");
	}
	return 0;
}

(十七)计算数字的每位数字之和

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main()
{
	int number;
	scanf("%d", &number);
	int a = 0;
	while (number > 10)
	{
		a += number % 10;
		number /= 10;
	}
	a += number;
	printf("%d", a);
	return 0;
}

;