初始C语言
文章目录
什么是C语言
C语言是一门计算机语言,人与计算机交流的语言
计算机语言的发展
早期计算机识别的是二进制语言,电脑是硬件,通电的(正电与负电)
早期汇编语言:10100001 ADD-助记符-汇编语言
B语言->C语言->C++
有低级向高级不断的推展,越发展越简单,让更多的人能够编写(类比傻瓜照相机,功能越来越多,操作越来越简单)
C语言
C语言早期不成熟,慢慢成熟,最后到流行,但是由于早期不成熟,每个公司都对C语言进行编改,导致不统一,所以对C语言进行了国际标准ANSIC(89年推出)
C99和C11并不是非常流行,所以存在兼容性,一些编译器不支持
第一个程序
-
创建工程
-
创建源文件
-
写代码
main 表示主函数,程序的入口
int 是整型的意思,main 前面的 int 表示 main 函数调用返回一个整数型
调用printf 这个打印函数
库函数-C语言本身提供我们使用的函数,但是这是属于别人的东西,我们需要打招呼,所以在前面声明stdio.h的头文件,std 表示标准,i o 表示输入和输出
数据类型
char 字符数据类型
short 短整型
int 整型
long 长整型
long long 更长的整型
float 更精准的浮点型
double 双精度的浮点型
%c 打印字符格式的数据
%s 打印字符串类型的数据
%d 打印十进制整型的数据
%f 打印浮点数字(小数)->双精度%lf
%p 以地址的形式打印
%x 打印十六进制的数据
bit:最小的单位,一个bit只能存放一个二进制位
byte字节:计算机里面的单位,一个字节等于八个比特位
pb = 1024 tb = 1024 gb = 1024 mb = 1024 kb = 1024 byte;
C语言国际标准:sizeof(long)>=sizeof(int)
变量和常量
定义变量和常量,还有全局变量和局部变量,当局部变量的名字和全局变量相同时,局部变量优先(建议不用)
定义变量在最前面,不然会报错。
变量的作用域和生命周期
作用域
作用域:程序设计概念,通常来说,一段程序代码所用到的名字并不总是有效的或可用的
而限于这个名字的可用性的代码范围是这个名字的作用域
- 局部变量的作用域是变量所在的局部范围
- 全局变量的作用域是整个工程
生命周期
变量的生命周期指的是变量的创建到变量的周期的销毁之间的一个时间段
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束
- 全局变量的生命周期是:整个程序的生命周期
scanf 是C语言提供的,而 scanf_s 是VS编译器提供的,不建议写后种,因为代码不具有可移植性和跨平台性,使用一个宏定义第一行加上一句话,就可以解决
#define _CRT_SECURE_NO_WARNINGS 1
加在源文件的第一行,来解决一些跨平台报错的问题
常量
- 字面常量:直接写出来的常量,主观写出来的
- const 修饰的常量:const 指的是常属性 (n 是变量,但是具有常属性,所以n为常变量)
- #define 宏定义的量
- 枚举常量:一一列举(星期、性别、三原色),枚举关键字:enum
enum Sex{
MALE,
FEMALE,
SECRET
};
字符串,转义字符,注释
字符串
“hello,world\n”:这种由双引号引起来的字符串字面值,或者称为字符串
字符串得到结束符标志是一个\0 的转移字符,在计算字符长度的时候\0是结束字符,不算字符内容,\0 的数字为0
EOF:end of file —— 文件结束标志,本质上数据为-1
数据存储在计算机上面的时候是二进制,所以出现ASCII码来代表一些字符的数字
strlen 求的字符串的长度不包括\0在内,不统计
转义字符
\n 换行 \t 空格
注释
一些复杂的代码可以增加一些注释来帮助我们理解。
选择语句 if语句
#include <stdio.h>
int main()
{
int input=0;
printf("please input a num about choice\n");
scanf("%d",&input);
if(input == 1)
printf("earn a good offer\n");
else
printf("sell a bargain\n");
}
循环语句
while 语句和 do while 语句
for 语句
函数
当一个程序需要运用一个相同的方法运算的时候,就可以定义一个函数,然后调用这个函数,就可以减小这个程序的时间空间的复杂度,加快程序的运算以及简单,与Javascript当中的数据的切割一样,可以使用函数来执行。
函数分为库函数和自定义的函数,然后如果调用库函数的话就应该了解相应的函数所需要的调用的头文件。
数组的使用以及声明
通过下标来访问以及下标从 0 开始
操作符
如果是左移右移字符,移动后原来的数字一定不会改变,就只有一个变量来储存移动后的数字会随着移的位不一样而改变,但是原来的数字不会改变(移动都是二进制位,000000000001 —> 000000000010 )
& | ^ 按位与、或、异或
sizeof 计算的是变量/类型所占的空间大小,单位是字节
后置++:先使用,后++
前置++:先++,在使用
. 应用在结构体当中就可以访问里面的成员(结构体变量)
-> 应用在结构体当中也是访问对象,但是可以针对结构体变量访问结构体里面的成员
原码、反码、补码
负数在内存中存储的时候,存储的是二进制的补码
只要是整数,内存中存储的都是二进制的补码,正数的原码,反码,补码都相同
原码:直接按照正负,写出二进制的序列
反码:原码的符号位发生改变,其他位取反得到
补码:反码+1
条件操作符
exp1?exp2:exp3;
逗号操作符
exp1,exp2,exp3,…expN 认识到逗号之间可以写表达式就可以
一些常见的关键字
- 关键字typedof:顾名思义是类型的定义,这里应该理解为类型重命名(别名)
- 关键字static:修饰局部变量,将局部变量生命周期变长;修饰全局变量,改变全局变量的作用域,让静态的全局变量只能在自己所案子的源文件里面使用,除了源文件就无法使用;修饰函数,改变了函数的作用域,但是不太准确,改变函数的来链接属性,普通的函数时具有外部外部链接属性,一旦被static 修饰就从外部链接属性——>内部链接属性
指针
有一种变量时用来存储地址的——>指针
*p -->是一种解引用的操作符,可以对这个变量指的一个变量进行操作
无论什么类型都是这样,因为他存放的是地址
指针所占的字节大小 32->4 64->8
内存
#include <stdio.h>
int main()
{
int a = 10 ; //向内存申请了四个字节的空间
printf("%p\n",&a);
int* p = &a;
printf("%p\n",p);
return 0;
}
Ctrl + Fn + F
运行时发现存在一闪而过的现象,解决方法就是:项目名称->属性->链接器->系统->子系统->控制台->点应用
结构体
结构体就是我们创造出来的一种类型
struct Book{
char name[20];
short price;
};
#include <stdio.h>
#include <string.h>
int main()
{
// 利用结构体的类型-创建一个还类型的结构体变量
struct Book b1 = {"C语言程序设计","55"};
struct Book* pd = &b1;
printf("书名:%s",(*pd).name);
printf("书名:%s",pd->name);
printf("书名:%s",b1.name);
printf("价格:%d\n",b1.price);
b1.price = 35;
strcpy(b1.name,"C++");
printf("修改后的价格:%d\n",b1.price);
printf("修改后的书名:%s\n",b1.name);
return 0;
}
疑问:为什么修改价格,前面仍然输出的是原来的价格,但是后面的价格输出的是修改后的价格,以后扩展怎么修改结构体的书名
-
解答: 修改价格的时候,是因为程序是一步一步的执行的,修改的步骤在输出前一个没有修改价格的后面,所以先输出的就是没有改变的价格,但是之后因为价格已经被修改,所以,后输出的价格就发生了变化。
-
strcpy 字符串拷贝(有两个参数),关于字符串操作的,修改价格很容易是因为价格是一个变量,但是名字是一个数组,用上面的方法所指的是这个数组的地址
博客的重要性
GitHub:注册一个账户,创建一个代码仓库
QQ 空间就相当于 Github 的代码库,可以设置公开
坚持写代码,然后上传代码就可以看到一片绿色,对面试有帮助,帮助我们自律,贵在坚持。
分支与循环
C语言是一门结构化的程序设计语言
- 顺序结构
- 选择结构
- 循环结构
分支语句和循环语句
什么叫语句?
C语言当中由一个分号;隔开的就是一条语句,比如:
printf("hehe");
1+2;
分支语句:
分支语句也就是选择语句,如果你好好努力的话可以找到一个搞得工作,如果你不好好弄学习的话,你就要去卖红薯。
- 分支语句
if:注意格式,好的格式利于人们阅读同时也减少错误
语法结构:
if(表达式)
语句;
if(表达式)
语句1;
else
语句2;
if(表达式)
语句1;
else if(表达式)
语句2;
else
语句3;
//判断一个数字是否为奇数
#include <stdio.h>
int main()
{
int a;
printf("please input a number\n");
scanf("%d",&a);
if( a%2 == 0)
{
printf("这个数不是奇数\n");
}
else
printf("这个数是奇数\n");
return 0;
}
//输出1~100之间的奇数
#include <stdio.h>
int main()
{
for( int i = 1;i<=100;i++)
{
if( i%2 != 0)
printf("%d\t",i);
}
return 0;
}
switch:switch 语句也是一种分支语句,常常用于多分支的语句
#include <stdio.h>
int main()
{
int day;
printf("please input a day\n");
scanf("%d",&day);
switch(day)
case 1:printf("星期1\n");break;
case 2:printf("星期2\n");break;
case 3:printf("星期3\n");break;
case 4:printf("星期4\n");break;
case 5:printf("星期5\n");break;
case 6:printf("星期6\n");break;
case 7:printf("星期7\n");break;
default:printf("输入错误\n");break;
}
- 循环语句
while
总结:break 在 while 循环语句里面的作用,其实在循环语句当中只要遇到 break ,就会停止后期的所有循环,直到终止循环,所以 while 中的 break 是用于永久终止循环的。continue 在 while 循环语句里面的作用,continue 是用于终止本次循环的,也就是本次循环中continue后面的代码不会执行,而是接着跳转到while语句里面的判断部分,进行下一次循环语句入口的判断
#include <stdio.h>
int main()
{
//putchar 语句和printf语句的功能是一样的
int a = getchar();
putchar(a);
printf("%c\n",a);
return 0;
}
//这样的语句在实际开发中有什么意义?
#include <stdio.h>
int main()
{
int ch = 0;
while(ch = getchar() != EOF)
{
putchar(ch);
}
return 0;
}
例如书写一个代码进行输入密码和确认密码的判断,存储密码会进行筛选,接着后面的代码会首先看缓存区里是否有东西,如果没有才执行下面的语句,有的话会照样执行,导致终止运行,密码:123456 ABCD
空格不等于\0
/*这个代码只会输出数字,不会输出其他的字母
字符以及其他的符号,这里需要用到ASCII表*/
#include <stdio.h>
int main()
{
while((ch = getchar() != EOF))
{
if(ch < '0' || ch > '9')
continue;
putchar(ch);
}
return 0;
}
for
for(表达式1;表达式2;表达式3)
循环语句
表达式1为初始化部分,用于初始化循环的变量,表达式2为条件的判断的部分,用于判断循环时候终止,表达式3为调整部分,用于循环条件的调整。
不可以在for循环体内修改变量,防止for循环失去控制,建议for语句的循环控制变量的取值采用“前闭后开区间”的写法
do while:至少要执行一次
do
循环语句
while();
//1.计算n的阶乘
#include <stdio.h>
int main()
{
int n = 0;
int sum = 1;
printf("please input a number\n");
scanf("%d",&n);
for(int i = 1;i<=n;i++)
{
sum*=i;
}
printf("sum = %d",sum);
return 0;
}
//2.计算1!+ 2!+ 3!+ 4!····+10!
#include <stdio.h>
int main()
{
int n = 0;
int ret = 1;
int sum = 0;
for(n = 1;n<=10;n++)
{
ret = 0;
for(int i = 1;i<=n;i++)
{
ret*=i;
}
sum+=ret;
}
return 0;
}
#include <stdio.h>
int main()
{
int n = 0;
int ret = 1;
int sum = 0;
for(n = 1;n<=10;n++)
{
ret*=n;
sum+=ret;
}
return 0;
}
//3.在一个有序数组中查找具体的某个数字n,编写int binsearch(int x,int v[],int n);功能:在v[0]<=v[1]<=v[2]<=···<=v[n-1]的数组中查找x
这样的算法过于冗杂,我们应该加快效率,可以使用折半查找法
#include <stdio.h>
binsearch(int x,int v[],int n);
int main()
{
int x = 0;
int n = 0;
int v[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14}
printf("please input a number\n");
scanf("%d",&n);
printf("please input a number\n");
scanf("%d",&x);
binsearch(x,v[],n);
}
binsearch(int x,int v[],int n)
{
for(int i = 0; i<20; i++)
if(v[i] == x)
printf("v[%d] == x,找到了",i);
}
//二分查找法:
#include <stdio.h>
int main()
{
int arr[]={1,2,3,4,5,6,7,8,9,10};
int size = sizeof(arr)/sizeof(arr[0]);
int right = size-1; //数组的右下标
int left = 0; //数组的左下标
int x = 0;
printf("请输入你需要查找的数字\n");
scanf("%d",&x);
while(left < right)
{
int mid = (right + left)/2;
if (arr[mid] > k)
{
right=mid-1;
}
else if (arr[mid] < k )
{
left=mid+1;
}
else
{
printf("找到了,下标为%d\n",mid);
break;
}
}
if( left > right)
{
printf("找不到\n");
}
}
//4.编写代码,演示多个字符从两端移动,向中间汇聚
//涉及到的知识点就是得到一个数字的长度,但是在字符串的数组里面,存在\0 这个结束字符,是并不可以避免的,所以在得到数组最后一个下标的时候一定要考虑\0 这个字符,不然程序就会出现问题,这里就存在两种计算数组长度的方法,一个就是用sizeof(),一个就是使用strlen(),两者不同的就是sizeof()不会避免字符串的最后内个\0,但是strlen 在计算的时候是不会考虑的,所以具体情况具体分析就可以
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
int main()
{
char arr1[] = "Welcome to bit!!!!!";
char arr2[] = "###############";
int left = 0;
int right = strlen(arr1) - 1;
while(left<=right)
{
arr2[left]=arr1[left];
arr2[right]=arr2[right];
printf("%s\n",arr2);
//休息一秒
Sleep(1000);
//执行系统命令的一个函数-cls-清空屏幕
system("cls");
left++;
right--;
}
printf("%s",arr2);
return 0;
}
//5.编写代码实现,模拟用户登录的情景,并且只能登录三次,只允许输入三次密码,如果密码正确则登录成功,如果三次均输入错误,则退出程序。
//等号不能用来表示字符串是否相等,这里就可以联想到上一次书的信息,字符串的修改以及字符串的比较都不是向我们想象的那样简单,这里就需要调用库函数,所以就可以调用strcmp这个库函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char oripassword[20]={'123456789'}
char password[20];
for(int i = 0;i<3;i++)
{
printf("please input your password\n");
scanf("%s",password);
if(strcmp(oripassword,password) == 0)
{
printf("登陆成功\n");
break;
}
}
if(i == 3)
printf("密码错误\n");
return 0;
}