C语言
安装vs2022
配置环境
第一个程序
#include <stdio.h>
int main(){
printf("Hello world");
return 0;
}
在第一个程序中,stdio.h全称为标准输入输出,在<>内,还可以放置math.h,time.h等其他库。int定义程序的结果是一个整数,main定义程序的主入口名字,不能改变。{}内是代码范围,return 0;表示程序正常结束,非0表示非正常结束,它于int main相对应。
程序执行流程
1.编写
2.编译
3.链接
4.执行
核心语法
注释
//test
/*
test
*/
关键字
关键字为全部小写高亮字符
常量
- 整数常量
- 实型常量 (带小数点的常量)
- 字符常量 (带单引号的单个字母数字符号)
- 字符串常量
输出常量
#include <stdio.h>
int main(){
printf("输出最终内容",)
}
格式控制符 | 说明 | 单词 |
---|---|---|
%d | 整数型 | decimal |
%f | 实型 | floating-point |
%c | 字符型 | character |
%s | 字符串型 | string |
#include <stdio.h>
int main(){
printf("魏鑫身高%f,年龄%d,喜欢吃%s",121.1,18,"shi");
return 0;
}
Tips
#include <stdio.h>
int main() {
printf("魏鑫的女朋友的姓名是:%s。性别%s。年龄%d。身高%.1f米。体重%d。", "狗", "女", 18, 1.5, 110);
return 0;
}
变量
格式
int a ; #int:类型,a:变量名
#include <stdio.h>
int main() {
int a = 10, b = 20,c=a+b;
printf("c是:%d", c);
return 0;
}
计算机存储规则
略
数据类型
整数类型
整数 | 取值范围 | 内存 |
---|---|---|
short | -32768~32767 | 2 |
int | -2147483648~2147489647 | 4 |
long | ……………………………………… | 4,8 |
long long | ………………………………………………… | 8 |
sizeof()测量数据类型占用多少字节
#include <stdio.h>
int main() {
short int a = 10;
printf("%d\n",a);
int b = 50;
printf("%d\n",b);
long int c = 1000L;
printf("%ld\n",c);
long long int d =10000L;
printf("%lld\n",d);
//signed:定义有符号整数,正数,复数
//unsigned:定义无符号整数,正数
signed int e = -4;
printf("%d\n",e);
unsigned int d = 1; //定义一个序号1,甚至你还可以在unsigned后加个short
printf("%u\n",d)
return 0;
}
#include <stdio.h>
int main() {
float a = 3.14F;
printf("%.2f\n",a);
//double双精度小数
double b = 1.78;
printf("%.lf\n",b);
// long double高精度小数
long double c = 3.1415926L;
printf("%.2lf\n",c)
//用sizeof测量每个类型占多少字节
printf("%zu\n",sizeof(float));
printf("%zu\n",sizeof(a));
//小数数据无法跟unsigned组合使用
}
//char类型占一个字节
char a = "a",b = "1";
printf("%c\n%c\n",a,b);
算数运算符与逻辑运算符
大致省略
Tips
键盘输出数字,将其拆分成个位,十位,百位(只能输入百位数)
#include <stdio.h>
int main() {
printf("请输入数字:");
int num;
scanf_s("%d", &num);
int ge;
ge = num % 10;
printf("个位:%d\n", ge);
int shi;
shi = num / 10 % 10;
printf("十位:%d\n", shi);
int bai;
bai = num / 100 % 10;
printf("百位:%d\n", bai);
return 0;
}
隐式转换
- 在进行不同类型的数据计算时,会把取值范围小的数据类型转换为取值范围大的数据类型
- short和char在进行运算时会提升为int类型再计算
double > float > long long > long > int > short > char
强制转换
- 如果把取值范围大的转换为取值范围小的,就要强制转换
int a = 10;
short i = (short)a;
____________________________________________________________________________________________________________
short a = 10;
short b = 20;
shout r = (short)a + b;//shout运算时会转换为int
运算符
字符相加
#include <stdio.h>
int main() {
//"a" "A" "0"所对应的ascll码
printf("%d",'a');
printf("%d",'A');
printf("%d",'0');
return 0;
}
自增自减运算符
int a = 10;
a++;//a = 11
a--;//a = 9
++a;//a = 11
--a;//a = 9
win7时前缀优先后缀,其他优先级一样
赋值运算符
略
关系运算符
略
逻辑运算符
略
&& 与 ||具有短路效果
三元运算符
- 格式:关系表达式? 表达式1: 表达式2;
- 首先计算关系表达式的值
- 如果成立,返回表达式1,反之返回表达式2
//求两数最大值
a > b ? a : b;
//求三数最大值
int t = a > b ? a : b;
t > c ? t : c;
逗号运算符
略
运算符的优先级
流程控制语句
- 顺序结构
- 分支结构
- 循环结构
分支结构
if a<b {
return 0;
}
else if {
return 0;
}
else {
return 0;
}
switch () {
case 1 :
break;
case 2 :
break;
default :
break;
}
循环语句
for (初始;判断;控制;) {
return 0;
}
//输入两个整数,求它们范围内能被6和8整除的数
#include <stdio.h>
int main() {
int num1, num2;
int a = 0;
printf("请输入两个整数:\n");
scanf_s("%d\n%d", &num1,&num2);
for (int i = num1; i < num2; i++) {
if (i % 6 == 0 && i % 8 == 0) {
printf("依次为:\n%d\n", i);
a++;
}
}
printf("一共有%d个", a);
return 0;
}
//初始化
while (判断){
循环
控制
}
#include <stdio.h>
int main() {
int n = 0;
printf("请输入数字:");
scanf_s("%d", &n);
int i = n;
//printf("%d", i);
while (i != 1 && i % 2 == 0) {
i /= 2;
//printf("%d\n", i);
}
//printf("%d", i);
if (i == 1) {
printf("yes");
}
else {
printf("no");
}
return 0;
}
#include <stdio.h>
int main() {
int a = 0;
double b = 0.1;
while (b <= 8844430) {
b = b * 2;
a++;
}
printf("%d", a);
return 0;
}
#include <stdio.h>
int d = 0;
int a = 0;
int main()
{
printf("请输入数字");
scanf("%d", &d);
while (d != 0)
{
int temp = d % 10;
d/=10;
a =a * 10 + temp;
}
printf("%d", a);
}
#include <stdio.h>
int main()
{
int a;
printf("Enter a number: ");
scanf("%d", &a);
int b = 0;
int c = 0;
while (c < a)
{
b++;
c = b * b;
}
printf("The number is: %d", b-1);
}
#include <stdio.h>
int d = 0;
int a = 0;
int main()
{
printf("请输入数字");
scanf("%d", &d);
int c = d;
while (d != 0)
{
int temp = d % 10;
d/=10;
a =a * 10 + temp;
}
if (a == c)
{
printf("true");
}
else if(a!=c)
{
printf("not");
}
}
#include <stdio.h>
int main()
{
int a,b;
int c = 0;
printf("Enter a number:");
scanf("%d",&a);
printf("Enter another number:");
scanf("%d",&b);
while (a>=b)
{
a=a-b;
c++;
}
printf("商:%d\n",c);
printf("余:%d",a);
}
do….while 语句
初始化语句;
do {
循环体语句;
条件控制语句;
}while循环(条件判断语句);
循环语句(高级)
无限循环
for (;;){
}
while (1){
}
do{
}while(1)
跳转控制语句
- 在循环控制中,跳到其他语句执行
#在100内第一个能被3和5整除的数
#include <stdio.h>
int main()
{
for (int i = 1;i<100;i++)
{
if (i%3==0&&i%5==0)
{
printf("%d\n",i);
break;
}
}
}
#continu就是结束本次循环,跳过本次循环,执行下次循环
循环嵌套
#打印三行五列的*
int main()
{
for (int i = 0;i < 3;i++)
{
printf("\n");
for (int j = 0;j < 5;j++)
printf("*");
}
return 0;
}
#打印正直角三角和倒直角三角
int main()
{
for (int i = 1;i <= 5;i++)
{
printf("\n");
for (int j = i;j <= 5;j++)
printf("*");
}
return 0;
}
int main()
{
for (int i = 1;i<=5;i++)
{
printf("\n");
for (int j = 1;j <=i ;j++)
printf("*");
}
return 0;
}
#九九乘法表
int main()
{
for (int i =1; i<10; i++)
{
printf("\n");
for (int j =1; j<=i; j++)
{
printf("%d * %d = %d\t",j,i,j*i);
}
}
return 0;
}
#找质数
int main()
{
int a = 0;
int c = 0;
printf("num");
scanf("%d",&a);
for (int i = 2; i <= a; i++)
{
int b = 0;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
b++;
break;
}
}
if (b == 0)
{
printf("yes");
c++;
}
else
{
printf("no");
}
}
printf("%d",c);
return 0;
}
#输出1~1000内个数相加为15的数
int main()
{
for (int i = 1;i <= 1000;i++)
{
int a = i;
int b = 0 ;
while (a != 0){
b = a;
int temp = a % 10;
a = a / 10;
int temp2 = a % 10;
a = a / 10;
if (temp + temp2 + a == 15)
{
printf("%d\t",b);
}
}
}
return 0;
}
#### go to 使用
for (i = 0;i < 5;i++){
for (j = 0;j < 5;j++){
printf("he");
goto a;
}
}
a: printf("llo");
函数
常见函数
c手册:cppreference.com
随机数
线性同余方程
$x$n-1 $ = ax_n + b\,mod\,m$
#include <stdio.h>
#include <stdlib.h>
int main(){
srand(1);
for (int i; i < 5; i++){
int num = rand();
printf("%d\n",num);
}
return 0;
}
弊端:
- 种子固定,随机数固定
- 随机数范围(0~32767)
#随机种子
int main(){
srand(time(NULL));
int num = rand();
printf("%d\n",num);
}
#定义随机范围
#1.(7~87),包左不包右,7~88(87+1)
#2.拿右减开头 88 - 7 = 81
int main(){
srand(time(NULL));
int num = rand() % 81+ 7;//0~80 7 就是7~87
printf("%d\n",num);
}
#判读输入的数是否与随机数相同
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
for (int i = 1; i <= 100; i++) #用while(1)也行
{
int num = rand() % 100 + 1;
printf("随机数为:%d",num);
printf("Enter:");
int num1 = 0;
scanf("%d", &num1);
if (num == num1)
{
printf("%d\n", num);
break;
}
else
{
printf("no\n");
}
}
}
数组
数据类型 数组名 [长度] ={数据值,数据值……}
变量 = 数组名[索引]
数组遍历
略
内存地址
32位:2^32^
64位:2^54^
转十六位方便阅读
数组在内存中
a[5] = {1,2,3,4,5};
printf("%p/n",a);
数组的俩问题
- 数组作为函数的形参,注意什么
- 实际传递的是数组的首地址
- 数组的索引越界问题
- 最小索引:0
- 最大索引: 长度-1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void aa();
int main()
{
int a[] = {1,2,3,4,5};
int size = sizeof(a) / sizeof(int);
aa(a,size);
}
void aa(int a[],int size)
{
for (int i = 0; i < size; i++)
{
printf("%d\n",a[i]);
}
}
#求最大值
int main()
{
int a [] ={33,5,66,44,55};
int len = sizeof(a) / sizeof(int);
int max = 0;
for (int i = 1; i < len; i++)
{
if (a[i] > max)
{
max = a[i];
}
}
printf("%d\n", max);
}
int main()
{
srand(time(NULL));
int a = 0,sum = 0;
int b[10] = {0};
for (int i = 0; i < 10; i++) {
a = rand() % 100 + 1;
b[i] = a;
sum += b[i];
}
printf("和:%d",sum);
}
int main()
{
srand(time(NULL));
int a= 0,sum = 0,c = 0,d = 0;
float count = 0;
int b[10];
for (int i = 0; i < 10; i++)
{
a = rand() % 100 + 1;
b[i] = a;
sum += b[i];
c++;
}
count = sum;
for (int i = 0; i < 10; i++)
{
if (b[i] < count/c)
{
d++;
}
}
printf("和:%d:\n",sum);
printf("平均数:%.1f\n",count/c);
printf("小于平均数的:%d",d);
return 0;
}
int main()
{
int a[5]={0};
for (int i = 0; i < 5; i++)
{
printf("Enter Number : ");
scanf("%d",&a[i]);
}
for (int i = 0; i < 5; i++)
{
printf("%d ",a[i]);
}
printf("\n");
for (int i = 0,j = 4; i < j; i++,j--)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
for (int i = 0; i < 5; i++)
{
printf("%d ",a[i]);
}
}
int main()
{
srand(time(NULL));
int b[5];
for (int i = 0; i < 5; i++)
{
printf("Enter a number: ");
scanf("%d", &b[i]);
}
for (int i = 0; i < 5; i++)
{
int a = rand() % 5;
int temp = b[i];
b[i] = b[a];
b[a] = temp;
}
for (int i = 0; i < 5; i++)
{
printf("%d ", b[i]);
}
}
常见算法
- 基本查找
- 二分查找
- 插值查找
- 分块查找(以下全了解)
- 哈希查找
- 树表查找
- 斐波那契查找
基本查找:
int main()
{
int b[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
{
if (b[i]==3)
{
printf("Yes");
break;
}
if (i == 4)
{
printf("No\n");
}
}
}
二分查找
#必须是有顺序的一组数,不论从大到小还是从小到大
int a();
int main()
{
int arr[8] = {2,12,354,4567,7544,7777,8888,99888};
int num = 0;
int len = sizeof(arr) / sizeof(arr[0]);
printf("Enter");
scanf("%d",&num);
int index = a(arr,len,num);
printf("%d",index);
}
int a(int arr[], int len, int num)
{
int max = len -1;
int min = 0;
while(min <= max)
{
int mid = (max+min)/2;
if(arr[mid] < num)
{
min = mid + 1;
}
else if (arr[mid] > num)
{
max = mid -1;
}
else
{
return arr[mid];
}
}
return -1;
}
插值查找(二分查找改进)
$mid = min + (key-arr[min]) / (arr[max] - arr[min]) * (max - min)$
$mid = min + \frac{key-arr[min]}{arr[max]-arr[min]}*(max -min)$
#比二分查找更严格的要求,最好每个数均匀点,如果不满足,反而更慢
..............
你以为我会写
那是不可能的
分块查找
- 原则1:前一块中的最大数据,小于后一块中所有的数据(块内无序,块外有序)
- 原则2:块数量一般等于数字的个数开根号。比如16个数字一般分为4块左右。
- 核心思路:先确定要查找的元素在哪一块,然后在块内挨个查找。
其他不管
排序算法
冒泡排序
- 相邻俩数据比较,小的放前,大的放后(从小到大,可以改)
int main()
{
int arr[9] = {3,1,5,4,23,53,11,2,12};
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i < len-1; i++)
{
for (int j = 0; j < len-1-i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for (int i = 0; i < len ; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
选择排序
int main()
{
int arr[9] = {3,1,5,4,23,53,11,2,12};
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i < len-1; i++)
{
for (int j = i + 1; j < len; j++)
{
if (arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
for (int i = 0; i < len ; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
指针
格式:数据类型 * 变量名
int main(){
int a = 10;
int *p = &a;
double b = 19;
double * p = &b;
}
作用:
1.操作其他函数中的变量
2.函数返回多个值
3.函数的结果和计算状态分开
4.方便的操作数组和函数
int swap();
int main()
{
int a = 12;
int b = 10;
swap(&a,&b);
printf("a=%d, b=%d\n",a,b);
return 0;
}
int swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
return 0;
}
指针细节
函数中变量的生命周期跟函数相关,函数结束了,变量也会消失
此时在其他函数中,就不发通过指针使用了
如果不想函数中的变量被回收,可以在变量前面加static关键字
int * p(){
static int a = 10;
return &a;
}
int main(){
int *a = p();
printf("%d",a);
}
#求最大最小值
void px(int *max,int *min,int len,int a[])
{
*max = a[0];
*min = a[0];
for(int i=1;i<len;i++)
{
if(a[i]>*max)
{
*max = a[i];
}
if(a[i]<*min)
{
*min = a[i];
}
}
printf("%d\n",*max);
printf("%d",*min);
}
int main()
{
int a[10] = {1,0,112231,4,5,6,7,8,9};
int len = sizeof(a) / sizeof(a[0]);
int max = 0,min = 0;
px(&max,&min,len,a);
}
#定义一个函数,将两数相除,取余数
int a1(int *a,int *b,int *res)
{
if (*b == 0)
{
return 1;
}
*res = *a % *b;
return 0;
}
int main()
{
int a11 = 0;
int b11 = 0;
int res = 0;
int *a12 = &a11;
int *b12 = &b11;
printf("enter:");
scanf("%d",a12);
printf("enter:");
scanf("%d",b12);
int flag = a1(a12,b12,&res);
if(flag == 1)
{
printf("no");
}
else
{
printf("%d",res);
}
}
指针高级
指针的计算
-
有意义的操作:
指针跟整数进行加减操作(每次移动n个步长)
指针跟指针进行减操作
-
无意义的操作:
指针跟整数进行乘除操作。原因:指针指向不明
指针和指针进行加,乘除操作。
-
野指针:指向空间未分配
-
悬空指针:指向空间已分配,但被释放了
可以用来交换两个变量的数据
你以为我会写?
想多了。
- 指向指针的指针叫二级指针(可套娃)
数组指针
int main() {
int a[2][5] = {{1, 2, 3, 4, 5},{11,22,33,44,55}
};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", a[i][j]);
}
}
}
函数指针
#include <stdio.h>
int *j (int *a1, int *b1)
{
printf("%d\n", *a1 + *b1);
}
int *jj (int *a1, int *b1)
{
printf("%d\n", *a1 - *b1);
}
int *c (int *a1, int *b1)
{
printf("%d\n", *a1 * *b1);
}
int * cc (int *a1, int *b1)
{
if (*b1 == 0)
{
printf("error");
return NULL;
}
printf("%d\n", *a1 / *b1);
}
int main()
{
int a = 0;
int b = 0;
int c1 = 0;
int *p = &a;
int *p1 = &b;
printf("enter 1");
scanf("%d", &a);
printf("enter 2");
scanf("%d", &b);
printf("enter 3");
scanf("%d", &c1);
switch (c1)
{
case 1:
j(p, p1);
break;
case 2:
jj(p, p1);
break;
case 3:
c(p, p1);
break;
case 4:
cc(p,p1);
break;
default:
printf("error");
}
}
字符串
sb c语言没有字符串数据类型,可以用两种方式定义字符串
char str[4] = ["abc"] #eg:char str[4] = ['a','b','c',\0]
char* str = "abc"
- c语言中字符保存是以数组的形式保存的
#错误示例
#include <stdio.h>
int main()
{
char a[3] = "abc";
printf("%s\n", a);
}
- 指针定义的字符串不能修改,可以复用
int main()
{
char a[3] = "";
printf("Enter a string: ");
scanf("%s", a);
for (int i = 0; i < 3; i++)
{
printf("%c", a[i]);
}
}
-------------------------------------------------------------------------------------------------------------------
int main()
{
char str[100];
printf("Enter a string: ");
scanf("%s", str);
char* p = str;
while (*p != '\0')
{
printf("%c", *p);
p++;
}
}
- 自己去试
#include <stdio.h>
#include <string.h>
int main()
{
for (int i = 1; i <= 3;i++)
{
char user[100] = "admin";
char password[100] = "admin";
char new_user[100] = "";
char new_password[100] = "admin";
printf("enter username: ");
scanf("%s", new_user);
printf("enter password: ");
scanf("%s", new_password);
if (!strcmp(user, new_user) && !strcmp (password, new_password))
{
printf("you already exists\n");
return 0;
}
{
if (i == 3)
{
printf("you don't exists,bye\n");
return 0;
}
printf("you don't exists,you only %d\n",3-i);
}
}
}
int main()
{
char str[100];
printf("Enter a string: ");
scanf("%s", str);
int bigst = 0;
int smallst = 0;
int num = 0;
for (int i = 0; i < strlen(str);i++)
{
char c = str[i];
if (c >= '0' && c <= '9' )
{
num++;
}
else if (c >= 'A' && c <= 'Z')
{
bigst++;
}
else if (c >= 'a' && c <= 'z')
{
smallst++;
}
}
printf("The bigst is: %d\n", bigst);
printf("The smallst is: %d\n", smallst);
printf("The number is: %d", num);
return 0;
}
结构体
- 结构体可以理解为自定义的新的数据类型
- 他是由一批数据组合而成的结构型数据
- 里面每个数据都是结构体的成员
struct a {
char aa[100];
int b;
double sc;
};
struct a
{
char name[20];
int age;
};
int main()
{
struct a a = {"John", 20};
struct a b = {"John1", 201};
struct a c[3] = {a,b};
for (int i = 0; i < 2; i++)
{
printf("%s %d\n", c[i].name,c[i].age);
}
}
起别名
typedef struct{
int a;
char b[1];
}ss;
typedef struct node
{
char name[100];
int age;
int height;
int weight;
} ss;
int main()
{
ss a = {"John", 20,12,21};
ss b = {"Doe", 30,12,3,};
ss c = {"Doe", 40,23,12};
ss d[3] = {a,b,c};
for (int i = 0; i < 3; i++)
{
printf("%s %d\n", d[i].name, d[i].age);
}
}
结构体作为函数的参数
typedef struct student
{
char name[20];
int age;
}s;
void met(s* aa)
{
printf("%s\t%d\n",aa->name,aa->age);
printf("enter:");
scanf("%s",aa->name);
printf("enter:");
scanf("%d",&(aa->age));
printf("%s\t%d\n",aa->name,aa->age);
}
int main()
{
s stu;
strcpy(stu.name,"John");
stu.age = 18;
printf("student name:%s\n",stu.name);
met(&stu);
printf("student age and name:%d %s\n",stu.age,stu.name);
}
结构体嵌套
struct Message
{
char mail[200];
char phone[100];
};
struct student
{
char name[20];
int age;
char gender;
double height;
struct Message ms;
};
int main()
{
struct student s;
strcpy(s.name,"zhang");
s.age=20;
s.gender='m';
s.height=1.33;
strcpy(s.ms.phone,"1145134");
strcpy(s.ms.mail,"sadkfjklas");
printf("name:%s\n",s.name);
printf("age:%d\n",s.age);
printf("gender:%c\n",s.gender);
printf("height:%f\n",s.height);
printf("phone:%s\n",s.ms.phone);
printf("mail:%s\n",s.ms.mail);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct node{
char name[50];
int count;
};
int main()
{
struct node a[4] = {{"A",0},{"B",0},{"C",0},{"D",0}};
srand(time(NULL));
for (int i = 0; i < 80; i++)
{
int choose = rand() % 4;
a[choose].count++;
}
int max = a[0].count;
for (int i = 0; i < 4; i++)
{
if (a[i].count > max)
{
max = a[i].count;
}
}
for (int i = 0; i < 4; i++)
{
if (a[i].count == max)
{
printf("%s is %d times\n", a[i].name, a[i].count);
}
}
printf("\n");
for (int i = 0; i < 4; i++)
{
struct node t = a[i];
printf("%s %d\n",t.name,t.count);
}
}
结构体内存对齐
共同体
- 一种数据可能又多个数据类型
union Money{
double mond;
int mons;
char mod[100];
}
int main(){
union Money m;
m.mod = "100w";
printf("%s\n",m.mod);
}
共用体的特点
- 共用体,也叫联合体,共同体
- 所有的变量都是用同一个内存空间
- 所占的内存大小 = 最大成员的长度(也受内存影响)
- 每次只能给一个变量进行赋值,, 因为第二次赋值会覆盖原有数据(也受内存对齐影响)
结构体和共用体的区别
-
一种事物中包含多个属性
-
一个数据包含多个类型
存储方式:
- 结构体:各存各的
- 共用体:存一起,多次存会覆盖
内存占用:
- 结构体:各变量总和(受内存对齐影响)
- 共用体:最大类型(受内存对齐影响)
动态内存分配
函数名 | 作用 |
---|---|
malloc | 申请连续的空间 |
calloc | 申请连续的空间 + 初始化 |
realloc | 修改空间大小 |
free | 释放空间 |
#include <stdio.h>
#include <stdlib.h>
int main(){
int* p = malloc(100 * sizeof(int));
for (int i = 0;i<100;i++){
*(p+i) = (i + 1)*10;
printf("%d\n",*(p+i));
}
for (int i = 0;i<100;i++){
p[i] = (i + 1)*10;
printf("%d\n",*(p+i));
}
free(p);
}
c语言内存结构
- 函数进栈,变量随之存在,函数退栈,变量随之消失
文件
- 相对路径
- 绝对路径
读取文件
- 打开文件:fopen
- 读取数据:fgetc fgets fread
- 关闭文件:fclose
int main()
{
FILE* file = fopen("D:\\Code_python\\1.txt","r");
int c ;
while ((c = fgetc(file))!= EOF)
{
printf("%c",c);
}
fclose(file);
}
使用
fgetc
函数从文件流中读取字符时,文件流的内部指针会自动向前移动到下一个字符的位置。这意味着每次调用fgetc
时,它都会从当前文件流指针的位置读取字符,并将文件流指针移动到下一个字符。这个过程是自动的,不需要程序员显式地进行指针操作
int main()
{
FILE* file = fopen("D:\\Code_python\\1.txt","r");
char c[1024];
char* str;
while ((str = fgets(c,1024,file)) != NULL)
{
printf("%s",c);
}
fclose(file);
}
int main()
{
FILE* file = fopen("D:\\Code_python\\1.txt","r");
char c[1024];
fread(c,sizeof(char),1024,file);
printf("%s",c);
fclose(file);
}
写数据
FILE* file = fopen("D:\\Code_python\\1.txt","w");
int c = fputc(12,file);
printf("%d",c);
int main()
{
FILE* file = fopen("D:\\Code_python\\1.txt","w");
int d = fputs("hello",file);
printf("%d",d);
fclose(file);
}
int main()
{
FILE* file = fopen("D:\\Code_python\\1.txt","w");
char a[1024] = {"helloworld"};
int a1 = fwrite(a,sizeof(a),1,file);
printf("%d",a1);
fclose(file);
}
读写模式
模式 | 描述 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
#include <stdio.h>
int main()
{
FILE* file = fopen("D:\\a\\python杂笔.pdf","rb");
FILE* file2 = fopen("D:\\a\\python杂笔11.pdf","wb");
char c[1024];
int n;
while((n = fread(c,sizeof(char),1024,file)) != 0)
{
fwrite(c,sizeof(char),n,file2);
}
fclose(file);
fclose(file2);
}