C语言学习
C语言学习
1.基础
常用头文件:
#include<stdio.h>//标准I/O库
#include<stdlib.h>//定义了EXIT_SUCCESS和EXIT_FAILURE符号
#include<string.h>
#include<math.h>
格式修饰符号:
printf("%ld %lf",a b);//l&L
printf("%5d",a);//5表示域宽,输出的宽度>=5
printf("%-5d",a);
printf("%05d",a);//前面会用0补齐
printf("%o",a);//以八进制打印一个整型值
printf("%x",a);//以十六进制形式打印一个整数值
如果函数scanf()的格式控制字符串中存在除格式说明符以外的其他字符,那么这些字符必须在输入数据时由用户从键盘原样输入
scanf("%c%*c%c%*c%d",&a,&b,&c);//%*c可以读取一个字符且不用指定变量
输入:
long long a;
double b;
scanf("%ld%lf",a,b);
while(~scanf("%d",&n)&&n!=0)//循环输入,且n不能等于0
{
printf("%d\n",n);
}
while((ch = getchar() != EOF &&ch != '\n'))
;
2.字符串
输入输出:
sb=getchar();//读入一个字符
putchar(a);
gets(s);//可以读入包含空格的
puts(s);
字符串操作:
strcpy(a,s);//把s字符串复制到a上,a会被全部覆盖
strcat(a,s);//把s连接到a上
3.数据
3.1数据类型
整形(int):4个字节
短整型(short):2个字节
长整型(long):4个字节
超长整型(long long):8个字节
字符型(char):1个字节
单精度浮点型(float):4个字节
双精度浮点型(double):8个字节
无符号类型:
unsigned int a = 5;
//在前面加上unsigned即可
3.2 链接属性
链接属性一共有三种,external,internal,none
3.3 static关键字
用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一直存在。
for(i=1;i<=5;i++)
{
static int m = 5;
m++;
printf("%d ",m);
}
//输出:6 7 8 9 10
4.语句
goto语句:跳转到指定位置
int i = 0;
min_next:
if(i < 5)
{
i++;
goto min_next;
}
printf("%d\n",i);
5.操作符和表达式
*是间接访问操作符,它与指针一起使用,用于访问指针所指向的值。
优先级:前面你懂
完整版:C和指针 P81
- <=
- ==/!=
- &&
- ||
- 赋值
7.函数
7.1外部函数和内部函数
如果在定义函数时省略extern,则默认为外部函数。可以被调用。需要调用此函数的其他文件中,需要对此函数作声明。加extern表示该函数“是在其他文件中定义的外部函数”。
8.指针
8.1基础
地址指向变量单元:将地址形象化地称为“指针”。
定义方式:类型名 *指针变量名,*在后面
定义指针变量时必须指定基类型,因为不同类型占得字节数不一样。
例子:
int *p=&a;//定义的时候就初始化
int *p;//定义了一个整型数据的指针
//表示*p产生的结果类型是int
p=&a;
int* a;//a被声明为类型为int*的指针。
int* b,c,d;//只有b是指针,别的是普通的int
int *b,*c,*d;//这样才是声明三个指针。
8.2引用指针变量
*p=1;//将整数1赋给p当前所指向的变量 如果p指向a a的值也会被改变 因为那个地址里的值已经被改变了(存储器里)
//交换两个值
void swap(int *p1,int *p2)//传入两个地址,所以值可以改变
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}
8.3通过指针引用数组
所谓数组元素的指针就是数组元素的地址。
int a[5]={1,2,3,4,5};
int *p;
p=&a[0];//等价于p=a;
p=p+1;//指向下一个元素
p--;//指向上一个元素
//++在前和在后的区别
int a[5]={1,3,5,7,9};
int *p=a;
//以下输出彼此独立
printf("%d\n",*p++);//1 取出p的数字再++ 因为在后 表达式本身还是原来
printf("%d\n",++*p);//2 类似上面
printf("%d\n",*(p++));//1 因为先取*p值,然后p才+1 这时候检查*p是3
printf("%d\n",*(++p));//3
数组名作为函数参数:
void fun(int arr[],int n)
{}
void fun(int *arr,int n)//两种写法一样
{}
8.4指向多维数组的指针
学不会,读个研究生先
8.5通过指针引用字符串
1.基础
char str[]="china";//名字str表示的是字符数组
printf("%c\n",*(str+7));//相当于调用str[7]
char *str="china";
char *str;
str="china";//与上面等价
*str="china";//错误,str就已经是地址
str=str+1;//数组名代表地址,但它是常量,不能改变
2.函数应用
例:
void copy_str(char from[],char to[]);
void copy_str(char *from,char *to);//字符型指针变量
注:
char *f="a=%d\n";
int a=10;
printf(f,a);//可以正常运行
8.6指向函数的指针
参数声明为const,这表示函数将不会修改函数调用者所传递的两个参数。
void rearrange(char *output,char const*input)
9.结构体
9.1基础
算结构体的大小直接算就行,用编译器测的不一定是对的。
注意C和C艹不一样,声明得加上struct
struct student a[N];
9.2结构体指针
struct node
{
int x,y;
}a[N];
struct node *p;
p=&a[1];
printf("%d %d\n",p->x,p->y);
printf("%d %d\n",(*p).x,(*p).y);//这俩输出的结果是一样的
//name是字符数组
p=(struct node *)a[1].name;
printf("%s\n",p);
用结构体变量和结构体变量的指针作函数参数
9.3共用体
使几个变量共享一段内存,都从同一地址开始。
引用方式类似结构体。
union data1
{
int i;
char ch;
float f;
}a,b,c;
union data1 a,b,c;//也可以直接定义
union data1 a={16};//初始化第一个成员
union data a={.ch='j'};//选择想初始化的成员,只能初始化一个成员
只能用一个成员。
9.4使用枚举类型
声明枚举类型enum开头。例如:
每一个枚举元素都代表一个整数,C语言编译定义时的顺序默认它们的值为0,1,2,3,4...在上面的定义中,sun的值自动设为0,mon为2.
enum weekday{sun,mon,tue,wed,thu,fri,sat};//声明一个枚举类型weekday
enum weekday workday,weekend;//声明枚举变量
enum{sun,mon,tue,wed,thu,fri,sat} workday,weekend;//或者直接声明枚举变量,只能是其中一个的值
workday=mon;//赋值为1
enum weekday{sun=7,mon=1,tue,wed,thu,fri,sat}workday,weekend;
//可以人为指定值 tue自动为2,后面依次+1
9.7用typedef声明新类型名
typedef int Integer;//用法一样
typedef struct
{
int month,day,year;
}date;
date birth;//可以不用struct
typedef int Num[100];//声明Num为整型数组类型名
Num a;//定义a为整型数组名,它有100个元素
typedef char *ptr_to_char;//把ptr_to_char声明为一个指向字符的指针
ptr_to_char a;
a = "hello";
typedef long long ll;//就是起个别名
与define的区别:define是在预编译的时候处理的,只是简单的字符串替换,typedef是在编译阶段处理的。
10.文件
10.1基础
FILE f1;//file类型的变量
FILE *fp;//指向file型数据的指针变量
10.2fopen和fclose
fopen的返回值是指向a1文件的指针
FILE *fp;
fp=fopen("a1","r");//fopen(文件名,使用文件方式);
if((fp=fopen("a1","r"))==NULL)//常用方式
{
printf("error\n");
exit(0);
}
使用文件方式:r:只读
w:只写 r+:读写
a 为续写数据打开文本文件,原有内容得以保留
fclose用法:fclose(文件指针);
如果不关闭文件就结束程序运行将会丢失数据。
10.3读写数据文件
fgetc(fp);//从fp指向文件读入一个字符 失败返回EOF(-1)
fputc(ch,fp);//把字符ch(变量)写入文件 失败返回EOF(-1)
示例程序:(已经测试通过)
需求:
- 输入输入文件和输出文件的名字操作文件
- 在遇到结束标志之前,把输入文件的字符输出到输出文件中,并显示在屏幕上
# include<stdio.h>
# include <stdlib.h>
int main()
{
FILE *in,*out ;
char ch,infile[10],outfile[10];
printf("输入读入文件的名字:");
scanf("%s",infile);
printf("输入输出文件的名字:");
scanf("%s",outfile);
if((in=fopen(infile,"r"))==NULL)//注意可以通过输入指定文件名
{
printf("无法打开此文件\n");
exit(0);
}
if((out=fopen(outfile,"w"))==NULL)
{
printf("无法打开此文件\n");
exit(0);
}
ch=fgetc(in);//读入一个字符
while(!feof(in))//没有遇到结束标志 可以改为ch!=-1或ch!=EOF
{
fputc(ch,out);
putchar(ch);
ch=fgetc(in);
}
putchar(10);
fclose(in);
fclose(out);
return 0;
}
/*测试数据:
wlq.txt
wlq2.txt
返回结果:
(文件里的内容,同时第一个文件的数据会被写入第二个文件)
*/
读写字符串:
fgets(str,n,fp);
//读成功 返回地址str 失败返回NULL
//fp指向的文件读入一个长度为(n-1)的字符串,存放在str中
fputs(str,fp);
//输出成功返回0 不成功返回非零值
//写入...
用格式化方式读写文本文件:
fprintf(文件指针,格式字符串,输出表列);
fscanf(文件指针,格式字符串,输入表列);
fscanf(fp,"%d,%f",&i,&f);
fprintf(fp,"%d,%6.2f",i,f);
用二进制方式向文件读写一组数据
for(i=0;i<40;i++)
fread(&stud[i],sizeof(struct node),1,fp);
for(i=0;i<40;i++)
fwrite(&stud[i],sizeof(struct node),1,fp);
//里面的1指的是要读写一个数据项(每个数据项的长度为sizeof(struct node))
10.4随机读写数据文件
1.用rewind函数使文件位置标记指向文件开头。例子:
FILE *fp1;
rewind(fp1);
2.用fseek函数改变文件位置标记
fseek(文件类型指针,位移量,起始点);
起始点有三种:
文件开始位置:SEEK_SET或者0
文件当前位置:SEEK_CUR或者1
文件末尾位置:SEEK_END或者2
fseek(fp,100L,0);//文件标记向前移到离文件开头100个字节数
fseek(fp,50L,1);//文件位置标记向前移到离当前位置50个字节处
fseek(fp,-10L,2);//文件位置标记从文件末尾向后退10个字节
3.用ftell函数测定文件位置标记的当前位置
i=ftell(fp);
if(i==-1L)printf("error\n");//如果错误会返回-1L
10.5出错检测
如果调用各种输入输出函数出现了错误,除了函数返回值有所反映外,还可以用ferror函数检查。
ferror(fp);//返回0没出错 非零值出错
clearerr(fp);//
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现