您好,欢迎来到好走旅游网。
搜索
您的当前位置:首页考研复试C语言篇

考研复试C语言篇

来源:好走旅游网

第一章 概述

1.1什么是程序

为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的合集。

1.4C语言的特点

1.6C程序运行机制

  1. 编辑:hello.C 文件就是源代码。
  2. 编译:将hello.c程序翻译成目标文件hello.obj   //在计算机底层执行。
  3. 链接:将目标文件hello.obj+库文件 生成可执行文件  .exe   //在计算机底层执行。
  4. 运行:执行.exe文件得到运行结果。

1.8C程序开发注意事项

1)C程序源文件以“c”为扩展名。
2)C程序的执行入口时main()函数。
3)C语言严格区分大小写。
4)C程序由一条条语句构成,每个语句以“;”结束。

1.9常用的转义字符

\t:一个制表位,实现对齐功能

\n:换行符

\\:\

\":"

\':'

\r:一个回车

//:单行注释文字

/*  */:块注释。多行注释。

第二章  变量

2.1.1 变量是程序的基本组成单位

2.2 变量的介绍

2.2.1 概念

变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值)。

2.2.2 变量使用的基本步骤

声明变量:int num;   

赋值:num = 60;

使用:printf("num = %d",num);

一步到位:int num2 = 99;

2.4 变量使用注意事项

  1. 变量表示内存中的一个存储区域(不同的数据类型占用的空间大小不一样)
  2. 该区域有自己的名称和类型
  3. 变量必须先声明后使用
  4. 该区域的数据可以在同一类型范围内不断变化
  5. 变量在同一作用域内不能重名
  6. 变量三要素(变量名  值  数据类型)

2.5 变量的数据类型

基本类型:数值类型:整型(短整型short2、整型int2、长整型long4)、浮点型(单精度float4、双精度double8)、字符型char1

构造类型:数组、结构体struct、共用体union、枚举类型enum

指针类型

空类型void

  • 浮点型常量默认为double型,声明float型常量时,需要加’f’或’F’。
  • printf(“d1=%f”,d1);//在输出时,默认保留小数点6为。

2.12 指针入门

2.13 值传递和地址传递

2.13.1 C语言传递参数(或者赋值)可以是值传递(pass by value),也可以传递指针(a pointer passed by value),传递指针也叫地址传递

1)默认传递值的类型:基本数据类型(整型类型、小数类型,字符类型),结构体,共用体。

值传递:将变量指向的存储内容,在传递赋值时,拷贝一份给接收变量。

第三章  常量

1)常量是固定值,在期间不能改变。这些固定的值,又叫做字面量。
2)常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值,也有枚举常量。
3)常量的值在定义后不能进行修改。

整数、浮点、字符、字符串常量

3.3.1 定义常量的方式

1)使用#define预处理器,#define 常量名 常量值
2)使用const关键字,const 数据类型 常量名=常量值;//即就是一个语句

3.6 const和#define的区别

1)const定义的常量时,带类型,define不带类型
2)const是在编译、运行的时候起作用,而define是在编译的预处理阶段起作用
3)define只是简单的替换,没有类型检查。简单的字符串替换会导致边界效应
4)const常量可以进行调试的,define是不能进行调试的,主要是预编译阶段就已经替换掉了,调试的时候就没它了
5)const 不能重定义,不可以定义两个一样的,而define通过undef取消某个符号的定义,再重新定义
6)define可以配合#ifdef、#ifindef、 #endif来使用,可以让代码更加灵活,比如我们可以通过#define 来启动或者关闭调试信息

第四章  运算符

4.1算术运算符

+-*/%

%:7%5=2;a%b=a-a/b*b

4.2 关系运算符(比较运算符)

==、!=、>、<、<=、>=

1)关系运算符的结果要么是真(非0表示),要么是假(0表示)
2)关系表达式经常用在if结构的条件中或循环结构的条件中

4.3 逻辑运算符

与&&、或||、非!

用于连接多个条件(一般来讲就是关系表达式),最终的结果要么是真(非0表示),要么是假(0表示)

4.4 赋值运算符

=、+=、-=、*=、/=、%=、<<=、>>=、&&=、|=

运算顺序从右往左。

4.5 位运算符

作用于位,并逐位执行操作。

4.6 三元运算符

条件表达式?表达式1:表达式2;

条件表达式为非0(真),运算后的结果是表达式1;

条件表达式为0(假),运算后的结果是表达式2;

4.7 运算符优先级

4.8 标识符的命名规则和规范

4.8.1 标识符概念

1)C语言对各种变量、函数等命名时使用的字符序列称为标识符
2)凡是自己可以起名字的地方都叫标识符

4.8.2 标识符的命名规则

  1. 由26 个英文字母大小写,0-9 ,或 $ 组成
  2. 数字不可以开头
  3. 不可以使用关键字和保留字,但能包含关键字和保留字。
  4. C 语言中严格区分大小写,长度无限制。
  5. 标识符不能包含空格

4.8.3 标识符命名规范

  1. 程序中不得出现仅靠大小写区分的相似的标识符int x,X: 变量x 与X 容易混淆
  2. 所有宏定义、枚举常数、常量(只读变量)全用大写字母命名,用下划线分隔单词.比如: const double TAX_RATE = 0.08,//TAX_RATE 只读变量#define FILE_PATH"/usr/tmp"
  3. 定义变量别忘了初始化。定义变量时编译器并不一定清空了这块内存,它的值可能是无效的数据、运行程序,会异常退出
  4. 变量名、函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写: xxxYyyZ7z [驼峰法,小驼峰,比如 short stuAge = 20;]比如:tankShotGamc   大驼峰[TankShotGame]

4.9 关键字

关键字中所有字母都为小写。

4.10 键盘输入语句

4.10.2 步骤

1)include <stdio.h>
2)使用scanf函数
3)使用适当的格式参数接收输入

第五章  二进制和位运算

二进制

十进制

八进制:以数字0开头表示。

十六进制:以0X或0x开头表示。

5.2 进制的转换

5.3 二、八、十六进制转换成十进制示例

5.6 十进制转换成二、八、十六进制

5.9 二进制转换成八、十六进制

5.11 八、十六进制转换成二进制

5.13 原码、反码、补码

  1. 二进制的最高位是符号位:0表示正数,1表示负数
  2. 正数的原码反码补码都一样
  3. 负数的反码=它的原码符号位不变,其他位取反(0—>1,1—>0)
  4. 负数的补码=它的反码+1
  5. 0的反码、补码都是0
  6. 在计算机运算的时候,都是以补码的方式来运算的。

5.14 位运算符

5.14.1 C中位运算符介绍

第六章   程序流程控制

1)
2)分支控制
3)

6.2 顺序控制

程序从上到下逐行执行,中间没有任何判断和跳转。

6.3 分支控制if-else

1)单分支
2)双分支
3)多分支

6.3.2 单分支

if(条件表达式){

执行代码块;

}

6.3.3 双分支

if(条件表达式){

执行代码块1;

}else{

执行代码块2;

}

6.3.4 多分支

if(条件表达式1){

执行代码块1;

}else  if(条件表达式2){

执行代码块2;

}

.......

else{

执行代码块n;

}

6.4 嵌套分支

在一个分支结构中又完整的嵌套了另一个分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。嵌套分支不适合过多,最多不要超过3层。

if(条件表达式){

        if(条件表达式){//被包含的可以是单分支、双分支、多分支

}

}else{

执行代码块2;

}

6.5 switch分支结构

6.6 for循环控制

6.7 while循环控制

6.8 do…while循环控制

6.9 多重循环控制

6.10 跳转控制语句-break

break语句用于终止某个语句块的执行,一般使用在switch或者循环[三大循环]中。

6.11 跳转控制语句-continue

continue语句用于结束本次循环,继续执行下一次循环。

6.12 跳转控制语句-goto

6.13 跳转控制语句-return

return使用在函数,表示跳出所在的函数,在讲解函数的时候会详细的介绍,这里我们简单的提一下。

第七章   枚举

7.2 基本介绍

1)枚举是C语言中的一种构造,它可以让数据更加简洁,更易读,对于只有几个有限的特定数据,可以使用枚举
2)枚举对应英文(enumeration,简写enum)
3)枚举是一组常量的集合,包含一组有限的特定的数据
4)枚举语法定义格式为

enum 枚举名 {枚举元素1,枚举元素2,.....}

enum DAY{ NON=1,TUE=2,WED=3,THU=4,FRI=5,SAT=6,SUN=7 };

7.5 switch使用枚举

#include <stdio.h>
#include <stdbool.h>

enum SEASONS{
    SPRING=1,SUMMER,AUTUMN,WINTER
} season;

void main(){
    printf("请输入你喜欢的季节:(1.spring,2.summer,3.autumn,4.winter):");
    scanf("%d",&season);
    switch (season) {
        case SPRING:
            printf("春天");
            break;

        case SUMMER:
            printf("夏天");
            break;

        case AUTUMN:
            printf("秋天");
            break;

        case WINTER:
            printf("冬天");
            break;

        default:
            printf("没有");        
    }  
    getchar();
    getchar();
}

7.6 枚举类型使用注意事项和细节

1)第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。例如:第一个枚举成员的值定义为1,第二个就是为2,以此类推。

2)在定义枚举类型时改变枚举元素的值

enum DAY{
    MON,TUE,WED,THU=9,FRI,SAT,SUN//如果没有给赋值,就会按照顺序赋值
}day;//表示定义了一个枚举类型enum Day,同时定义了一个变量day(类型是enum DAY)
//说明 FRI,SAT,SUN 就是10,11,12

3)枚举变量的定义的形式1–先定义枚举类型,在定义枚举变量

enum SEASONS{
    SPRING=1,SUMMER,AUTUMN,WINTER
};
enum SEASONS season;

4)枚举变量的定义的形式2-定义枚举类型的同时定义枚举变量

enum SEASONS{
    SPRING=1,SUMMER,AUTUMN,WINTER
}season;

5)枚举变量的定义的形式3-省略枚举名称,直接定义枚举变量

enum{
    SPRING=1,SUMMER,AUTUMN,WINTER
}season;//这样使用枚举,该枚举类型只能使用一次

6)可以将整数转换为对应的枚举值
不能直接将一个整数,赋给枚举变量,但是可以将整数,转成枚举类型,再赋给枚举变量.

#include <stdio.h>
#include <stdbool.h>

void main(){
    enum SEASONS{
        SPRING=1,SUMMER,AUTUMN,WINTER
    }season;

    int n=4;
    season=(enum SEASONS)n;
    printf("season=:%d",season);
    getchar();
}

第八章   函数

为完成某一功能的程序指令(语句)的集合,称为函数。在C语言中,函数分为:自定义函数、系统函数.

8.3 函数的定义

8.3.1 基本语法

返回类型  函数名(形参列表){

执行语句...;//函数体

return 返回值; //可选

}

1)形参列表:表示函数的输入
2)函数中的语句:表示为了实现某一功能代码块
3)函数可以有返回值,也可以没有,如果没有返回值,返回类型声明为 void 。

8.4 头文件

1)头文件是扩展名为.h的文件,包含了C函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和C标准库自带的头文件

2)在程序中要使用头文件,需要使用C预处理指令#include来引用它。前面我们已经看过 stdio.h头文件,它是C标准库自带的头文件

3)#include叫做文件包含命令,用来引入对应的头文件(.h文件)。#include也是C语言预处理命令的一种。#include的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。但是我们不会直接在源文件中复制头文件的内容,因为这么做很容易出错,特别在程序是由多个源文件组成的时候。

4)建议把所有的常量、宏、系统全局变量和函数原型写在头文件中,在需要的时候随时引用这些头文件

1)引用头文件相当于复制头文件的内容
2)源文件的名字可以不和头文件一样,但是为了好管理,一般头文件名和源文件名一样
3)C语言中include <>与include ""的区别

8.7 函数-调用机制

4)函数调用规则
1、当调用(执行)一个函数时,就会开辟一个独立的空间(栈)
2、每个栈空间是相互独立
3、当函数执行完毕后,会返回到调用函数位置,继续执行
4、如果函数有返回值,则,将返回值赋给接收的变量
5、当一个函数返回后,该函数对应的栈空间也就销毁

8.8 函数-递归调用

8.8.1 基本介绍

一个函数在函数体内又调用了本身,我们称为递归调用

8.8.3 函数递归需要遵守的重要原则:
1)执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)
2)函数的局部变量是独立的,不会相互影响
3)递归必须向退出递归的条件逼近,否则就是无限递归,死龟了:)
4)当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁

8.9 函数注意事项和细节讨论

8.10 函数参数的传递方式

8.11 变量作用域

8.11.1 基本说明

所谓变量作用域(Scope),就是指变量的有效范围
1)函数内部声明/定义的局部变量,作用域仅限于函数内部

2)函数的参数,形式参数,被当做该函数内的局部变量,如果与全局变量同名它们会优先使用局部变量(编译器使用就近原则)

3)在一个代码块,比如for / if中的局部变量,那么这个变量的的作用域就在该代码块

4)在所有函数外部定义的变量叫全局变量,作用域在整个程序有效

8.11.2 初始化局部变量和全局变量

1)局部变量,系统不会对其默认初始化,必须对局部变量初始化后才能使用,否则,程序运行后可能会异常退出.
2)全局变量,系统会自动对其初始化,如下所示

8.11.3 作用域的注意事项和细节

1)全局变量(Global Variable)保存在内存的全局存储区中,占用静态的存储单元,它的作用域默认是整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件)。

2)局部变量(Local Variable)保存在栈中,函数被调用时才动态地为变量分配存储单元,它的作用域仅限于函数内部。【内存布局分析】
3)C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量
4)在同一个作用域,变量名不能重复,在不同的作用域,变量名可以重复,使用时编译器采用就近原则.
5)由{}包围的代码块也拥有独立的作用域

8.12 static关键字

8.12.1 基本介绍
static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护。

8.12.2 局部变量使用static修饰
1)局部变量被static修饰后,我们称为静态局部变量
2)对应静态局部变量在声明时未赋初值,编译器也会把它初始化为0
3)静态局部变量存储于进程的静态存储区(全局性质),只会被初始一次,即使函数返回,它的值也会保持不变

8.12.3 全局变量使用static修饰
1)普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量),静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响
2)定义不需要与其他文件共享的全局变量时,加上 static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用

8.12.4 函数使用static修饰
1)函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数
2)非静态函数可以在另一个文件中通过extern引用
3)静态函数只能在声明它的文件中可见,其他文件不能引用该函数
4)不同的文件可以使用相同名字的静态函数,互不影响

8.13 字符串中常用的系统函数

头文件<string.h>

1)得到字符串的长度 size_strlen(const char *str)计算字符串 t 的长度,直到空结束字符,但不包括空结束字符
2) 拷贝字符串char *strcpy(char *dest, const char *src)把 src 所指向的字符串复制到 dest。
3) 连接宁符串char *strcat(char *dest, const char *src)把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。

8.14 时间和日期相关函数

1) 获取当前时间char *ctime(const time t *timer)返回一个表示当地时间的字符串,当地时间是基于参数 timer。
2) 编写一段代码来统计 函数 test 执行的时间double difftime(time t timel, time t time2)
返回 timel 和 time2 之间相差的秒数(timel-time2)

8.15 数学相关函数

mah.h 头文件定义了各种数学函数和一个宏。在这个库中所有可用的功能都带有一个 double 类型的参数,且都返回 double 类型的结果
举例说明:
1) double exp(double x)返回 e 的 x 次幂的值。
2)double log(double x)返回 x 的自然对数(基数为 e 的对数)
3)double pow(double x, double y)返回 x 的 y 次幂。
4)double sqrt(double x)返回 x 的平方根。
4)double fabs(double x)返回 x 的绝对值。

8.16 基本数据类型和字符串类型的转换

8.16.2 sprintf函数的用法

1)sprintf和平时我们常用的 printf函数的功能很相似。sprintf函数打印到字符串中,而printf函数打印输出到屏幕上。sprintf 函数在我们完成其他数据类型转换成字符串类型的操作中应用广泛
2)该函数包含在 stdio.h的头文件中

#include <stdio.h>

int main(){
    char str1[20];
    char str2[20];
    char str3[20];

    int a=20984,b=48090;
    double d=14.309948;

    //说明
    //1.sprintf是一个系统函数,可以将结果存放到字符串中
    //2.格式化的结果,会存放到str1中
    sprintf(str1, "%d %d",a,b);
    sprintf(str2,"%.2f",d);
    //%8.2f含义是格式化后,一共有8位,小数点后占用2位,不够用空格占位
    sprintf(str3,"%8.2f",d);
    printf("str1=%s,str2=%s,str3=%s",str1,str2,str3);
    getchar();
}

8.16.4 字符串类型转基本类型

语法:通过<stdlib.h>的函数调用atoi atof即可

#include <stdio.h>
#include <stdlib.h>

void main(){
    //字符数组
    char str[10]="123456";
    char str2[10]="12.67423";
    char str3[3]="ab";
    char str4[4]="111";

    //说明
    //1. atoi(str)将str转成整数
    int num1=atoi(str);
    short s1=atoi(str4);

    //说明
    //1. atof(str2) 将str2转成小数
    double d=atof(str2);
    //说明
    //1.str3[0] 表示获取到str3这个字符串(数组)的第一个元素 'a'
    char c=str3[0];
    printf("num1=%d d=%f c=%c s1=%d",num1,d,c,s1);
    
    getchar();
}

1)在将char数组类型转成基本数据类型时,要确保能够转成有效的数据,比如 我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数
2)如果格式不正确,会默认转成0 或者0.0

第九章  预处理命令

1)使用库函数之前,应该用#include引入对应的头文件。这种以#号开头的命令称为预处理命令。
2)这些在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理、提前处理)
3)预处理主要是处理以#开头的命令,例如#include<stdio.h>等。预处理命令要放在所有函数之外,而且一般都放在源文件的前面
4)预处理是C语言的一个重要功能,由预处理程序完成。当对一个源文件进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译
5)C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等,合理地使用它们会使编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计

9.3 C语言宏定义

1) #define叫做宏定义命令,它也是C语言预处理命令的一种。所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串

9.3 宏定义的形式

9.3.1 #define 宏名 字符串

1)#表示这是一条预处理命令,所有的预处理命令都以#开头。宏名是标识符的一种,命名规则和变量相同。字符串可以是数字、表达式、if语句、函数等
2)这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符串等同,它不需要双引号
3)程序中反复使用的表达式就可以使用宏定义

#define N 100

#define M (n*n+3*n)

1)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的替换。字符串中可以含任何字符,它可以是常数、表达式、if 语句、函数等,预处理程序对它不作任何检查,如有错误,只能在编译已被宏展开后的源程序时发现。
2)宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换
3)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef 命令

4)代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替

5)宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名,在宏展开时由预处理程序层层代换

#define PI 3.1415926
#define S PI*y*y
printf("%f",S);
//在宏替换后变为:
printf("%f",3.1415926*y*y);

6)习惯上宏名用大写字母表示,以便于与变量区别。但也允许用小写字母
7)可用宏定义表示数据类型,使书写方便

8)宏定义表示数据类型和用 typedef定义数据说明符的区别:宏定义只是简单的字符串替换,由来处理;而typedef 是在编译阶段由编译器处理的,它并不是简单的字符串替换,而给原有的数据类型起一个新的名字,将它作为一种新的数据类型。

9.5 带参数的宏定义

1)C语言允许宏带有参数。在宏定义中的参数称为“形式参数”,在宏调用中的参数称为“实际参数”,这点和函数有些类似
2)对带参数的宏,在展开过程中不仅要进行字符串替换,还要用实参去替换形参
3)带参宏调用的一般形式为:宏名(实参列表);

#include <stdio.h>

//说明
//1.MAX就是带参数的宏
//2.(a,b)就是形参
//3.(a>b) ? a : b是带参数的宏对应字符串,该字符串中可以使用形参
#define MAX(a,b) (a>b)?a:b
int main(){
    int x,y,max;
    printf("input two numbers:");
    scanf("%d %d",&x,&y);

    //说明
    //1.MAX(x, y);调用带参数宏定义
    //2.在宏替换时(预处理,由预处理器),会进行字符串的替换,同时会使用实参,去替换形参
    //3.即MAX(x, y)宏替换后(x>y) ? x : y
    max=MAX(x, y);
    printf("max=%d\n",max);
    getchar();
    getchar();
    return 0;
}

1)带参宏定义中,形参之间可以出现空格,但是宏名和形参列表之间不能有空格出现

2)在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型。而在宏调用中,实参包含了具体的数据,要用它们去替换形参,因此实参必须要指明数据类型
3)在宏定义中,字符串内的形参通常要用括号括起来以避免出错。

#include <stdio.h>
#include <stdlib.h>
#define SQ(y) (y)*(y) //带参宏定义,字符串内的形参通常要用括号括起来以避免出错

int main(){
    int a,sq;
    printf("input a number");
    scanf("%d",&a);
    sq=SQ(a+1);//宏替换 (a+1)*(a+1)
    printf("sq=%d\n",sq);
    system("pause");
    
    return 0;
}

9.6 带参宏定义和函数的区别

1)宏展开仅仅是字符串的替换,不会对表达式进行计算;宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存。
2)函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码

预处理指令是以#号开头的代码行,#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符,整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换

9.7.1 常见的预处理指令

1)预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的,程序员在程序中用预处理命令来调用这些功能。
2)为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。
3)文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。
4)条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。
5)使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计

第十章  数组

数据类型  数组名  【数组大小】;

int  a[5];   赋初值  a[0]=1;a[1]=30;...

10.4.2 数组内存图(重要)

10.4.5 3种初始化数组的方式

10.6 字符数组与字符串


字符数组实际上是一系列字符的集合,也就是字符串(Suing)。在C语言中,没有专门的字符串变量,没有string 类型,通常就用一个字符数组来存放一个字符串
在 C 语言中,字符串实际上是使用 null字符(\0)终止的一维字符数组。因此,一个以 null结尾的字符串,包含了组成字符串的字符。

"\0'是 ASCI 码表中的第0个字符,用 NUL表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在C语言中仅作为字符串的结束标志。

如果在给某个字符数组赋值时,(1)赋给的元素的个数小于该数组的长度,则会自动在后面加"\0,表示字符串结束,(2)赋给的元素的个数等于该数组的长度,则不会自动添加"\0'。

10.7 字符串的表示形式

10.7.1 用字符数组存放一个字符串

10.7.2 用字符指针指向一个字符串

2) printf("%s\n",str);可以输出 str 指向的字符串

10.7.3 使用字符指针变量和字符数组两种方法表示字符串的讨论

3)对字符指针变量,采用下面方法赋值,是可以的

10.8 字符串相关函数

第十一章  多维数组-二维数组

11.1 的使用

11.1.2 使用方式1:先定义在初始化

语法:类型 数组名[大小][大小];
比如:int a[2][3];

    int a[4][6];//没有初始化,则是分配的内存垃圾值

    int i,j;
    //全部初始化为0
    for (i=0;i<4; i++) {
        for(j=0;j<6;j++){
            a[i][j]=0;
        }
    }

11.1.4 使用方式2:直接初始化

1)可以只对部分元素赋值,未赋值的元素自动取“零”值

2)如果对全部元素赋值,那么第一维的长度可以不给出。比如:

第十二章  指针

比如: int *ptr = &num; ptr就是指向 int类型的指针变量,即 ptr是 int*类型。
5)获取指针类型所指向的值,使用: * (取值符号),比如: int * ptr,使用*ptr获取 ptr指向的值

12.3 指针的算术运算

  • 数组在内存中是连续分布的
  • 当对指针进行++时,指针会按照它指向的数据类型字节数大小增加
  • 数组在内存中是连续分布的
  • 当对指针进行–时,指针会按照它指向的数据类型字节数大小减少

12.4 指针的比较

指针可以用关系运算符进行比较,如==、<<=和>>=。如果pl和 p2指向两个变量,比如同一个数组中的不同元素,则可对pl 和 p2进行大小比较,

12.5 指针数组

数据类型 *指针数组名[大小];

1)比如:int *ptr[3];
2)ptr声明为一个指针数组
3)由3个整数指针组成。因此,ptr中的每个元素,都是一个指向int值的指针

12.6 指向指针的指针(多重指针)

1)一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int类型指针的指针:
int **ptr;//ptr的类型是int **
2)当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,比如 **ptr

12.7 传递指针(地址)给函数

传地址或指针给指针变量

#include <stdio.h>
#include <string.h>

void test2(int *p);//函数声明,接受int *
int main(){

    int num=90;
    int *p=&num;
    test2(&num);//传地址
    printf("\nmain()中的num=%d",num);
    test2(p);//传指针
    printf("\nmain()中的num=%d",num);

    getchar();
    return 0;
}

void test2(int *p){
    *p+=1;
}

传数组给指针变量

#include <stdio.h>
#include <string.h>

double getAverage(int *arr,int size);
double getAverage2(int *arr,int size);
int main(){

    int balance[5]={1000,2,3,17,50};
    double avg;
    avg=getAverage(balance, 5);
    printf("Average value is :%f\n",avg);
    avg=getAverage2(balance, 5);
    printf("Average value is :%f\n",avg);

    getchar();
    return 0;
}

double getAverage(int *arr,int size){
    int i,sum=0;
    double avg;
    for(i=0;i<size;++i){
        sum+=arr[i];
        printf("\narr存放的地址=%p",arr);
    }
    avg=(double)sum/size;
    return avg;
}

double getAverage2(int *arr,int size){
    int i,sum=0;
    double avg;
    for(i=0;i<size;++i){
        sum+=*arr;
        printf("\narr存放的地址=%p",arr);
        arr++;//指针的++运算,会对arr存放的地址做修改
    }
    avg=(double)sum/size;
    return avg;
}

如果在getAverage()函数中,通过指针修改了数组的值,那么main函数的balance数组的值是否会相应改变?会的,因为getAverage()函数中的指针,指向的就是main函数的数组。

12.8 返回指针的函数

请编写一个函数strlong(),返回两个字符串中较长的一个

#include <stdio.h>
#include <string.h>

char* strlong(char *str1,char *str2){
    printf("\nstr1的长度%d str2的长度%d",strlen(str1),strlen(str2));
    if(strlen(str1)>=strlen(str2)){
        return str1;
    }else {
        return str2;
    }
}

int main(){

    char str1[30]="abc";
    char str2[30]="dddddd";
    printf("\nLonger string:%s\n",strlong(str1,str2));
    
    getchar();
    return 0;
}

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int* f1(){
    static int arr[10];

    int i=0;
    for(i=0;i<10;i++){
        arr[i]=rand();
    }

    return arr;
}

void main(){
    int *p;
    int i;
    p=f1();//p指向是在f1生成的数组的首地址(即第一个元素的地址)
    for(i=0;i<10;i++){
        printf("\n%d",*(p+i));
    }

    getchar();
}

12.9 函数指针(指向函数的指针)

用函数指针来实现对函数的调用,返回两个整数中的最大值.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int max(int a,int b){
    return a>b?a:b;
}

void main(){
    int x,y,maxVal;

    //说明 函数指针
    //1. 函数指针的名字 pmax
    //2. int 表示 该函数指针指向的函数是返回int类型
    //3. (int,int) 表示 该函数指针指向的函数形参是接受两个int
    //4. 在定义函数指针时,也可以写上形参名 int (*pmax)(int x,int y)=max;
    int (*pmax)(int,int)=max;
    printf("Input two numbers:");
    scanf("%d %d",&x,&y);
    maxVal=(*pmax)(x,y);
    printf("Max value:%d pmax=%p pmax本身的地址=%p\n",maxVal,pmax,&pmax);

    getchar();
}

12.10 回调函数

1)函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数
2)简单的讲:回调函数是由别人的函数执行时调用你传入的函数(通过函数指针完成)

使用回调函数的方式,给一个整型数组 int arr[10]赋10个随机数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//回调函数
//1.int (*f)(void)
//2.f就是函数指针,它可以接收的函数是(返回int,没有形参的函数)
//3.f在这里被initArray调用,充当了回调函数的角色
void initArray(int *array,int arraySize,int (*f)(void)){
    int i;
    for(i=0;i<arraySize;i++){
        array[i]=f();
    }
}

int getNextRandomValue(void){
    return rand();
}

void main(){
    int myarray[10],i;
    initArray(myarray, 10,&getNextRandomValue);
    for(i=0;i<10;i++){
        printf("%d ",myarray[i]);
    }

    getchar();
}

12.11 指针的注意事项和细节

12.12 动态内存分配

12.12.1 C程序中,不同数据在内存中分配说明

1)全局变量--内存中的静态存储区
2)非静态的局部变量--内存中的动态存储区--stack 栈
3) 临时使用的数据…建立动态内存分配区域,需要时随时开辟,不需要时及时释放--heap 堆
4)根据需要向系统中请所需大小的空间,由于未在声明部分定义其为变量或者数组,不能通过变量名或者数组名来引用这些数据,只能通过指针来引用)

12.12.2 内存动态分配的相关函数

12.12.4 动态分配内存的基本原则

第十三章  结构体和共用体

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void main(){
    /*
        张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。
        请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,
        则显示张老太没有这只猫猫。
        
        分析:
        1.猫猫有三个成员(变量)组成
        2.使用结构体解决
    */
    //创建结构体Cat【是数据类型】
    struct Cat{//结构体名Cat, Cat就是我们自己构造的一个数据类型
        char* name;//名字
        int age;//年龄
        char* color;//颜色
    };
    //使用Cat结构体,创建变量
    struct Cat cat1;
    struct Cat cat2;
    //给cat1、cat2的各个成员赋值
    cat1.name="小白";
    cat1.age=3;
    cat1.color="白色";
    cat2.name="小花";
    cat2.age=100;
    cat2.color="花色";
    //输出两只猫的信息
    printf("\n 第1只猫 name=%s age=%d color=%s", cat2.name, cat1.age, cat1.color);
    printf("\n 第2只猫 name=%s age=%d color=%s", cat2.name, cat2.age, cat2.color);

    getchar();
}

13.1.6 结构体和结构体变量的区别和联系

13.1.8 如何声明结构体

13.1.10 创建结构体和结构体变量

13.1.11 成员的获取和赋值

13.2 结构体案例

景区门票案例
1)一个景区根据游人的年龄收取不同价格的门票
2)请编写游人结构体(Visitor),根据年龄段决定能够购买的门票价格并输出
3)规则:年龄>18,门票为20元,其他情况免费
4)可以循环从控制台输入名字和年龄,打印门票收费情况,如果名字输入 n ,则退出程序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Visitor{
    char name[10];
    int age;
    double pay;//应付票价
};
/*
    编写函数处理业务
    说明:因为结构体默认是值传递,会拷贝一份完整数据,效率较低
            因此,为了提高效率,我们直接接收地址(指针)
*/
void ticket(struct Visitor* visitor){
    if(visitor->age>18){
        //(*visitor).pay=20;
        visitor->pay=20;
    }else{
        //(*visitor).pay=0;
        visitor->pay=0;
    }
}
void main(){
    struct Visitor visitor;
    while(1){
        printf("\n 请输入游客名字");
        scanf("%s",visitor.name);
        if(!strcmp("n",visitor.name)){
            break;
        }
        printf("\n 请输入游客年龄");
        scanf("%d",&visitor.age);
        ticket(&visitor);
        printf("\n 该游客应付票价=%.2f",visitor.pay);
    }

}

13.3 共用体

13.3.3 共用体基本介绍

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
    data就是一个共用体(内存布局),包含三个成员,共享数据空间,
    该空间的大小以占用最大的成员为准
*/
union data{
    int n;
    char ch;
    short m;
};

void main(){
    union data a;
    printf("%d,%d\n",sizeof(a),sizeof(union data));
    a.n=0x40;
    printf("%d,%c,%d\n",a.n,a.ch,a.m);
    a.ch='9';
    printf("%d,%c,%d\n",a.n,a.ch,a.m);
    a.m=0x2059;
    printf("%d,%c,%d\n",a.n,a.ch,a.m);
    a.n=0x3E25AD54;
    printf("%d,%c,%d\n",a.n,a.ch,a.m); 

    getchar();

}

13.3.6 共用体内存布局分析

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define TOTAL 2//人员总数

struct Person{
    char name[20];
    int num;//编号
    char sex;//性别 f=>女 m=>男
    char profession;//职员 s=>学生 t=>老师
    union{
        float score;
        char course[20];
    }sc;//sc是一个共用体变量
};

void main(){
    int i;
    struct Person persons[TOTAL];//定义了一个结构体数组
    //输入人员信息
    for (i=0; i<TOTAL; i++) {
        printf("Input info:");
        scanf("%s %d %c %c",persons[i].name,&(persons[i].num),&(persons[i].sex),&(persons[i].profession));
        if(persons[i].profession=='s'){
            printf("请输入该学生成绩:");
            scanf("%f",&persons[i].sc.score);
        }else{
            printf("请输入该老师课程:");
            scanf("%s",persons[i].sc.course);
        }
        fflush(stdin);//刷新
    }
    //输出人员信息
    printf("\nName\t\tNumtSex\tProfession\tScore/Course\n");
    for(i=0; i<TOTAL; i++){
        if(persons[i].profession == 's'){//如果是学生
            printf("%s\t%d\t%c\t%c\t%f\n",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.score);
        }else{//如果是老师
            printf("%s\t%d\t%c\t%c\t%s\n",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.course);
        }
     }
 
    getchar();

}

第14章 文件操作

14.1.1 文件在程序中是以流的形式才操作的

14.1.2 相关函数在stdio.h

C标准库-stdio.h该头文件定义了三个变量类型、一些宏和各种函数来执行输入和输出,在开发过程中,可以来查询

14.2 C输入&输出

1)当我们提到输入时,这意味着要向程序写入一些数据。输入可以是以文件的形式或从命令行中进行。C语言提供了一些列内置的函数来读取给定的输入,并根据需要写入到程序中
2)当我们提到输出时,这意味着要在屏幕、打印机上或任意文件中显示一些数据。C语言提供了一系列内置的函数来输出数据到计算机屏幕上和保存数据到文本本间或二进制文件中

14.3 标准文件

1)C语言把所有的设备都当做文件。所以设备(比如显示器)被处理的方式与文件相同。以下三个文件会在程序执行时自动打开,以便访问键盘和屏幕

2)文件指针是访问文件的方式,我们会讲解如何从屏幕读取值以及如何把结果输出到屏幕上
3)C语言中的I/O(输入/输出)通常使用printf()和scanf()两个函数。scanf()函数用于从标准输入(键盘)读取并格式化,printf()函数发送格式化输出到标准输出(屏幕)
4)案例演示,将内容输出到屏幕

#include <stdio.h>
int main(){
	printf("hello");
	return 0;
}

14.4 getchar()&putchar()函数

1)int getchar(void)函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。您可以在循环内使用这个方法,以便从屏幕上读取多个字符。
2)int putchar(int c)函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间只会输出一个单一的字符。您可以在循环内使用这个方法,以便在屏幕上输出多个字符
3)应用实例:程序会读取一个单一的字符

#include <stdio.h>
int main(){
	int c;
	printf("Enter a value");
	c=getchar();
	
	printf("\n You entered");
	putchar(c);
	printf("\n");
	
	return 0;
}

14.5 gets()&puts()函数

1)char *gets(char *s)函数从stdin读取一行到s所指向的缓冲区,直到一个终止符或EOF
2)int puts(const char *s)函数把字符串s和一个尾随的换行符写入到stdout
3)应用实例:程序读取一整行直到该行结束

#include <stdio.h>
int main(){
	char str[100];
	printif("Enter a value:");
	gets(str);

	printf("\nYou entered");
	puts(str);
	return 0;
}

14.6 scanf()和printf()函数

#include <stdio.h>
int main(){
	char str[100];
	int i;

	printf("Enter a value");
	scanf("%s %d",str,&i);
	printf("\nYou entered:%s %d",str,i);
	printf("\n");
	return 0;
}

14.7 C文件读写

14.8 打开文件

14.9 关闭文件

14.10 写入文件

#include <bits/types/FILE.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void main(){
    
    //创建一个文件指针
    FILE* fp=NULL;
    //打开该文件
    fp=fopen("d:/test/100.txt", "w+");//w+ 模式是 文件会被截断尾零长度
    //fp=fopen("d:/test/100.txt", "a+");//w+ 模式是 文件会被截断尾零长度
    //将内容写入到文件中
    /*
    fprintf(fp, "你好 北京\n");
    fputc("你好,上海\n", fp);*/
    //关闭文件
    fclose(fp);
    printf("创建,写入信息完成");
 
    getchar();

}

14.11 读取文件

#include <bits/types/FILE.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void main(){
    
    //创建一个文件指针
    FILE* fp=NULL;
    //定义一个缓冲区
    char buff[1024];

    //打开文件
    fp=fopen("d:/test200.txt","r");
    //方法1
    //fscanf(fp, "%s",buff);
    //输出
    //printf("%s\n",buff);

    //方法2 读取整个文件
    //说明,循环读取fp指向的文件内容,如果读到NULL,就结束
    while (fgets(buff,1024,fp)!=NULL) {
        printf("%s",buff);
    }

    //关闭文件
    fclose(fp);
 
    getchar();

}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- haog.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务