1章(c语言基础知识)
- c语言的使用标准,第一个标准是c89标准
- c语言的有关键字是32个,9种控制语句以及34种运算符
- c程序文件的扩展名:文件名.c
编译器:其实简单的理解就是就计算机只能进行计算较为简单的二进制,但是人的日常生活中是很难理解这些语言的,为此,有人想到了一种方法,就是在计算机与人类的语言(接近)之间搭建桥梁,这样人类就可以使用容易理解的语言去控制计算机的运行。
gcc编译器:==(GNN complier collection )==可以用来编译c语言,c++、java、Ada、object c、Go等语言
gcc 编译的方法
1.gcc [-optiond]
2.g++ [-optiond]
解释:
- 命令、选项和源文件之间使用空格分隔
- 一行命令中可以有零个、一个或多个选项
- 文件名可以包含文件的绝对路径,也可以使用相对路径
- 如果命令中不包含输出可执行文件的文件名,可执行文件的文件名会自动生成一个默认名,Linux平台为a.out,Windows平台为a.exe
gcc、g++编译常用选项说明:
选项 | 含义 |
---|
-o file | 指定生成的输出文件名为file | -E | 只进行预处理 | -S(大写) | 只进行预处理和编译 | -c(小写) | 只进行预处理、编译和汇编 |
gcc的安装在晚上的教程就比较多,在这里就不一一介绍了
tips:
1.测试gcc安装:win+r键输入cmd后,在命令上中输入:cmd (进入命令行) 然后输入:
gcc -v
2.用gcc编译c方法 在文件目录上方点击cmd进入命令行,然后输入
gcc hello.c#加空格,此时输入文件名.c此时默认生成文件名.exe文件(同一目录下)
数据类型(生活中的数据类型是多种多样的,而程序在编写时是为了模拟显示的生活场景或解决一些实际问题)
#include<>和#include""区别
tips:
- < > 表示系统直接按系统指定的目录检索
- “” 表示系统先在 “” 指定的路径(没写路径代表当前路径)查找头文件,如果找不到,再按系统指定的目录检索
注释:
- //叫行注释,注释的内容编译器是忽略的,注释主要的作用是在代码中加一些说明和解释,这样有利于代码的阅读
- /**/叫块注释
- 块注释是C语言标准的注释方法
- 行注释是从C++语言借鉴过来的
1)预处理:宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除,这里并不会检查语法
2)编译:检查语法,将预处理后文件编译生成汇编文件
3)汇编:将汇编文件生成目标文件(二进制文件)
4)链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去
64位和32位
- 所有的64位CPU兼容32位的指令,32位要兼容16位的指令,所以在64位的CPU上是可以识别32位的指令
- 在64位的CPU构架上运行了64位的软件操作系统,那么这个系统是64位
- 在64位的CPU构架上,运行了32位的软件操作系统,那么这个系统就是32位
- 64位的软件不能运行在32位的CPU之上
CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。于是 CPU<—>寄存器<—>内存,这就是它们之间的信息交换
第一个c语言程序:
#include<stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
数据类型 | 说明以及字节数 |
---|
char | 字符型(1字节) | short | 短整型(2字节) | int | 整型(4字节) | long | 长整型(4字节) | long long | 更长的整型(8字节) | float | 浮点型(4字节) | double | 双精度浮点型(8字节) |
注释:c语言的标准规定是sizeof(long)>=sizeof(int)即(8>4)
计算机中的内存:最小的为比特位是二进制
计算机中的最小的为字节(一个字节是8个比特位)
一个kb是1024个字节 一个mb是1024kb 一个G是1024 一个T是1024G
**变量和常量(**简单的理解就是常量就是不变的值、变量就是变化的值) 变量的定义方法:类型 变量名=赋值
例如:int age =10;
变量分为局部变量和全局变量(两者在命名时是不要相同如果是一致的,此时局部变量优先)
#include<stdio.h>
#include<stdlib.h>
int num1=10;
int main(void)
{
int num2=20;
printf("%d\n",num2);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int num1=10;
示例:局部变量和全局变零重名
int main(void)
{
int num1=20;
printf("%d\n",num1);
return 0;
}
变量的生命周期:
1.从{开始到}结束,变量只在这个区域内起作用
2.全局变量的生命周期从头至尾,即整个程序的生命周期中局部变量都起作用
C语言中的常量:
- 字面常量
- const修饰的常变量
- #define第一的标识符常量
- 枚举常量
字面常量
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
10;
return 0;
}
const修饰的常变量
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
const int num1=10;
printf("%d\n",num1);
num1=20;
printf("%d\n",num1);
return 0;
}
标识符常量
#include<stdio.h>
#include<stdlib.h>
#define red 50
#define max 10
int main(void)
{
int arr[max]={0};
printf("%d\n",red);
return 0;
}
枚举常量
#include<stdio.h>
#include<stdlib.h>
enum Color{
yello,
red,
blue
};
int main(void)
{
printf("%d\n",yello);
printf("%d\n",red);
printf("%d\n",blue);
enum Color color=blue;
printf("%d\n",color);
color=0;
printf("%d\n",color);
return 0;
}
tips:
1.枚举关键字为enum
2.字符串:双引号括起来的一串字符
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char arr1[]={"abc"};
char arr2[]={'a','b','c'};
printf("%d\n",sizeof(arr1));
printf("%d\n",sizeof(arr2));
printf("%s\n",arr1);
printf("%s\n",arr2);
printf("%d\n",strlen(arr1));
printf("%d\n",strlen(arr2));
return 0;
}
tips: \0对字符串是十分重要的,(\0是转义字符-就是转变原来的字符的意思) 此时直接放置0也是可以的,只是加上\0加以区分(清晰明了)
例如:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
printf("abc\n");
printf("%c\n",'\'a');
printf("c:\test\32\test.c");
printf("\n");
printf("%d\n",strlen("c:\test\32\test.c"));
return 0;
}
C语言中如何实现循环
- while语句
- for语句
- do …while语句
数组:相同类型元素的集合
示例:
int arr[10];
char ch [20];
float arr2[5];
int arr3[10]={1,2,3,4,5,6,7,8,9,10};
数组变遍历:
函数的分类:
- 自定义函数
- 库函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int Add(int x,int y)
{
return (x+y);
}
int main(void)
{
int num1;
int num2;
int ret=0;
scanf("%d%d",&num1,&num2);
ret=Add(num1,num2);
printf("ret=%d\n",ret);
return 0;
}
操作符:
- 算术操作符+ - * \ %(取余)
- 移位操作符:<<(左移)>>(右移)
- 位操作符:二进制位&(按位于)、|(按位或)^(按位异或)
- 赋值操作符: +=、-=、*=、/=、%=、>>=、<<=
操作符:
- 单操作法(1个操作数):如:!逻辑反操作
- 双目操作符(两个操作符)如a+b
- 三目操作符
tips:
c语言中0为假非0为真
sizeof(计算变零或者类型所占内存空间的大小)
使用方法:
int num1=1;
prntf("%d\n,sizeof(num1));
prntf("%d\n,sizeof num1);
prntf("%d\n,sizeof(int));
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int sz=0;
printf("%d\n",sizeof(int));
printf("%d\n",sizeof(arr));
sz=sizeof(arr)/sizeof(arr[0]);
printf("%d\n",sz);
return 0;
}
运行结果:
tips:
- 字符串的结束的标志是‘\0’
- “abcdjf”;隐藏了‘\0’
- '\0’是转义字符
- 0是数字
- ‘0’是字符0
- EOF是文件结束标志
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int Add(int x,int y)
{
return (x+y);
}
int Max1(int x,int y){
return (x>y?x:y);
}
int Max2(int x,int y){
if(x<y){
return y;
}
else{
return x;
}
}
int main(void)
{
int num1;
int num2;
int ret=0;
int max1=0;
int max2=0;
scanf("%d%d",&num1,&num2);
ret=Add(num1,num2);
max1=Max1(num1,num2);
max2=Max2(num1,num2);
printf("ret=%d\n",ret);
printf("ret=%d\n",max1);
printf("ret=%d\n",max2);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int a=0;
int b=~a;
printf("%d\n",b);
return 0;
}
此时一定很是一会为什么输出为-1,因为此时的~是按位(二进制位)取反 图解: tips: 前置++和后置++ 前置++,就是先自增,再赋值 后置++,就是先赋值,再自增
类型转换:
- 自动类型转换
- 强制类型转换
int a=(int)3.14;
关系操作符:<、>、<=、>=、!=(测试不相等)、==(测试相等)
逻辑操作符:&&(逻辑与同时为真则为真)||(逻辑或有真为真)!(逻辑非假为真,真为假)
条件操作符:(三目运算符):exp?exp1:exp2;
max=a<b?b:a;
逗号表达式: exp1,exp2,exp3…expN;
元素引用:[ ]
函数调用:()
结构体:. 或者->
typedef关键字:重命名
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
unsigned int num1=20;
typedef unsigned int u_int;
u_int num2=20;
return 0;
}
static关键字:
- 修饰局部变量,会使局部变量的生命周期变长(下一次运行时会保留上次的值)
static int num1=3; 此时num1修改后的值会保留到下一次运行 - 修饰全局变量,此时改变了变量的作用域,此时静态修饰的全局变量只能在自己所在的.c文件中使用
如果是引用同一源文件下的全局变零 需要在该文将中声明
extern int g_val;
static int g_val;
- static修饰函数改变了函数的连接属性,函数默认是拥有外部链接属性的,用来static后,函数就只要内部链接属性
#define
- 定义变量
- 定义宏
示例 定义变量
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define max 100
#define Max(x,y)(x>y?x:y)
int main(void){
int num=max;
int ret;
int num1,num2;
scanf("%d%d",&num1,&num2);
ret=Max(num1,num2);
printf("ret=%d\n",ret);
printf("num=%d\n",num);
return 0;
}
运行结果:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int a=10;
printf("%p\n",&a);
int* p=&a;
printf("%p\n",p);
int sz=sizeof(p);
printf("%d\n",sz);
return 0;
}
结构体:复杂对象,多种数据类型
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Book{
char name[20];
short price;
};
int main(void){
struct Book book1={"c语言程序设计",55};
struct Book book2={"哲学",89};
printf("书名:%s\n",book1.name);
printf("书名:%s\n",book2.name);
printf("价格:%d\n",book1.price);
printf("价格:%d\n",book2.price);
struct Book* pb=&book1;
printf("%s\n",(*pb).name);
printf("%s\n",(*pb).price);
printf("%s\n",pb->name);
printf("%s\n",pb->price);
return 0;
}
2章(分支和循环)
分支和循环c语言是一门结构化的程序语言
- 顺序结构
- 选择结构
- 循环结构
分支语句(选择结构):
- if
- switch
循环语句:
- while
- for
- do…while
goto语句 (由分号隔开的就是一条语句)
单分支示例:
if(表达式)
语句1;
else
语句2;
多分支:(只能执行一个,由上至下)
if(表达式1)
语句1;
esle if (表达式2)
语句2;
else
语句3;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int age=0;
scanf("%d",&age);
if (age<18){
printf("age=%d是未成年",age);
}else if(age>=18&&age<28){
printf("age=%d是青年",age);
}else if(age>=28&&age<50){
printf("age=%d是壮年",age);
}else{
printf("age=%d是老年",age);
}
return 0;
}
如果条件语句后面只有一条语句此时可以不加{}括起来,如果是多条语句则需要将其括起来
if 语句也可以嵌套使用,示例
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int age=0;
scanf("%d",&age);
if (age<18){
printf("age=%d是未成年",age);
}else{
if(age>=18&&age<28){
printf("age=%d是青年",age);
}else if(age>=28&&age<50){
printf("age=%d是壮年",age);
}else{
printf("age=%d是老年",age);
}
}
return 0;
}
悬空else问题:(else与离他最近的else进行匹配)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int a=1;
int b=2;
if (a==2)
printf("hehe");
if(b==2)
printf("haha");
else{
printf("xixi");
}
return 0;
}
如果改一下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int a=1;
int b=2;
if (a==2){
printf("hehe");
if(b==2){
printf("haha");
}
}else{
printf("xixi");
}
return 0;
}
tips:
1.没有缩进的代码不是好代码 2.正确的是该缩进的缩进,该回车的回车 3.=号和==号是不一样的(可以在使用的时候写成下面方式)
if(5==num)
判断一个数是否是奇数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int num=0;
scanf("%d",&num);
if (num%2==0){
printf("num=%d是偶数",num);
}else{
printf("num=%d是奇数",num);
}
return 0;
}
switch语句是一种分支语句,实现的功能也是可以使用if…else…实现 (只是if…else…在实现的时候比较慢)
语法:
switch(整型表达式)
{
语句项;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int day;
printf("请输入星期:");
scanf("%d",&day);
switch(day){
case 1:
printf("是星期一");
break;
case 2:
printf("是星期二");
break;
case 3:
printf("是星期三");
break;
case 4:
printf("是星期四");
break;
case 5:
printf("是星期五");
case 6:
case 7:
printf("是周末");
break;
default:
printf("输入错误");
break;
}
return 0;
}
tips:
1.此时的switch(一定是整型)
2.break不一定是要有根据需要进行选择,但是不执行后面的语句最好加上break
3.default(上面的都不成立的时候执行下面的语句)
4.default和case没有顺序可言,但是建议将default放在最后面
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int n=1;
int m=2;
switch(n){
case 1:m++;
case 2:n++;
case 3:
switch(n){
case 1:n++;
case 2:m++,n++;break;
}
case 4:m++;break;
default:
break;
}
printf("m=%d,n=%d\n",m,n);
return 0;
}
循环语句:
- while
- for
- do…while…
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
while(i<10){
if (i==5){
break;
}
printf("%d\n",i);
i++;
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
while(i<10){
if (i==5){
i++;
continue;
}
printf("%d\n",i);
i++;
}
return 0;
}
运行结果: tips:
- continue的作用是跳过该循环后面的语句,执行下一次循环
- break是直接跳出循环(此层循环,如果有多层循环)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
char ch=0;
while((ch=getchar())!=EOF){
putchar(ch);
}
return 0;
}
tips:
1.getchar就是接收一个字符,然后putchar是输出一个字符
2.EOF是end of file(值为-1,此时按下ctrl+z就是eof的意思)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
char password[20];
int ret=0;
int ch=0;
printf("请输入密码:");
scanf("%s",password);
while((ch=getchar())!='\n'){
;
}
printf("请确认是否接收密码:(Y or N)");
ret=getchar();
if (ret=='Y'){
printf("password=%s确认密码",password);
}else{
printf("passworf=%s放弃确认",password);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
while(i<10){
i++;
}
return 0;
}
while循环:
1.表达式1为初始化部分
2.表达式2为条件判断部分,用于判断循环终止
3.表达式3调整部分,用于循环条件的调整
三种循环(for、 while、 do… …while…)(一种可以替代另外的两种,此时用的最多的还是for循环)
for循环语句: 语法:for(表达式1:;表达式2;表达式3)
tips: 在for循环中的continue和berak的作用一样的
注意点:如果在while语句中执行continue是一定是要讲变量改变,否则会陷入死循环
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
for(i;i<10;i++){
if (i==5){
continue;
}
printf("i=%d\n",i);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
while(i<10){
if (i==5){
continue;
}
printf("i=%d\n",i);
i++;
}
return 0;
}
此时程序陷入死循环,因为此时的i一直是5,这是因为while循环循环条件的调整是独立的,此时i==5后,此条件未调整
tips;
- 不要再for循环体内修改循环变量,防止for循环失去控制
- 建议for循环控制变量的取值采用:前闭后开的写法
应用for(数组遍历\冒泡排序、数组求最大值、数组逆序)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int arr[10]={0,1,2,3,4,5,6,7,8,9};
int sz=sizeof(arr)/sizeof(arr[0]);
int max=0;
int temp=0;
int i=0;
for (i=0;i<sz;i++){
printf("i=%d\n",i);
}
for(i=0;i<sz;i++){
if(arr[i]>max){
max=arr[i];
}
}
printf("max=%d\n",max);
for(i=0;i<sz;i++){
if ((sz-i-1)>=i){
temp=arr[i];
arr[i]=arr[sz-1-i];
arr[sz-1-i]=temp;
}
}
for(i=0;i<sz;i++){
printf("i=%d\n",arr[i]);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int arr[10]={9,8,7,6,5,4,3,2,1,0};
int sz=sizeof(arr)/sizeof(arr[0]);
int i,j;
int temp;
for (i=0;i<sz-1;i++){
for(j=0;j<sz-1-i;j++){
if (arr[j]>arr[j+1]){
temp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
}
}
}
for(i=0;i<sz;i++){
printf("i=%d\n",arr[i]);
}
return 0;
}
for循环的变种:
tips;
- for 循环的初始化、调整、以及判断都输可以省略的,但是for循环的判断如果省略,那么则默认恒为真
- 若果不是很熟练,那么推荐不要省略
注意:初始值省略,此时的值为之前的变量值,如果循环改变了变量值,后面一直就是改变后的值
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
int j=0;
for(;i<10;i++){
for(;j<10;j++){
printf("hehe\n");
}
}
return 0;
}
输出为: 变种:判断的条件可知两个,此时循环的变量也可以只两个
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
int j=0;
for(i=0,j=0;i<=2&&j<5;++i,j++){
printf("haha\n");
}
return 0;
}
运行结果: tips:
如果得判断是k=0,若等式成立,则执行语句,如果是不成立,则不执行语句(for循环后的语句)
示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
int j=0;
for(i=0,j=0;i=1;++i,j++){
printf("haha\n");
}
return 0;
}
i=0意思是表达式为0,为假,所以不执行循环 i=1的意思是表达式为1,为真,所死循环
do while()循环至少执行一次 语法
do{
循环语句;
}while(判断);
do while()和while循环内使用continue一定要注意此时循环控制变量一定要让其发生改变,否则会陷入死循环
示例: 死循环:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
do{
if(i==5){
continue;
}
printf("i=%d\n",i);
i++;
}while(i<10);
return 0;
}
改正:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int i=0;
do{
if(i==5){
i++;
continue;
}
printf("i=%d\n",i);
i++;
}while(i<10);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int Factor(int n){
int ret=1;
int i=n;
for(i;i>=1;i--){
ret*=i;
}
return ret;
}
int main(void){
int num;
int ret=0;
int n_ret=0;
int i=0;
scanf("%d",&num);
ret=Factor(num);
printf("num=%d\n",ret);
for(i=num;i>=1;i--){
n_ret+=Factor(i);
}
printf("n_ret=%d\n",n_ret);
return 0;
}
有序数组中查找具体的数字(不重复数组)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int arr[10]={1,34,45,3,9,7,39};
int sz=sizeof(arr)/sizeof(arr[0]);
int find_num;
scanf("%d",&find_num);
int i=0;
for(i=0;i<sz;i++){
if(arr[i]==find_num){
printf("下标是%d,find_num=%d",i,find_num);
break;
}else{
if(i==(sz-1)){
printf("没找到,find_num=%d\n",find_num);
}
}
}
return 0;
}
二分查找法:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int sz=sizeof(arr)/sizeof(arr[0]);
int find_num;
scanf("%d",&find_num);
int left=0;
int right=sz-1;
while(left<=right){
int mid=(left+right)/2;
if (arr[mid]>find_num){
right=mid-1;
}else if(arr[mid]<find_num){
left=mid+1;
}else {
printf("find_name=%d,下标为%d",find_num,mid);
break;
}
}
if(left>right){
printf("找不到");
}
return 0;
}
示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
int main(void){
char arr1[]="welcome hello world";
char arr2[]="###################";
int sz=sizeof(arr2)/sizeof(arr2[0]);
int left=0;
int right=sz-2;
while(left<=right){
arr2[left]=arr1[left];
arr2[right]=arr1[right];
printf("arr2=%s",arr2);
Sleep(1000);
system("cls");
left++;
right--;
}
printf("arr2=%s\n",arr2);
return 0;
}
示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
int count=0;
char password[20]={};
while(count<3){
printf("请输入密码:");
scanf("%s",password);
if(strcmp(password,"123445")==0){
printf("输入成功\n");
break;
}else{
count++;
}
}
if (count==3){
printf("你输入的次数是:%d,已经超过了最多次数\n",count);
}
return 0;
}
|