跳转至

C 程序设计基础

4122 个字 117 行代码 预计阅读时间 18 分钟

常见坑

1. 运算优先级的题: 先回忆优先级,不要想当然

2. 循环的题,慢慢写,搞清楚 for、while,

3. 看清楚分号!!!

4. 记住 x++ 相关的问题

一、C 语言的基本语法单位

1. 合法标识符

英文字母、数字和下划线组成,第一个字符必须是字母或者下划线(字母需要区分大小写)

不能以数字开头!

以下合法的标识符是 A
A) _0
B) a[1]
C) student.name
D) register

2.C 语言 32 个关键字

  • 类型说明保留字 :

int,long,short,float,double,char,unsigned,signed,const,void,volatile,enum,struct,union

  • 语句定义保留字 :

if,else,goto,switch,case,do,while,for,continue,break,return,default,typedef

  • 存储类说明保留字 : auto,register,extern,static

  • 长度运算符保留字 :sizeof

不是C语言提供的合法关键字是 C
    A) switch
    B) char
    C) Case
    D) default

二、数据类型、运算符和表达式(很重要)

1. 常量

  • 整型常量
  • 十进制整数
    • 123、-120
    • %d
  • 八进制整数
    • 0 开头的数字进行表达
    • 0123、-011
    • 八进制不能出现 8
    • %o
  • 十六进制整数
    • 0x 开头的数字进行表达
    • 0x123、-0x11
    • Hh 为结尾
    • %x
  • long L 为结尾
  • unsigned U 为结尾
  • 二进制 Bb 结尾
  • 浮点型常量
  • 十进制小数形式
    • 小数形式是由数字和小数点组成的一种实数表示形式
    • 例如0.123.123123.0.0等都是合法的实型常量 ( 实数、浮点数 )
  • 指数形式
    • C 语言中,则以“e”或“E”后跟一个整数来表示以“10”为底数的幂数。C 语言语法规定,字母 e E 之前必须要有数字,且 e E 后面的指数必须为整数
    • 字母 e E 之前的小数部分中,小数点左边有且只能有一位非零的数字。
    • 常见格式:+1.2E+51.5e-9-5.0e10
  • 浮点数默认为 double
  • 字符型常量
  • 普通字符
    • 单引号括起
    • ASCII 码表示(0~255 整型)
  • 转义字符
    • 注意单引号、双引号、反斜杠的字符表示前都需要加\
    • \0
    • \ddd三位八进制的 ASCII \101='A'
    • \xhh二位十六进制的 ASCII \x41='A'
  • 字符串常量
  • 双引号括起
  • 字符串所占字节数为其中的字符数 +1'\0'字符串结束标志)
  • 不要忘记最后的 0

  • 题型:判断正确表示的常量

    下列正确的转义字符是 ( D ) A.''' B.'97' C.'0xab' D.'\'

    以下正确的字符常量是 ( B ) A.'412' B.255 C.'08' D. ''

    下列实型常数表示形式不正确的是 ( C ) A.327. B.1.48e4 C..5E-10 D.2.1e4

    下面四个选项中,均非浮点数正确表示的选项是 ( D ) A.160. 0.12 e3 B.-.18 123e4 0.0 C.-e3 234 1e3 D.123 2e4.2 .e5

  • 题型:常量所占字节

    sizeof(5.0) 的值为 ( D ) A. 5 B. 4 C. 2 D. 8

    C 语言中,下列表达式的值最大的是 ( D ) A. sizeof('a'); B. sizeof(97); C. sizeof("aaaa"); D. sizeof(97.0);

  • 题型:进制转换

    下列程序段的输出结果是:8=10_____ int i=010,j=16; printf("%d=%xn",i,j);

2. 变量

  • 整型变量
  • int 4 字节
  • short 2 字节
  • long 4 字节
  • 浮点型变量
  • float 4 字节
  • double 8 字节
  • 字符变量
  • char 1 字节
  • C 语言允许对整型变量赋以字符值,也允许对字符变量赋以整型值

image-20221229103520570

static 作用:静态变量的生存周期和作用域 - bigclould - 博客园 (cnblogs.com)

作用域

生命周期:从定义开始分配存储单元到运行结束存储单元被回收的整个过程

存储方式

  • 静态存储方式:指在程序运行期间由系统分配固定的存储空间的方式
  • 动态存储方式:指在程序运行期间根据需要动态地分配存储空间的方式

存储类型

  • C 语言的四种存储类型:
  • 动态存储 auto(自动)
  • 动态存储 register(寄存器)
  • 静态存储 static(静态)
  • 静态存储 extern(外部)

  • 若存储在动态存储区中的变量没有初始化,则变量的值是不确定的,而对于存储在静态存储区中的变量,则系统自动初始化与变量类型相同的 0 初值

  • 凡是在函数外声明的变量(全局变量)储存在静态存储区;凡是在函数内(包括 main 函数)前面没加 static 声明的变量,都储存在动态存储区。
  • 凡是函数中未指定存储类别的局部变量,其隐含的存储类型为auto
/*t1*/
下面说法中正确的是()。
A.若全局变量仅在单个C文件中访问则可以将这个变量修改为静态全局变量以降低模块间的耦合度
B.若全局变量仅由单个函数访问则可以将这个变量改为该函数的静态局部变量以降低模块间的耦合度
C.设计和使用访问动态全局变量静态全局变量静态局部变量的函数时需要考虑变量生命周期问题
D.静态全局变量使用过多可那会导致动态存储区堆栈溢出
//答案
A.B.C都正确这题应该是选错误选项如果选错误选项应该选D
A选项变量分为全局变量和局部变量局部变量和形参的作用域是函数内部全局变量的作用域是整个文件但可以通过声明一个extern的全局变量拓展全局变量的作用域也可以通过定义一个static的全局变量限制这种拓展
B选项如果全局变量仅仅由单个函数访问不存在耦合度的问题
C选项动态全局变量静态全局变量静态局部变量的生命周期都为程序运行期间其中静态局部变量的生存周期虽然为整个源程序但是其作用域仍然与局部变量相同当退出函数是该变量还存在但是不能使用
D选项全局变量和静态变量都是存储在静态存储区所以在递归调用是不会压栈也不会造成堆栈溢出

若全局变量仅在单个C文件中访问则可以将这个变量修改为静态全局变量以降低模块间的耦合度
若全局变量仅由单个函数访问不存在耦合度的问题
动态全局变量静态全局变量静态局部变量的生命周期都是整个程序运行期间跟函数设计没有关系
静态全局变量存储于全局静态数据区  
    
/*T2*/

3. 运算符和表达式(优先级很重要)

image-20221223172815017

image-20221223172846547

image-20221223172912591

规则:单目 > 双目 > 三目

算术运算符 > 自增自减运算 > 关系运算符 > 逻辑运算符 > 赋值运算符 > 条件运算符 > 逗号运算符

注意:单目运算符(从右到左) 三目运算符(从右到左)**

易考点:除法 / 左右有一个实型,结果就是实型(类型自动转换)

  sizeof(4/2.0)的值为( D )
  A. 5
  B. 4
  C. 2
  D. 8

  假设有定义:float x=16/5/2.0,y=16/5.0/2; 则x和y的值分别为 A
  A.1.5 1.6   B.1.6 1.6   C.1.5 1.5   D.1.6 1.5

易考点:取余 (%) 要求为整型,余数正负取决于被除数

小数不能取余

  以下表达式 -16%3 的值是____-1_____

  (优先级)
  表达式 1+4/5+15<7+4%5+(8,10) 的值为____1____

  变量定义如下 double x=2.4,y=3.2;int a=7;
  表达式 x=(int)(x+y)%7/2*a%3 的值为____2___

易考点:赋值语句

赋值运算符的左边必须是一个变量

  若以下选项中的变量已正确定义,则正确的赋值语句是C
  A. x1=11.9%3
  B. 1+2=x2
  C. x3=012
  D. x4=1+2=3

赋值语句的顺序为从右到左

  设 int a=12,则执行完语句a+=a-=a*a后,a的值是
  A.0
  B.264
  C.144
  D.-264
 D
  对于定义:int m=5,y=2;当计算表达式y+=y-=m*=y后,y的值为__-16__

赋值语句的返回值为等号右边的值

  表达式 a+=a-=(b=6)/(a=2) 的值是 -2

  if (a=x) ...(只要x不为0,if语句后的...一定执行)

易考点:自增自减运算(只能用于变量,不能用于常量)

x++: 先参与运算,再进行加 1

以下程序的输出为 -4
    int i=10,j=5,ans;
    ans=++j-i--;
    printf("%d",ans);

易考点:逻辑运算符

逻辑运算符的运算结果只有两种情况,即真假。非 0 视为真,0 值视为假

易错点 : && 只要左边为逻辑 0,右边的表达式将不会计算。同理 || 左边为逻辑 1,右边不计算

​ 记忆几个特殊的 ASCII

  • a -> 97 A -> 65 0 -> 48

    假设 a=2,b='2',s="2", 下列逻辑表达式中值为 1(真)的是 A A.(s[1]>'a')|| ~(a+b) B.(b>a) && (s[2]='0') C.!(s+1 && b-a) D.!a>b && ~(a>b)

    C 程序中,下面(B)不能表示逻辑值“真” A.(a=1,b=2) B.4>>3 C.-0.01 D."false"

    以下程序运行输出值是 2 1 1 int a=1,b=0,c; c=++a || ++b; b=!b; printf("%d %d %d",a,b,c)

    以下程序的输出值是 A static int x,y,z; z += (x=1)||(y=2) printf("%d#%d",y,z) A.0#1 B.2#1 C.2#2 D.z的值不确定

    B
    

    下列语句执行后 n 的值为: n=(4 > 4 - !2) && (2 > 1) || (2 &&6); A)  0  B)  1  C)  6  D)  以上均不对

    下列程序段的输出结果为(A) int a=1,b=2,c=2,t; while (a<b<c) { t=a; a=b; b=t; c–; } printf("%d,%d,%d"a,b,c) A.1,2,0 B.2,1,0 C.1,2,1 D.2,1,1

    假设有定义 :int x=10; 则表达式 0<=x<=9 的值是_1_

    表达式 !!5 的值为1_

易考点:位运算(转换为二进制运算、保证运算位数一致)

( 双目运算符中 ) 算术运算符 > 移位运算符 > 比较 > 等于 > 位运算符

  变量a=1,b='1',c=1.0,d="1",下列运算不能进行的是 C
  A.b/a--     B.~a|!b     C.c^++a     D.d+a-b

  若整型变量x=2,则表达式1<x<<x<4的值为___1___

  若整型变量a=10,b=-6,则表达式a>>8+b的值是__2___

  有short x=064,求-x^x<<2&x为____-36_____

易考点:问号表达式

  int a=1,b=2,c;
  有表达式 c=(a++>--b)?++a:b--; 问c的值是____1___

  假设a=5,b=1,在执行 t=a-b?(b-a?a<<2|b:b<<2|a):a>>b|2之后,t的值为 A 
  A.21    B.11    C.6   D.1

  设有变量定义: int a=3, b=4, c=5;
  则表达式:c>a>b && c||!b < c?2:1的值是:C
  A.0     B.1     C.2    D.语法有错

  若定义 int a=1,b=2,c=3,d=4;那么下列表达式值与 A
  (a>b?c>a?c-3:c-1:b==c?d-a:d-c)相等的是
  A.1   B.2   C.3   D.4

易考点:逗号表达式

表达式 1,表达式 2,……表达式 n

最后一个表达式的值就是该逗号表达式的值

计算顺序是从左到右,然后整个表达式返回的是最右边表达式的值。

如下表达式1先算最内层的括号表达式的最左边的值再把其最右边的值返回并赋值给b, 所以b在此次运算之后变为3之后b+2=5但5只是一个临时值b值还是3),之后15+b=18, 并且这个值由于是最右的表达式会作为整个大括号表达式的返回值即b再一次被赋值为18, 然后现计算b+=18得到36    
    
 b+=b=((b=(2,3),b+2),15+b

易错点:左值右值

(8 条消息 ) 左值和右值 _coolwriter 的博客 -CSDN 博客 _ 什么样的表达式可以做左值

(-i)++;//错误写法,-i不是左值

三、输入输出函数

scanf

printf( 顺序从右到左 )

注意 % 前后的数字限制位宽、小数位数、进制等规则

image-20221223173233886

  以下程序的输出值为 5 3 2
  int i=2;
  printf("%d %d %d",++i,i++,i++);

printf("%d%%")\ 两个百分号才能输出

printf("%5.2lf") 格式化输出样例

printf("%02d") 向左补 0 输出

(int)(f+0.5)实现四舍五入

四、结构

①选择结构 if 、switch

if 语句经典陷阱

  • a=5;b=6
  • if (a>b);a++;b++;
    • a=6 b=7
  • if (a>b){a++;b++;}
    • a=5 b=6
  • if (a>b) a++;b++;
    • a=5 b=7
  • if (a=b) a++;b++;
    • a=7 b=7

if 语句判断真假的几种情况 _ 那朵云好像只狗哦的博客 -CSDN 博客 _if0 是真还是假

switch 语句注意点

    switch ()
    {
        case  常量表达式1:
            语句1;
        case  常量表达式2:
            语句2;
        ...
        case 常量表达式n:
            语句n;
        default:
            语句n+1;
    }
+ switch + switch 后面的表达式可以是数值型也可以是字符型表达式 + 若swtich中表达式的值不是整数则自动取整 + case + case 后面的常量表达式只能是整型常量、字符常量或符号常量组成的表达式,即不能有变量或函数 + 每个常量表达式的值必须互不相同 + case 和 default 后的语句可以是单条语句,也可以是复合语句(在这里的复合语句可以不用大括号括起来) + case 执行语句末尾若没有break;,则执行完该部分后继续执行之后的 case 执行语句 + 多个case语句可以共用一组执行语句 + default + 若结构中含有default,该项可置于 case 之间(即 default 项可以不是结构的最后一项default case 中的语句都将被执行。

②循环结构 for、while、dowhile

1. for 循环:初值、终值、步长

for (表达式1;表达式2;表达式3)  
{
  循环体;
}
- 表达式1:给某些变量赋初值
  • 表达式 2:表明循环的终止条件

  • 表达式 3:用于循环中修改某些变量的值 注意: 表达式 1、2、3 可以全部或部分省略,但是永远不能省略 for(;;)=while(1) 表达式 1、2、3 都可由包含逗号运算符的多个表达式组成 陷阱: 空语句 for(i=0;i<100;i++); 依然是要注意分号

    注意递归调用的输出顺序问题!!

题型:for 循环执行了几次(循环变量最终的值)

  循环 for(i=1,j=6; ++i!=--j; ) s=i+j;  循环语句体将执行 D
  A、 2次    B、 3次    C、 4次    D、 以上均不是

错(一直执行)
  判断: 对于下列for循环语句,循环体一次也不执行 
    int i,k;
    for (i=0,k=-1;k=1;i++,k++)
      printf("***");

2. while 语句和 do-while 语句

while (表达式)
{
  循环体语句;
}
do 
{
  循环体;
}while(表达式);
+ 表达式是循环进行的条件 + 真(逻辑 1)和假(逻辑 0 + while (1)(死循环) 注意:do-while 语句和 while 语句最大的区别是: while 语句可能1次都不执行 而无论是否满足执行循环体的条件,do-while语句至少会执行一次循环体
    设 char a[]="0123456789abc";int i=0,j=0;
    执行下列哪一条语句所得到的结果和其他三项不同  C
    A.for (;i<=j;i++,--j)
    B.for (;i<=j;) a[i++]=a[j--];
    C.while (i++ <=--j) a[i]=a[j]
    D.do {a[i]=a[j];} while (++i<--j)

    设 int i=0,j=9;char s[]="happy new year",*sp=s,*sq=s+9;
    执行下列哪一条语句所得的结果和其他三项不同 C
    A. while (i<=j) s[i++]=s[j--];
    B. for (;i<=j;++i,--j)  s[i]=s[j];
    C. for (;sp++<=sq--;) *sp =*sq;
    D. do {*sp=*sq} while (sp++ <sq--);

3.break 语句

  • 通常用于跳出循环语句或 switch 语句
  • 注意: 跳出的是循环而不是语句 只能跳出一层循环 break语句不能用于循环体和switch之外的任何其他语句

4.continue 语句

  • 用于结束本次循环,即跳过循环体尚未执行的语句,接着进行下一次执行循环的判定
  • 注意: continue语句和break语句的区别是: continue语句只是结束本次循环,而不是终止整个循环 break语句是结束整个循环过程

五、数组

数组的合法定义

数组名:

会返回首元素类型的指针

一维数组

  1. 全部赋初值
  2. 定义时可省略下标
    • int a[]={0,2,4,6,8,10}
  3. 部分赋初值
    • 定义时不可省略下标
    • 系统为前几个元素赋初值,而剩下的数组元素赋初值 0
    • int b[15]={1,3,5,7,9}
  4. 若是静态存储的数组,如果没有初始化,系统自动给所有的数组元素赋 0 static int a[10]

二维数组

  • 按行初始化 —— 每一对花括号对应一行的元素
  • int a[2][3]={{1,2,3},{4,5,6}};
  • 按存放顺序初始化
  • int a[2][3]={1,2,3,4,5,6};
  • 注意:在初始化二维数组时可省略第一维大小,但第二维大小不能省略
  • int a[][3]={1,2,3,4,5,6};
  • int a[2][]={1,2,3,4,5,6}; ×

字符串

  • 给字符串进行操作的时候,注意考虑 ==0== 的位置移动和赋值
  • 字符数组本质还是数组
  • 常见的字符串处理函数
strlen();//遇到/0就停止计算
sizeof();//占据空间 要记住常见类型的大小
strcmp(str1,str2);// 按照字典序
strlen();
strcpy();//destination  source
strncpy(destination,source,length);//get specific subsequence of source
strcat();

#include<ctype.h>
int islower();
int isalpha();//用函数判断是否大小写,如果懒得打字的话
  • strcmp

  • 自左向右逐个字符相比( ASCII 值大小相比较,直到出现不同的字符或遇 '0' 为止。如:

    ​ 1."A"<"B" 2."A"<"AB" 3."Apple"<"Banana" 4."A"<"a" 5."compare"<"computer"

  • 返回值为正数,负数,0 。而确切数值是依赖不同的 C 实现的。

    当两个字符串不相等时,C 标准没有规定返回值会是 1 -1,只规定了正数和负数。

    有些会把两个字符的 ASCII 码之差作为比较结果由函数值返回。

  • 关于 sizeofstrlen 的区别

聊点基础的–sizeof,strlen, 数组 , 字符串在一起能整哪些坑?

NULL,0,'0'“0”,"0" 你真的分得清吗?

  • 字符串的定义方法和常见错误

字符串实际上是使用空字符 \0 结尾的一维字符数组。

char s[15] = "helloworld";//定义时候用字符串赋值
char str[10] ;str[10] = "China";//先定义,再赋值;
char s[15]={'h','e','l','l','o','w','o','r','l','d'};//逐个元素进行赋值,注意有10个元素,第11个元素值为0,即为'\0',所以不需要自己写
char s[15];strcpy(s, "helloworld");//利用strcpy函数
char *a; a="ABCDE";//利用指针和字符串常量
char *a="ABCDE";//原理同上
char s[15];scanf("%s",s);//利用scanf输入,不要加&,遇到空白字符停止,包括空格,制表符,换行符
char s[15];gets(s);//只在换行符停止
//常见错误
char s[5]={"ABCDE"};//长度超了,"ABCDE/0";
char s[5]={'h','e','l','l','o'};//正好填满了数组,没地方放'\0'了
char *n;scanf("%s",n); // 不能用还未分配地址的指针
char *a={"ABCDE"};//不需要加大括号
char s[15]; s="HelloWorld";//不能先定义,再赋值,s是首元素的指针,不能给指针赋上字符串
char str1[10],str2 = "China";str1 = str2;//将一个字符串赋值给另一个字符串,只能使用strcpy函数

六、函数

类型标识符 函数名()

若无类型标识符,默认返回值为int(强制转换)

main & mian

void 不能有返回值

int 可以没有返回值

return 不代表有返回值,可以用return;跳出函数

  • C 语言中,函数的定义顺序是有讲究的:默认情况下,只有后面定义的函数才可以调用前面定义过的函数

  • 如果想把函数的定义写在 main 函数后面,而且 main 函数能正常调用这些函数,那就必须在 main 函数的前面进行函数的声明(声明函数的时候可以省略参数名称)

  • int sum(int, int);

main 函数的 [C 语言中 int main(int argc,char *argv ]) 的两个参数详解 _C 语言 _ 脚本之家 (jb51.net)

#include<stdio.h>
int main(int argc, char *argv[ ])
{
      printf("%d,%s", argc, argv[1]+1);
      return 0;
}

形参和实参

  • 形参只能是变量,在被定义的函数中,必须指定形参的类型。

  • 没有确定的值

  • 形参变量在未出现函数调用时,并不占用内存,只在调用时才占用。调用结束后,将释放内存。
  • 实参可以是常量、变量、表达式、函数 - 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。
  • 开辟内存存储数据

传参

  • 函数调用中发生的数据传送是单向的。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
  • 不是指针类型时候,形参和实参占用的是不同的内存空间,形参将实参的内容复制一份,在该函数运行结束的时候形参被释放,而实参内容不会改变。
  • 参数是指针类型在调用该函数的过程中,传给函数的是实参的地址,在函数体内部使用的也是实参的地址,即使用的就是实参本身。所以在函数体内部可以改变实参的值。

七、指针与地址

  • 指针的自增自减运算(+1 的含义)
  • 函数运用指针进行值传递
  • 指针与数组
  • 指针和字符串
  • 指针和结构体 `
(*p).a	//√
p->a	//√
typedef int * POINT[10];//有10个元素的,类型是int*的指针数组

动态内存分配

  • malloc = memory allocate

void *malloc(unsigned size)

申请成功返回开始指针,不成功返回 NULL

  • void *calloc(unsigned n, unsigned size)

n 个长度为 size 的空间

返回内存起始地址的指针

  • void free(void *ptr)

  • 先要初始化 , 好习惯 int *p = NULL

  • 使用指针操作数组效率更高

struct+ 指针 (*p)注意先打括号

访问结构的成员时使用成员运算符 ".",而通过指针访问结构的成员时,则使用指向运算符 "->"

#1 
函数返回值是指针的不能返回函数内部的局部变量的地址因为函数内部的局部变量在函数运行结束后生存期结束

//可以避免的情况
 - 返回的是函数形参的地址
 - 返回的是形参形参是指针类型
 - 局部变量为static
 - 指向常量的指针
 - 函数中指针动态赋值指向的内存位于堆不free,该内存一直占用

#2 指针数组和数组指针
语句 int *p[5]; 
定义了一个指针数组p用于指向一个有5个元素的数组
//F

八、结构体

  • 结构体指针 (*sp).name=sp->name
  • 嵌套结构体
已知职工记录描述如下下列正确赋值方式是B
struct worker
{
  char name[20];
  char sex;
  struct birth 
  {
    int day;
    int month;
    int year;
  }a;
}w,*p=&w;
A.p->name="Li"
B.p->a.year=2000
C.w.day=25
D.w.birth.month=10;

九、宏定义

本质是一种预处理命令,可以出现在程序中的任何位置,习惯上我们尽可能将预处理指令写在源程序开头,其有效范围是从定义开始到文件结束

  • 行首以 # 标识的控制行都是预处理命令

  • C 语言的预处理主要有三个方面的内容: 1. 宏定义; 2. 文件包含; 3. 条件编译。

include<> 到系统设定的文件夹寻找;而用“”括号括起来的先到当前文件夹寻找,再到系统文件夹寻找

  • 编译分为:预处理、编译、汇编、链接

  • 不带参数的宏定义

  • #define N 100
  • N 为宏名,100 是宏的内容(宏所表示的字符串)
  • 在预处理阶段,对程序中所有出现的“宏名”,预处理器都会用宏定义中的字符串区代换,这称为“宏替换”或“宏展开”。
  • 带参数的宏
  • 除了一般的字符串替换,还要做参数代换
  • 宏替换只作替换,不做计算,不做表达式求解
  • #define S(a,b) a*b area=S(3,2);第一步被换为area=a*b; ,第二步被换为area=3*2;
  • 容易有问题 :
  • #define S® r*r area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b; 正确的宏定义是#define S® ®*®
  • 宏定义的精髓是替换,且要替换得一模一样 因此:
  • 宏定义末尾不加分号
  • 宏名和参数的括号间不能有空格
  • 宏定义可以实现一些函数的功能
  • #define MAX(a,b) (a>b)?a:b 区别:
    • 宏展开使源程序变长,函数调用不会
    • 宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)
  • 有关宏定义的题目,要把宏定义全部展开之后再进行运算!!
  • 宏定义可以出现在函数内部

十、文件

文件操作 (FILE) 与常用文件操作函数——C 语言 - 蓝海人 - 博客园 (cnblogs.com)

分类:文本文件和二进制文件

文件的处理方式

r/w/a/rb/wb/ab

文件处理函数总结

打开关闭
fopen(文件路径,文件使用方式) 打开文件 成功,返回起始地址
失败,返回 NULL
fclose(fp) 关闭文件并刷新缓存区 若成功关闭文件,返回 0
失败,返回 EOF
输入输出
fgetc() 输入一个字符 若读取成功,返回该字符;
若读到文件末尾,返回 EOF
fputc(ch,fp) fp中写入单个字符ch 若写入成功,则返回该字符;
若读到文件末尾,返回 EOF
fgets((char*)str,x,fp) 读取x-1个字或者读到换行 若读取成功,返回指向所读串的指针(该字符串的首地址
出错或已到文件尾,返回一个空指针 NULL
fputs(str,fp) 输出一个字符串 成功返回非负值
若写入错误,返回EOF
fread(str,strlen(str)+1,n,fp) 读入数组元素 返回实际读到的数据块个数
fwrite(str,strlen(str)+1,n,fp) 返回实际写入的数据块个数
fprintf(fp,"格式字符串",变量表) printf 差不多
定位
rewind(fp) rewind= 倒带 fp返回fp所指的文件的开头地址
ftell(fp) 相对于文件首的偏移字节数 成功返回当前值 ( 一开始是 0,每向后移动一次 +1),否则返回-1L
fseek(FILE *fp,"偏移量","起始位置") 用于设置文件指针的位置;
文件的顺序读写、改变文件指针fp的值、文件的随机读写
可选的"起始位置"
SEEK_SET文件开头 0L
SEEK_CUR当前位置 1L
SEEK_END文件末尾 2L
其他
feof(fp) 若文件结束,返回值为 1(真,否则为 0(假)
fflush(fp) 刷新fp的缓冲区 成功返回0,否则返回EOF
1c语言源程序是文本文件目标文件和可执行文件是二进制文件        //答案:T 记忆方法:能不能用文本编辑器打开

2对于缓冲文件系统在进行文件操作时系统自动为每一个文件分配一块文件内存缓冲区内存单元)。
//答案:T

3文件指针指向文件缓冲区中文件数据的存取位置
//答案:F
解析 文件指针实际上是指向一个结构体类型的指针包含有诸如缓冲区的地址在缓冲区中当前存取的字符的位置对文件是还是”、是否出错是否已经遇到文件结束标志等信息

4定义FILE *fp; 则文件指针fp 指向的是()。
        A.文件在磁盘上的读写位置
        B.文件在缓冲区上的读写位置
        C.整个磁盘文件
        D.文件类型结构体
//答案:D

5若读文件还未读到文件末尾 feof()函数的返回值是 )。
A.-1		B.0		C.1		D.非0
//答案:B
解析如果遇到文件结束函数feoffp的值为1否则为0

6以下语句将输出 ()。
    #include <stdio.h>
    printf("%d  %d  %d", NULL, '\0', EOF);
A.0 0 1		 B.0 0 -1
C.NULL EOF	 D.1 0 EOF
//答案:B

7缓冲文件系统的文件缓冲区位于()。
        A.磁盘缓冲区中
        B.磁盘文件中
        C.内存数据区中
        D.程序文件中
//答案:C
    

十一、基础算法

  • 质数判断

O(n) 遍历判断

O(nlogn) 素数筛 / 埃氏筛

  • GCD
int gcd(int x , int y){
	return y ? gcd(y,x%y) : x;
}
  • 排序算法

  • 桶排序

  • 快速排序
  • 归并排序
  • 选择排序

  • 二分算法

注意二分板子的打法,注意 +1 问题

int l = 0 , r = Count -1 , mid = (l+r) / 2;
while(l < r){ 
    mid = (l+r) / 2;
    if(value <= a[mid])     r = mid;
    else                    l = mid + 1;
}