首页 > 其他分享 >【嵌入式开发之标准I/O】流的刷新、定位以及格式化输出、输入

【嵌入式开发之标准I/O】流的刷新、定位以及格式化输出、输入

时间:2024-07-25 19:59:41浏览次数:10  
标签:fp 格式化 21 int printf 嵌入式 char tm 刷新

流的刷新

 int fflush(FILE *fp);
  • 成功时返回0;出错时返回EOF。

  • 将流缓冲区中的数据写入实际的文件。

  • Linux下只能刷新输出缓冲区,输入缓冲区丢弃。

  • 如果输出到屏幕使用fflush(stdout)。

流的定位

流的定位:ftell()函数 

long ftell(FILE *stream);

ftell() 函数的作用是获取文件的 当前指针位置 相对于 文件首地址 的 偏移字节数 ;

流的定位:fseek()函数 

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

描述及参数介绍

fseek()函数用来设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。 

  • fseek 参数whence参数:SEEK_SET/SEEK_CUR/SEEK_END

  • SEEK_SET :从距文件开头 offset 位移量为新的读写位置

  • SEEK_CUR:以目前的读写位置往后增加 offset 个位移量

  • SEEK_END:将读写位置指向文件尾后再增加 offset 个位移量

  • offset参数:偏移量,可正可负

返回值

如果成功,则该函数返回零,否则返回非零值。

流的定位:rewind()函数

void rewind(FILE *stream);
主要功能

将文件内部的位置 指针重新指向一个流( 数据流/文件)的开头。 

返回值

该函数不返回任何值。

流的定位代码实例(ftell函数、fseek函数和rewind函数)

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	char *buff;
	int ret;

	buff = (char *)malloc(20);

	if ((fp = fopen("ffseek.txt", "w+")) == NULL) {
		perror("fopen");
		return 0;
	}

	//向空文件些人字符,并输出文件指针fp的位置
	fwrite("abcdef", 6, 1, fp);
	printf("after fwrite fp = %d\n", (int)ftell(fp));

	//文件指针指向文件开头,并读取文件内容,再显示文件指针位置
	rewind(fp);
	printf("after rewind fp = %d\n", (int)ftell(fp));
	ret = fread(buff, 12, 1, fp);
	printf("fread: %s\n", buff);
	printf("after fread fp = %d\n\n", (int)ftell(fp));

	//利用SEEK_SET参数,设置偏移为3,显示文件指针位置
	fseek(fp, 3, SEEK_SET);
	printf("after SEEK_SET=3 fp = %d\n", (int)ftell(fp));

	//从指针新指向的位置开始替换字符,并显示替换后指针位置
	fwrite("aa", 2, 1, fp);
	printf("after fwrite 2 fp = %d\n", (int)ftell(fp));

	//文件指针指向文件开头,显示被替换后的内容
	rewind(fp);
	ret = fread(buff, 12, 1, fp);
	printf("after SEEK_SET=3 and instead \"aa\":%s\n", buff);
	printf("after SEEK_SET=3 fp = %d\n\n", (int)ftell(fp));

	//设置SEEK_CUR 3参数后,fp指针的位置
	fseek(fp, 3, SEEK_CUR);
	printf("after SEEK_CUR 3 fp = %d\n", (int)ftell(fp));

	//设置SEEK_END 2参数后,fp指针的位置
	fseek(fp, -2, SEEK_END);
	printf("after SEEK_END -2 fp = %d\n", (int)ftell(fp));

	return 0;
}

注意事项

  1. 文件的打开使用a模式 fseek无效

  2. rewind(fp) 相当于 fseek(fp,0,SEEK_SET);

  3. 这三个函数只适用2G以下的文件

格式化输入和输出

格式化输出

格式化输出:printf()函数

int printf(const char *format, ...);
printf("<格式化字符串>", <参量表>);
主要功能

发送格式化输出到标准输出 stdout。

返回值

如果成功,则返回写入的字符总数,否则返回一个负数。

格式化输出:fprintf()函数

int fprintf(FILE *stream, const char *fmt, …);
主要功能

这个函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件.因此fprintf()可以使得信息输出到指定的文件.

返回值

成功时返回输出的字符个数;出错时返回EOF。

代码实例
#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	char buf[100] = {0};
	int year = 2021;
	int month = 10;
	int day = 1;

	if ((fp = fopen("fprintf.txt", "w")) == NULL) {
		perror("fopen");
		return 0;
	}

	fprintf(fp,"%d-%d-%d\n", year, month, day);

    fclose(fp);

	return 0;
}
运行结果及分析
2021-10-1

首先,通过fopen函数打开文件fprintf.txt,再将year,month,day三个变量的值读取到这个文件中,再通过cat命令显示文件中的内容。

格式化输出:sprintf()函数 

int sprintf( char *buffer, const char *format [, argument] … );
主要功能

主要功能是把格式化的数据写入某个字符串。

返回值

成功时返回输出的字符个数;出错时返回EOF。

代码实例
#include <stdio.h>

int main(int argc, const char *argv[])
{
	char buf[100] = {0};
	int year = 2021;
	int month = 10;
	int day = 1;

	sprintf(buf,"%d-%d-%d", year, month, day);
	printf("%s\n", buf);

	return 0;
}
运行结果及分析
2021-10-1

将year,month,day三个变量值读取到字符串buf中,再通过printf输出。 

格式化输入 

格式化输入:scanf()函数

int scanf(const char * restrict format,...);
主要功能

按用户指定的格式从键盘上把数据输入到指定的变量之中

函数的第一个参数是格式字符串,它指定了输入的格式,并按照格式说明符解析输入对应位置的信息并存储于可变参数列表中对应的指针所指位置。每一个指针要求非空,并且与字符串中的格式符一一顺次对应。

函数 scanf() 是从标准输入流stdin (标准输入设备,一般指向键盘)中读内容的通用子程序,可以说明的格式读入多个字符,并保存在对应地址的变量中。

返回值

scanf函数返回成功读入的数据项数,读入数据时遇到了“文件结束”则返回EOF。

 格式化输入:fscanf()函数

int fscanf(FILE *stream, const char *format, ...);
主要功能

根据数据格式 const char * format , 从文件 FILE * stream 中 , 读取数据存储到 [argument...] 参数中 。 

返回值

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

代码实例
#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	int year;
	int month;
	int day;

	if ((fp = fopen("fprintf.txt", "r")) == NULL) {
		perror("fopen");
		return 0;
	}

	fscanf(fp,"%d-%d-%d", &year, &month, &day);
	printf("%d-%d-%d\n", year, month, day);

	fclose(fp);

	return 0;
}
运行结果及分析
2021-10-1

将fprintf.txt文件中的数据,通过fscanf读取到year,month,和day三个中,然后通过printf函数输出。

格式化输入:sscanf()函数

int sscanf(const char *str, const char *format, ...);
主要功能

sscanf函数的主要功能是从字符串读取格式化输入。

返回值 

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

代码实例
#include <stdio.h>

int main(int argc, const char *argv[])
{
	char buf[100] = {0};
	int year = 2021;
	int month = 10;
	int day = 1;

	int syear;
	int smonth;
	int sday;

	sprintf(buf,"%d-%d-%d", year, month, day);
	printf("%s\n", buf);

	sscanf(buf,"%d-%d-%d", &syear, &smonth, &sday);
	printf("%d, %d, %d\n", syear, smonth, sday);

	return 0;
}
 运行结果及分析
2021-10-1
2021, 10, 1

先通过sprintf将年月日按一定格式输出到buf字符串中,在通过sscanf函数将buf字符串中的字符分别输入到syear,smonth和sday三个变量中,最后通过printf函数输出。

实例分析

实例要求

每隔1秒向文件test.txt中写入当前系统时间,格式如下:

1,  2014-10-15 15:16:42

2,  2014-10-15 15:16:43

该程序无限循环,直到按Ctrl-C中断程序,每次执行程序时,系统时间追加到文件末尾,序号递增。

相关提示

time()用来获取系统时间(秒数)
time_t time(time_t *seconds) 1970.1.1 0:0:0
localtime()将系统时间转换成本地时间
struct tm *localtime(const time_t *timer)
struct tm {
   int tm_sec;         /* 秒,范围从 0 到 59                */
   int tm_min;         /* 分,范围从 0 到 59                */
   int tm_hour;        /* 小时,范围从 0 到 23                */
   int tm_mday;        /* 一月中的第几天,范围从 1 到 31                    */
   int tm_mon;         /* 月份,范围从 0 到 11                */
   int tm_year;        /* 自 1900 起的年数                */
   int tm_wday;        /* 一周中的第几天,范围从 0 到 6                */
   int tm_yday;        /* 一年中的第几天,范围从 0 到 365                    */
   int tm_isdst;       /* 夏令时                        */    
};

实例代码

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

#define FNAME "1.txt"
#define MODE "a+"

int main(int argc, const char *argv[])
{
	FILE *fp;
	time_t ctime;
	struct tm *ctimestr;
	int linecount = 0;
	char ch;

	//打开文件,打开失败直接返回
	if ((fp = fopen(FNAME, MODE)) == NULL) {
		perror("fopen");
		return -1;
	}

	//计算1.txt存储数据的行数,实现每次重新运行序号都是累增
	while ((ch = fgetc(fp)) != -1) {
		if (ch == '\n') {
			linecount++;
		}
	}
	
	//获取系统时间,转换为当地时间,并写入到文件
	while (1) {
		ctime = time(NULL);//获取系统时间
		ctimestr = localtime(&ctime);//将系统时间转换为当地时间

		//在屏幕上输出时间
		printf("%d, %04d-%02d-%02d %02d:%02d:%02d\n", linecount, ctimestr->tm_year+1900, ctimestr->tm_mon+1, ctimestr->tm_mday, 
				ctimestr->tm_hour,ctimestr->tm_min, ctimestr->tm_sec);

		//把时间输出到文件
		fprintf(fp,"%d, %04d-%02d-%02d %02d:%02d:%02d\n", linecount, ctimestr->tm_year+1900, ctimestr->tm_mon+1, ctimestr->tm_mday, 
				ctimestr->tm_hour,ctimestr->tm_min, ctimestr->tm_sec);
		fflush(fp);//写完文件记得刷新,写进磁盘

		sleep(1);
		linecount++;
	}

	fclose(fp);//关闭文件

	return 0;
}

运行结果及分析

0, 2024-07-21 00:42:45
1, 2024-07-21 00:42:46
2, 2024-07-21 00:42:47
3, 2024-07-21 00:42:48
4, 2024-07-21 00:42:49
5, 2024-07-21 00:42:50
6, 2024-07-21 00:42:51
7, 2024-07-21 00:42:52
8, 2024-07-21 00:42:53
9, 2024-07-21 00:43:17
10, 2024-07-21 00:43:18
11, 2024-07-21 00:43:19
12, 2024-07-21 00:43:20
13, 2024-07-21 00:43:21
14, 2024-07-21 00:43:22
15, 2024-07-21 00:43:23
16, 2024-07-21 00:43:24
17, 2024-07-21 00:43:25
18, 2024-07-21 00:43:26
19, 2024-07-21 00:43:27

注意事项

  • 写完文件记得fflush ,写到磁盘里面去。

  • int tm_mon;获取的值要加1是正确的月份

  • int tm_year;获取的值加1900是正确的年份

  • 每次运行都要在原来的基础上累计行号,可以用fgetc函数逐一读取文件中的字符,看能读取到多少个‘\n’则是多少行。

标签:fp,格式化,21,int,printf,嵌入式,char,tm,刷新
From: https://blog.csdn.net/boy_ding_jian/article/details/140576526

相关文章

  • 【嵌入式开发之标准I/O】二进制文件的读写及实验
    文本文件和二进制的区别文本文件和二进制文件的区别主要在于它们的编码方式和数据组织方式。‌编码方式:‌文本文件是基于字符编码的文件,‌常见的编码有ASCII编码、‌UNICODE编码等。‌这些编码将字符映射到特定的二进制值,‌使得字符可以在计算机中存储和传输。‌相比之下,‌......
  • 嵌入式学习--DAY10:函数的调用
    一、函数参数和函数的值1.在定义函数中指定的形参,在未出现函数调用时,它们并不占用内存中的存储单元,只有在发生函数调用时,函数中的形参才会被分配内存单元。在调用结束后,形参所占的内存单元也会被释放。2.实参可以是常量、变量或表达式。在被定义的函数中,必须指定形参的类型,实......
  • 嵌入式工控机和4U工控机的区别
    在现代工业自动化和智能控制领域,工控机(工业计算机)作为关键的硬件支撑,扮演着至关重要的角色。随着技术的进步和市场需求的多样化,工控机的种类和形态不断丰富。其中,嵌入式工控机与4U工控机是两种常见的工业计算机类型。它们在结构、功能、应用场合等方面存在显著的区别。本文将详细......
  • 【Python】到底什么是字符串格式化?
    字符串格式化的目的:在字符串中动态地插入数据或表达式。字符串格式化的对象:要插入到字符串中的数据。在详细解释之前,先引入第一种字符串格式化的方法name=input('请输入你的名字:')gender=input('请输入你的性别:')age=input('请输入你的年龄:')print(f'你的名字是{......
  • 嵌入式工控机的优势与示例
    嵌入式工控机是一种专用计算系统,旨在在较大的系统或设备中执行特定任务或功能。与通用计算机不同,嵌入式工控机通常集成到日常物品、机械或设备中,例如汽车、电器、医疗设备和工业机器。这些计算机针对效率和可靠性进行了优化,并且通常具有固定用途,运行专用软件来控制和监控设备的操......
  • 《安富莱嵌入式周报》第340期:开源便携RF信号发生器,六自由度3D鼠标,开源USB PD Sniffer,C
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 视频版:https://www.bilibili.com/video/BV18w4m1k7NF/目录1、开源便携RF信号发生器,支持12.5MHz-6.4GHz2、关于ThreadX被移交Eclipse后,使用FileX的exFAT功能版权问题3、......
  • MOTOROLAVME172PA-652SE 嵌入式控制器
    高性能控制:MOTOROLAVME172PA-652SE模块具有高性能的控制能力,可以用于实现复杂的工业自动化系统的控制和监测。多功能模块:该模块可能具备多种功能,如输入/输出控制、数据采集、信号处理等,可适应不同的应用需求。可编程性:MOTOROLAVME172PA-652SE模块通常支持编程和定制化,使......
  • Golang格式化占位符详解
    Golang格式化占位符详解在Golang编程中,格式化字符串是一种常见的操作,它可以用来将不同类型的数据格式化为字符串输出。在格式化字符串时,占位符起着至关重要的作用,通过占位符可以指定数据的输出格式。本文将详细介绍Golang中一些常用的格式化占位符,并提供具体的代码示例供大......
  • pyMysql插入数据格式化问题!(秒解决)
    运行以下代码出现的问题:%dformat:anumberisrequired,notstr。username=input("请输入用户名:")password=input("请输入密码:")password=hashlib.md5(password.encode("utf-8")).hexdigest()real_name=input("请输入真实姓名:")......
  • 【UDS诊断协议:ISO-14229中文】【嵌入式车载测试收徒】
    每日直播时间:(直播方式:腾讯会议)周一到周五:20:00-23:00周六与周日:9:00-17:00                 进腾讯会议学习的,可以关注我并后台留言直播内容:(车厂真实项目实操测试)HIL(硬件在环)测试、UDS功能诊断、UDS自动化诊断、数据库制作、DTC故障制造、CAN......