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

  1. <=
  2. ==/!=
  3. &&
  4. ||
  5. 赋值

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)

示例程序:(已经测试通过)

需求:

  1. 输入输入文件和输出文件的名字操作文件
  2. 在遇到结束标志之前,把输入文件的字符输出到输出文件中,并显示在屏幕上
# 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);//
posted @   wlqtc  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示