标准C语言10

标准C语言

结构struct

结构是一种由程序员自己设计的数据类型,用于描述一个事物的各项特征数据,由若干个不同的基础类型组成

设计:

struct 结构类型名
{

  类型 成员名1;

  类型 成员名2;

  ...

};


定义结构变量:

struct 结构类型名 结构变量名

注意:struct在C语言中,定义结构变量时不能省略

定义结构变量并初始化:

struct 结构类型名 结构变量名 = {v1,v2,v3…};

​ 初始化顺序一定要与成员顺序一致

struct 结构类型名 结构变量名 = {.成员名2=v2,.成员名1=v1,…};

​ 只初始化某些成员,顺序无须一致

注意:同类型的结构变量可以直接给另一个结构变量初始化

注意:这种种赋值方式只能在定义时使用

访问成员:

结构变量名.成员名;

​ 由于结构变量的字节数一般都比较大,普通的值传递效率非常大,因此传递结构变量的地址,也即是传递结构指针变量,此时想要通过结构指针变量访问成员时借助->,如果不需要修改指针变量的成员值,可以使用const保护

结构指针变量名->成员名;

typedef重定义结构类型名:

typedef struct  结构类型名 结构类型名;

typedef struct 结构类型名

{





}结构类型名;

​ 之后定义结构变量,可以不加struct

如何计算结构体的总字节数

​ 结构成员顺序会影响它的总字节数,如果能够在设计结构体时合理地安排成员顺序,可以大大地节约内存

内存对齐:

​ 假设第一个成员从零地址开始,存储每个成员的地址编号必须能被该成员的类型字节数整除,如果

不能整除则填充空白字节

内存补齐:

​ 结构体的总字节数,必须是它最大成员字节数的整数倍,如果不能整除,则在末尾补充空白字节

在Linux系统下计算结构体的对齐和补齐时,如果成员的字节数超过4,则按照4字节计算对齐和补齐

windows是按实际字节数对齐补齐

联合union

联合与结构使用方法基本一致,与结构的区别是联合的所有成员共用一
块内存,一个成员的值发生改变 ,其他成员也随之改变

联合的效果就是使用少量的内存对应多个标识符,以此达到节约内存的目的,但是现在几乎不使用

union Data

{
 char ch[5];   0~4
 int num;     0~3
}

sizeof(union Data) == 8

注意:计算联合的总字节数时,不需要考虑内存对齐,但是需要考虑内存补齐

如何判断系统的大小端?

假设十六进制 0x01020304 存储在以0x0A~0x0D范围内的4字节内存中

大端系统: 高位数据存储在低位地址,低位数据存储在高位地址

(0x0D:0x04 0x0C:0x03 0x0B:0x02 0x0A:0x01)

小端系统: 高位数据存储在高位地址,低位数据存储在低位地址

(0x0D:0x01 0x0C:0x02 0x0B:0x03 0x0A:0x04)

个人计算器一般都是小端系统,而UNIX服务器和网络设备都是大端,网络字节序也是大端模式的数据,本地字节序就是小端模式的数据

​ 序列化和反序列化

枚举enum

枚举就是一种数据类型,把可能出现的所有值罗列出来,并起一个有意义的名字表示这些值,除此之外给该类型的变

量赋其他值,是非法的(愿望)

枚举可以看做一种值受限的int类型,但是C编译器为了效率不检查,所以在C语言中枚举就相当于int类型变量

如果不给成员值,那么枚举中的值第一个默认从0开始,逐渐+1,如果设置了某个值,后面的成员在它的基础上逐渐+1

为什么要使用枚举:

​ 为无意义的值取一个有意义的名字,提高了代码的可读性,提高安全性(比变量更安全)(锦上添花)

文件

文件的分类:

文本文件: 存储的ASCII码的二进制 ‘2’ ‘5’ ‘5’ 50 53 53

二进制文件:存储的是数据的补码 255 1111 1111

文件IO:

FILE *fopen(const char *path, const char *mode);

功能: 打开或者创建文件

path: 文件的路径

mode: 文件打开模式

r 以只读权限打开文件,如果不存在则打开失败

r+ 在r的基础上,增加写权限

w 以只写权限打开文件,如果存在则清空打开,不存在则新建文件

w+ 在w的基础上,增加读权限

a 以只写权限打开文件,如果存在则在末尾追加,不存在则新建

a+ 在a的基础上,增加读权限

返回值: 文件指针,不需要关心里面有什么数据,只需要知道它是一个针对已打开文件的凭证,如果打开失败会返回NULL

二进制方式读写:

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

功能: 把内存中的数据写入到文件中

ptr: 待写入的内存的首地址

size: 一次写入的字节数

nmemb: 写入的次数

stream: 文件指针,fopen的返回值,表示往哪个文件写入数据

返回值: 成功写入的次数

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能: 从文件读取数据到内存中

ptr: 接收文件数据的内存首地址

size: 一次读取多少字节

nmemb: 读取多少次

stream: 表示往哪个文件读取

返回值: 成功读取到次数

文本方式读写文件:

int fprintf(FILE *stream, const char *format, ...);

功能: 以文本形式写入数据到文件中

stream: 要写入的文件

format: 占位符和提示信息

…: 变量名列表

返回值: 成功写入的字节数

int fscanf(FILE *stream, const char *format, ...);

功能: 从文件中读取数据到变量中

stream: 要读取的文件

format: 占位符(数据格式)

…: 变量地址列表

返回值: 成功读取的变量个数,不成功则返回EOF(-1)

关闭文件

int fclose(FILE *stream);

功能: 关闭一个打开文件

返回值: 成功返回0,失败返回-1

注意: 如果需要立即修改文件的内容,最好先关闭文件

文件位置指针:

​ 每个通过fopen打开的文件都有一个文件位置指针来记录着接下来要读写的位置,以r、r+、w、w+打开文件,位置指针在文件的开头,以a a+打开文件,位置指针自动在末尾

​ 如果想要随意读写文件的任意位置,那么可以通过手动设置文件位置指针的位置

int fseek(FILE *stream, long offset, int whence);

功能: 手动设置位置指针的位置

stream: 文件指针

offset: 偏移值 字节数

whence: 基础位置

SEEK_SET 文件开头

SEEK_CUR 当前位置

SEEK_END 文件末尾

返回值: 成功(调整后位置指针还在文件中)返回0,失败返回-1

void rewind(FILE *stream);

功能: 把文件位置指针设置到文件开头

long ftell(FILE *stream);

功能: 获取当前文件位置指针的位置

返回: 在第几个字节

int fgetc(FILE *stream);

功能: 从文件中读取一个字符

返回值: 失败、读取完毕返回EOF(-1)

char *fgets(char *s, int size, FILE *stream);

功能: 读取一行字符串到s中,最多读size-1个

int fputc(int c, FILE *stream);

功能: 写入一个字符到文件中

返回值: 成功返回非负整数,失败返回-1

int fputs(const char *s, FILE *stream);

功能: 写入一个字符串到文件中

返回值: 成功返回非负整数,失败返回-1

int remove(const char *pathname);

功能: 删除文件

pathname: 文件路径

返回值: 成功返回0,失败返回-1

int rename(const char *oldpath, const char *newpath);

功能: 重命名文件

返回值: 成功返回0,失败返回-1

命令行参数

main函数的参数

int main(int argc,const char* argv[])

是为了获取./a.out 命令行中的参数

argc 代表了命令行参数的个数

argv 每个参数字符串的首地址

注意: ./a.out是argv[0]

实现linux中cp命令

cp dest src

#include <stdio.h>

int main(int argc,const char* argv[])
{
    if(3!=argc)
    {
        printf("User:./CP dest src\n");
        return 0;
    }

    FILE *dest = fopen(argv[1],"r");
    if(NULL == dest)
    {
        printf("源文件不存在,请检查命令\n");
        return 0;
    }

    FILE *src = fopen(argv[2],"r");
    if(src)
    {
        printf("目标文件已存在,是否覆盖(y\\n)?");
        char cmd = getchar();
        if('y'!= cmd && 'Y'!= cmd)
        {
            printf("停止拷贝\n");
            return 0;
        }
        fclose(src);
    }
    src = fopen(argv[2],"w");
    if(NULL == src)
    {
        printf("文件路径权限有误,请检查\n");
        return 0;
    }
    char buf[256]={};
    int ret = 0;
	while(ret = fread(buf,1,256,dest))
	{
		fwrite(buf,1,ret,src);	
	}

	fclose(dest);
    fclose(src);
    dest = NULL;
    src  = NULL;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值