知识点回顾

变量、数组、结构体都是存储数据的方式

结构体是一种变量的模板,相对于变量、它可以存储多项数据,相对于数组,结构体中成员的数据类型可以不同。

#include

#include

struct staff

{

char FullName[64];//一个汉字占用两个字节

char Gender;//字符型变量可以存储整数 1--男 2--女 char类型范围:-127~128

char ID[18];

};

/*

除了使用(struct 结构体名 变量名)这种方式声明结构体变量以外,

还可以使用typedef语句来基于结构体声明数据类型

这个语句的作用就是将结构体 Staff 定义为新的数据类型 STAFF

*/

typedef struct staff STAFF;

int main()

{

//定义完结构体后,就可以基于结构体 声明结构体变量

STAFF s;

//struct staff s;

s.Gender = 1; //为结构体成员变量赋值

scanf("%s", s.FullName);

printf("%s\r\n", s.FullName);

return 0;

}

通过结构体将多个不同类型的数据结构成员整合在一起,可以方便的多项数据进项操作。

文件操作

在C语言中之前使用过的变量、数组都是存储在内存(RAM)中的,这些数据所占用的内存在程序结束以后会被操作系统回收,内存中的数也就会随之丢失。因此我们就需要将数据保存到外部存储器上(通常指硬盘),方便其下次使用。

在一些较为底层的语言里,你可以直接访问硬盘的某个扇区并进行数读写,但这种返回时除了效率比较低外还存在较大的安全隐患,不恰当的磁盘访问可能会引起严重的故障,比如操作系统崩溃或数丢失。所以这种方式是不推荐的。

因此我们就需要通过文件来访问磁盘上的数据,文件系统由操作系统管理,程序员通过这种操作系统可以间接地访问磁盘上地数据,不恰当地访问就可能会被操作系统阻止(例如文件被其它程序占用、或者程序没有访问这个文件的权限),这样一来就会安全得多,同时操作系统也会采取一些机制来提高文件的访问效率。

使用fopen()函数

fopen()函数可以打开或创建文件,想要将数据存储到磁盘上,首先我们就需要在磁盘上创建一个文件;如果这个文件已经创建,那么我们就需要打开它即可(可以直接打开,也可以进行覆盖,具体操作取决于你打开文件的方式)。在C语言中创建和打开文件都使用一个函数,fopen()函数,该函数的原型为:

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

/*

该函数的2个参数都是字符串常量

参数1:要打开或创建文件的具体路径

参数2:打开或创建文件的具体方式

*/

使用fwrite()函数将读取到对应货币的数据写入到指定路径的文件中:

#include

#include

#pragma comment(lib, "D:/CR37/Data/libs/BOCRates/BOCRates.lib")

int main()

{

ExchangeRate r; //定义一个结构体变量

//使用ReadBOCRatesByCode函数读取指定货币对应的值到 &r 所指向的结构体中

ReadBOCRatesByCode("USD", &r);

//以二进制形式打开或创建指定路径下的Rates.txt文件

FILE* fp = fopen("D:\\CR37\\Data\\Rates.txt", "wb");

//做判断

if (fp == NULL)

{

printf("文件打开失败!\r\n");

}

else

{

printf("文件打开成功,文件的信息存储在一个结构体中,指针fp指向了这个结构体\r\n");

//将内存中&r地址中的数据值 读取sizeof(ExchangeRate)大小的字节 保存到fp指向的文件内

fwrite(&r, sizeof(ExchangeRate), 1, fp);

//使用后要记得关闭文件

fclose(fp);

}

return 0;

}

使用fread()函数将指定路径的文件中的数据读出来:

#include

#include

#pragma comment(lib, "D:/CR37/Data/libs/BOCRates/BOCRates.lib")

int main()

{

//定义一个结构体变量

ExchangeRate r;

//以只读的方式打开对应路径下的文件

FILE* fp = fopen("D:\\CR37\\Data\\Rates.txt", "r");

//从fp 指向的位置 读取sizeof(ExchangeRate)字节的数据 送到&r所指向的位置

fread(&r, sizeof(ExchangeRate), 1, fp);

//打印对应的值

printf("%s\t", r.CurrencyCode);

printf("%s\t", r.CurrencyName);

printf("%s\t", r.PublishTime);

printf("%f\t", r.BuyingRate);

printf("%f\t", r.SellingRate);

printf("%f\t", r.CashBuyingRate);

printf("%f\t", r.CashSellingRate);

printf("%f\t\n", r.MiddleRate);

fclose(fp);

return 0;

}

程序运行的结果:

通过自定义函数实现和main()中相同的功能

避免main()函数中的语句过于繁琐,更具有模块化,以及程序的可修改性,所以我们需要进行自定义函数,实现文件写入和读取操作等功能:

1、写入(保存)函数:int SaveRates(ExchangeRate r);

2、读取函数:void LoadRatesFromFile(ExchangeRate* r);

3、显示数据:void DisplayRates(ExchangeRate r);

Visual 1:

#include

#include

#pragma comment(lib, "D:/CR37/Data/libs/BOCRates/BOCRates.lib")

/*

在联网的基础上将从API上读取指定货币的数据保存到磁盘上

在保存数据时,只需要将结构体变量的值传递进去就可以了,此时无需使用指针

*/

int SaveRates(ExchangeRate r)

{

FILE* fp = fopen("D:\\CR37\\Data\\Rates.txt", "wb");

if (fp == NULL)

{

printf("文件打开失败!\r\n");

return -1;

}

else

{

printf("文件打开成功!文件的信息存储在一个结构体中,指针指向了这个结构体\r\n");

fwrite(&r, sizeof(ExchangeRate), 1, fp);

fclose(fp);

return 0;

}

}

/*

这里传递结构体变量指针是因为要从磁盘中读取已保存的数据

*/

void LoadRatesFromFile(ExchangeRate* r)

{

FILE* fp = fopen("D:\\CR37\\Data\\Rates.txt", "r");

fread(r, sizeof(ExchangeRate), 1, fp);

fclose(fp);

}

//输出结构体成员对应的数值

void DispalyRates(ExchangeRate r)

{

printf("%s\t", r.CurrencyCode);

printf("%s\t", r.CurrencyName);

printf("%s\t", r.PublishTime);

printf("%f\t", r.BuyingRate);

printf("%f\t", r.SellingRate);

printf("%f\t", r.CashBuyingRate);

printf("%f\t", r.CashSellingRate);

printf("%f\t\n", r.MiddleRate);

}

int main()

{

//声明一个结构体变量

ExchangeRate r;

//调用ReadBOCRatesCode()函数,获取指定货币的数据

ReadBOCRatesByCode("JPY", &r);

//将其获取指定货币的数据保存到指定路径的文件内

SaveRates(r);

//调用LoadRatesFromFile()函数将指定路径的文件内的数据读取出来到对应的结构体成员中

LoadRatesFromFile(&r);

//调用DispalyRates()函数,打印对应的结构体成员的数值

DispalyRates(r);

return 0;

}

Visual 2:

#include

#include

#pragma comment(lib, "D:/CR37/Data/libs/BOCRates/BOCRates.lib")

/*

在联网的基础上将从API上读取指定货币的数据保存到磁盘上

在保存数据时,只需要将结构体变量的值传递进去就可以了,此时无需使用指针

*/

int SaveRates(ExchangeRate r)

{

FILE* fp = fopen("D:\\CR37\\Data\\Rates.txt", "wb");

if (fp == NULL)

{

printf("文件打开失败!\r\n");

return -1;

}

else

{

printf("文件打开成功!文件的信息存储在一个结构体中,指针指向了这个结构体\r\n");

fwrite(&r, sizeof(ExchangeRate), 1, fp);

fclose(fp);

return 0;

}

}

/*

这里传递结构体变量指针是因为要从磁盘中读取已保存的数据

*/

void LoadRatesFromFile(ExchangeRate* r)

{

FILE* fp = fopen("D:\\CR37\\Data\\Rates.txt", "r");

fread(r, sizeof(ExchangeRate), 1, fp);

fclose(fp);

printf("\r\n");

}

//输出结构体成员对应的数值

void DispalyRates(ExchangeRate r)

{

printf("%s\t", r.CurrencyCode);

printf("%s\t", r.CurrencyName);

printf("%s\t", r.PublishTime);

printf("%f\t", r.BuyingRate);

printf("%f\t", r.SellingRate);

printf("%f\t", r.CashBuyingRate);

printf("%f\t", r.CashSellingRate);

printf("%f\t\r\n", r.MiddleRate);

}

int main()

{

//声明一个结构体变量

ExchangeRate rates;

if (ReadBOCRatesByCode("JPY", &rates) == 1)

{

//条件为真,将读取到的对应数值保存到指定路径文件内

SaveRates(rates);

}

else

{

//如果上面的条件失败,就把本地保存的数读取出来

LoadRatesFromFile(&rates);

}

DispalyRates(rates);

return 0;

}

程序运行结果:

使用文件操作打印BMP格式的图片

说明

现在使用的图片主要为位图和矢量图:

矢量图形:是计算机图形学中用点、直线或者多边形等基于数学方程的几何图元表示图像。矢量图形与使用像素表示图像的位图不同。

位图(Bitmap):又称栅格图(英语:Raster graphics)或点阵图,是使用像素阵列(Pixel-array/Dot-matrix点阵)来表示的图像。

转换.bmp格式

需要提前将.png、.jpg等格式的图片通过画图工具转换成.bmp,转换的文件类型需要为24位位图,如下图所示:

位图(.bmp格式)图片的字节数计算方法:

使用WinHex工具以十六进制的方式查看.bmp图,可以看出第一、二字节所表示的字符分别为:‘B‘、‘M‘

代码实现

Visual 1:读取图片信息

#include

int main()

{

FILE* fp = fopen("D:\\CR37\\Data\\imgs\\computer1.bmp","rb");

char tag[2];//定义一个字符数组

fread(tag, 2, 1, fp);//字符数组的名称可以隐式的转换成数组的首地址,参数1无需添 加 & 运算符

if (tag[0] != 'B' || tag[1] != 'M')

{

printf("这张图片不是一张\".bmp\"图片!\r\n");

return -1;

}

else

{

printf("这张图片是一张\".bmp\"图片!\r\n");

}

//输出图片文件的字节大小

//BMPd文件的第3~6字节保存了图片的字节数

int filesize = 0;

fread(&filesize, 4, 1, fp);

printf("这张图片的字节大小为:%d 字节\r\n", filesize);

fclose(fp);

return 0;

}

程序运行结果:

BMP文件头信息头的结构体定义:

//header C结构体

typedef struct {

unsigned short int type; //文件格式 占用2Bytes,必须为"BM"

unsigned int size; //文件大小,占用4字节

unsigned short int reserved1, reserved2; //保留区 默认设置为0

unsigned int offset;//文件头到图像数据信息偏移字节数

} HEADER;

//infoheader 结构体

typedef struct {

unsigned int size; //文件部分size大小

int width; //图像宽

int height; //图像高

unsigned short int planes; // 位面数 总为1

unsigned short int bits; //素位深

unsigned int compression; //缩类型

unsigned int imagesize; //像大小(字节)

int xresolution,yresolution; //率(水平,垂直

unsigned int ncolours; //所用颜色索引数目

unsigned int importantcolours; //像显示有重要影响的颜色索引数

} INFOHEADER;

Visual 2:定于结构体,获取BMP图片的一些信息

#include

#include

#include

/*

BMP头文件54字节的结构体声明

使用typedef()为struct BitMapHeader结构体定义别名:BIT_MAP_HEADER

*/

typedef struct BitMapHeader

{

long Size;//文件大小

short Reserved1;//保留字,不考虑

short Reserved2;//保留字,同上

long OffBits;//实际位图数据的偏移字节数,即前三个部分长度之和

}BIT_MAP_HEADER;

/*

BMP信息头,也是一个结构体,其定义了BMP图片的具体参数信息

使用typedef()为struct BitMapInfo结构体定义别名:BIT_MAP_INFO

*/

typedef struct BitMapInfo

{

long Size;//指定此结构体的长度,为40

long Width;//位图宽

long Height;//位图高

short Planes;//平面数,为1

short BitCount;//采用颜色位数,可以是1,2,4,8,16,24,新的可以是32

long Compression;//压缩方式,可以是0,1,2,其中0表示不压缩

long SizeImage;//实际位图数据占用的字节数

long XPelsPerMeter;//X方向分辨率

long YPelsPerMeter;//Y方向分辨率

long ClrUsed;//使用的颜色数,如果为0,则表示默认值(2^颜色位数)

long ClrImportant;//重要颜色数,如果为0,则表示所有颜色都是重要的

}BIT_MAP_INFO;

int main()

{

FILE* fp = fopen("D:\\CR37\\Data\\imgs\\computer1.bmp","rb");

char tag[2];//定义一个字符数组

fread(tag, 2, 1, fp);//字符数组的名称可以隐式的转换成数组的首地址,参数1无需添 加 & 运算符

if (tag[0] != 'B' || tag[1] != 'M')

{

printf("这张图片不是一张\".bmp\"图片!\r\n");

return -1;

}

else

{

printf("这张图片是一张\".bmp\"图片!\r\n");

//为BMP头文件结构体声明变量

BIT_MAP_HEADER bmpHeader;

fread(&bmpHeader, sizeof(bmpHeader), 1, fp);

//为BMP信息头结构体声明变量

BIT_MAP_INFO bmpInfo;

fread(&bmpInfo, sizeof(bmpInfo), 1, fp);

printf("这张BMP图片的宽度为:%d\r\n", bmpInfo.Width);

printf("这张BMP图片的高度为:%d\r\n", bmpInfo.height);

}

fclose(fp);

return 0;

}

程序运行结果:

根据上面使用结构体获取的BMP图片信息,使用initgraph()函数就可以初始化一个对应大小像素的窗口

initgraph(bmpInfo.Width, bmpInfo.Height);

_getch();

运行结果如下:

给初始化的绘图窗口填充颜色:

initgraph(bmpInfo.Width, bmpInfo.Height);

for (int x = 0; x <= bmpInfo.Width; x++)

{

for (int y = 0; y <= bmpInfo.Height; y++)

{

putpixel(x, y, RGB(0, 0, 255));

}

}

程序运行结果:

从fp读取对应像素点的RGB数值:

initgraph(bmpInfo.Width, bmpInfo.Height);

//位图每个像素点的RGB值占用3个字节

char data[3];//存储像素点的RGB值

for (int x = 0; x <= bmpInfo.Width; x++)

{

for (int y = 0; y <= bmpInfo.Height; y++)

{

//从fp读取数据到data里

fread(data, 3, 1, fp);

//字符型数据可以转换成整型

int r = data[0];

int g = data[1];

int b = data[2];

putpixel(i, j, RGB(r, g, b));

}

}

程序运行结果(可以看出结果并不是我们想要的,多以找bug):

由于位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。所以需要更改循环条件:

initgraph(bmpInfo.Width, bmpInfo.Height);

//位图每个像素点的RGB值占用3个字节

char data[3];//存储像素点的RGB值

for (int y = bmpInfo.Height - 1; y >= 0; y--)

{

for (int x =0 ; x <= bmpInfo.Width -1; x++)

{

//从fp读取数据到data里

fread(data, 3, 1, fp);

//字符型数据可以转换成整型

int r = data[0];

int g = data[1];

int b = data[2];

putpixel(i, j, RGB(r, g, b));

}

}

程序运行结果:

还可以修改for()循环里的条件:

for (int y = bmpInfo.Height - 1; y >= 0; y--)

{

//修改这里的循环条件

for (int x =bmpInfo.Width -1 ; x >= 0; x--)

{

//从fp读取数据到data里

fread(data, 3, 1, fp);

//字符型数据可以转换成整型

int r = data[0];

int g = data[1];

int b = data[2];

putpixel(i, j, RGB(r, g, b));

}

}

程序运行结果:

Visual 3:完整代码

#include

#include

#include

/*

BMP头文件54字节的结构体声明

使用typedef()为struct BitMapHeader结构体定义别名:BIT_MAP_HEADER

*/

typedef struct BitMapHeader

{

long Size;//文件大小

short Reserved1;//保留字,不考虑

short Reserved2;//保留字,同上

long OffBits;//实际位图数据的偏移字节数,即前三个部分长度之和

}BIT_MAP_HEADER;

/*

BMP信息头,也是一个结构体,其定义了BMP图片的具体参数信息

使用typedef()为struct BitMapInfo结构体定义别名:BIT_MAP_INFO

*/

typedef struct BitMapInfo

{

long Size;//指定此结构体的长度,为40

long Width;//位图宽

long Height;//位图高

short Planes;//平面数,为1

short BitCount;//采用颜色位数,可以是1,2,4,8,16,24,新的可以是32

long Compression;//压缩方式,可以是0,1,2,其中0表示不压缩

long SizeImage;//实际位图数据占用的字节数

long XPelsPerMeter;//X方向分辨率

long YPelsPerMeter;//Y方向分辨率

long ClrUsed;//使用的颜色数,如果为0,则表示默认值(2^颜色位数)

long ClrImportant;//重要颜色数,如果为0,则表示所有颜色都是重要的

}BIT_MAP_INFO;

int main()

{

FILE* fp = fopen("D:\\CR37\\Data\\imgs\\computer1.bmp","rb");

char tag[2];//定义一个字符数组

fread(tag, 2, 1, fp);//字符数组的名称可以隐式的转换成数组的首地址,参数1无需添 加 & 运算符

if (tag[0] != 'B' || tag[1] != 'M')

{

printf("这张图片不是一张\".bmp\"图片!\r\n");

return -1;

}

else

{

printf("这张图片是一张\".bmp\"图片!\r\n");

//为BMP头文件结构体声明变量

BIT_MAP_HEADER bmpHeader;

fread(&bmpHeader, sizeof(bmpHeader), 1, fp);

//为BMP信息头结构体声明变量

BIT_MAP_INFO bmpInfo;

fread(&bmpInfo, sizeof(bmpInfo), 1, fp);

initgraph(bmpInfo.Width, bmpInfo.Height);

//位图每个像素点的RGB值占用3个字节

char data[3];//存储像素点的RGB值

for (int y = bmpInfo.Height - 1; y >= 0; y--)

{

for (int x =0 ; x <= bmpInfo.Width -1; x++)

{

//从fp读取数据到data里

fread(data, 3, 1, fp);

//字符型数据可以转换成整型

int r = data[0];

int g = data[1];

int b = data[2];

putpixel(i, j, RGB(r, g, b));

_getch();

closegraph();

}

}

}

fclose(fp);

return 0;

}

原文:https://www.cnblogs.com/ileemi/p/12523893.html

c语言中double sper是什么意思啊,C语言的文件操作的使用相关推荐

  1. c语言中double sper是什么意思啊,C语言 怎么样定义日期

    偶尔会用到,老忘记怎么用. 把我保存的一个页面粘过来了,一起分享. --------------------------------------------- 1 time 时间,日期和本地化函数 点 ...

  2. C语言中double\float类型默认输出几位小数

    首先,吐槽一下,就这么几句话的事情,你就收费,真的不想说啥了~ 然后正文给大家分享一下小数点默认输出的位数 C语言中常用的小数有俩种类型: float  比特数32  有效数字 6~7 double  ...

  3. c语言中double的用法,c语言中double的用法

    c语言中double的用法 2020-06-04 目前,随着计算机在人们生活和工作中的普及,其教学研究地位也在逐渐提升.C语言是一种计算机程序设计语言,其具有高级语言和汇编语言的特点.下面小编就跟你们 ...

  4. c语言求字符ascii,C语言中ASCII码是什么意思? c语言怎么求字符的ascii码

    导航:网站首页 > C语言中ASCII码是什么意思? c语言怎么求字符的ascii码 C语言中ASCII码是什么意思? c语言怎么求字符的ascii码 相关问题: 匿名网友: 是一个字符表,一个 ...

  5. c语言while作用范围,c语言中while是什么意思啊? , c语言while循环的表达式

    导航:网站首页 > c语言中while是什么意思啊? , c语言while循环的表达式 c语言中while是什么意思啊? , c语言while循环的表达式 匿名网友: 事例程序:void mai ...

  6. c语言中char是多少字节,c语言中char_char c = \'\\1\' 十进制是多少_c语言char

    网友求助:c语言中char_char c = \"\\1\" 十进制是多少_c语言char 问题 最佳答案 推荐答案 char一般默认是1个字节的无符号整型,范围0~255.如果是 ...

  7. C语言程序设计double,C语言中double类型数据占字节数为

    1以下选项中,能用作数据常量的是________. A.o115 B.0118 C.115L D.1.5e1.5 2下列叙述中错误的是_______. A.一个C语言程序只能实现一种算法 B.一个C函 ...

  8. 在c语言中a 这条语句的作用,C语言复习第二章

    C语言第二章 C语言复习(第二章) 一.填空 1.若采用十进制数的表示形式,则077为( ),0111为( ),0xab为( ). 2.C语言中的标识符只能由3种字符组成,它们是( ).( )和( ) ...

  9. c语言中b的作用是什么意思,C语言中是什么意思?ab怎么理解?

    C语言中&是什么意思?a&b怎么理解?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C语言中& ...

最新文章

  1. Oracle 触发器(上)
  2. 拉力赛 (Standard IO)
  3. 开源 Web 应用最常见漏洞是 XSS 和 SQLI 漏洞
  4. 设计立方体类(求出立方体的面积和体积 分别用全局函数和成员函数判断两个立方体是否相等)
  5. freemark 时间比较
  6. 摩托罗拉移动员裁员重点是研发
  7. go reflect 取指针_Go的方法集详解
  8. java集合框架03
  9. torch nn.MaxPool2d
  10. SpringMVC架构
  11. [Laravel] mac下通过 homestead 搭建环境 到运行项目
  12. stata学习之空间权重矩阵制作
  13. echarts地图各种点位实现
  14. 什么是人工智能(AI)数据平台?
  15. 笔记本电脑频繁自动重启_电脑一直自动重启怎么办 电脑一直自动重启的原因和解决办法...
  16. 《彩虹屁》快夸夸我!彩虹屁生成器
  17. 中产学院全国首创7大黄金技术桂林游学发布会
  18. mmd动作:FREELY_TOMORROW
  19. 牛津大学人类未来研究所:万字长文谈AI新职场方向-政策研究
  20. 22考研三战上交通信考研819电通初试第一428分经验分享

热门文章

  1. Nutanix 集群修改CVM IP地址
  2. BGP路由器协议排错教程:BGP 对等体失效的问题
  3. 声明银行账户类 java_编写Java程序,使用ThreadLocal类,项目中创建账户类 Account,类中包括账户名称name、 ThreadLocal 类的引用变量amount,表示存款...
  4. java 关闭kafka进程_无法启动任何kafka进程
  5. 中保研碰撞测试汇总 ---更新至2020.06.10
  6. flag在matlab中什么意思,动态 | 这个寒假,flag还是要立……
  7. windows64位-Erlang下载地址
  8. vue-router没有效果的问题解决之一
  9. 鸿蒙武器手机,鸿蒙野心不止手机,是华为下个十年最强武器?
  10. 杭州-2050青年科技大会