不带缓存的文件操作用到的几个的函数

本文介绍了不带缓存的文件I/O操作中常用的六个函数:creat、open、read、write、lseek和close。详细解释了每个函数的作用、参数及返回值,并提供了一个复制文件的具体实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不带缓存的文件I/O操作,主要用到6个函数--creat,open,read,write,lseek,close.

这里的不带缓存是指每一个函数都只调用系统中的函数,这些函数虽然不是ANSI C

的组成部分,但却是POSIX的组成部分。

下面就来介绍一下这几个函数:

1.creat:

函数的作用:

创建文件;

函数原型:

int creat(const char *pathname, mode_t mode);

函数参数:

Pathname:要建立的文件路径字符串(使用时要加双引号);

Mode: 建立文件的权限;

函数返回值:

Int.

成功返回文件描述符,

出错返回 -1

函数头文件:

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.c>

 

2.Open

函数作用:

打开或者创建文件。

函数原型:

int open (const char *pathname, int flags);

Int open (const char *pathname,int flags, mode_t mode);

函数参数:

flags:使用的标志;例如:

O_RDONLY 只读;

O_WRONLY 只写;。。。。。。

返回值:

Int 型;

成功返回文件描述符;

失败返回 -1;

头文件:(同上);

 

3.Read

函数作用:

从打开的文件中读取数据

函数原型:

Ssize_t read(int fd, void *buf, size_t count);

函数参数:

Fd:open返回的文件描述符。

Buf:放置都出来的数据缓冲区。

Count:要读取的字符数。

返回值:

Ssize_t (自己重命名的类型,一般为int型);

成功返回读到的字符数(字节)

出错返回-1;

头文件:

#include <unistd.h>

4.Write

函数作用:

将数据写入已经打开的文件内。

函数原型:

Ssize_t write(int fd, const void *buf, size_t count);

函数参数:

Count:写入的字节数。

返回值:

Int 型;

成功返回实际写入的字节数。

失败返回 -1.

 

5.lseek

函数作用:移动函数指针到指定位置。

函数原型:off_t lseek(int fd, off_t offset, int whence);

函数参数:

fd:文件描述符。

Whence:文件的指针位置。例如:

       SEEK_SET  文件头

       SEEK_CUR 文件的当前位置

       SEEK_END 文件尾

offset:文件指针偏移量,向前移动是负数,向后是正数。

返回值:

Int .

返回文件指针到文件头的字节数。

 

最后需要注意的是:当我们write函数写入数据时,文件指针指向了写入的数据尾,这时如果还用read来读取数据,是从文件指针指的地方开始读,是无法读到数据的,所以要用lseek函数把指针指向文件头。(lseek(fd,0,SEEK_SET));

 

例如复制一个文件到另一个文件:

程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define MAX_SIZE 1024

int main(int argc, char *argv[])
{
    int from_fd,to_fd;
    int from_read,to_write;
    char buf[MAX_SIZE];
    char *ptr;

    if(argc != 3)
    {
        printf("Please choose 2 file!\n");
	exit (1);
    }

    from_fd = open(argv[1],O_RDONLY);

    if(from_fd == -1)
    {
        printf("can not open file1 !\n");
	exit (1);
    }

    to_fd = open(argv[2],O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR);

    if(to_fd == -1)
    {
        printf("can not open file2 !\n");
	exit (1);
    }
    while(from_read = (from_fd,buf,MAX_SIZE))
    {
        if(from_read == -1)
	{
	    break;
	}
	else if(from_read > 0)
	{
	    ptr = buf;

	    while(to_write = write(to_fd,ptr,from_read))
	    {
	        if(to_write == -1)
		{
		    break;
		}
		else if(to_write == from_read)
		{
		    break;
		}
		else if(to_write > 0)
		{
		    ptr+=to_write;
		    from_read-=to_write;
		}
	    }
            if(to_write == -1)
	    {
	        break;
	    }
	}
    }
    
    close(from_fd);
    close(to_fd);
    
    exit(0);
}

<think>好的,用户之前让我帮忙在Keil5里为STC8A8K48D4写一个OLED模块的代码,现在他们接着上一个程序,想要一个显示数字的函数。我需要先回顾之前的代码结构,确保新函数能够无缝衔接。 首先,用户提供的代码里已经有了显示字符的函数OLED_ShowChar,这个函数应该是基于字库来显示单个字符。显示数字的话,通常有两种方式:一种是将数字转换为字符,然后调用现有的字符显示函数;另一种是直接处理数字的每一位,转换成对应的字符形式。用户可能需要一个更灵活的函数,比如可以显示整数、浮点数或者特定格式的数字。 接下来,我需要考虑用户的实际需求。可能他们需要显示传感器数据、计数器等,所以函数需要支持同位数的整数,可能包括正负数。另外,浮点数的显示可能也是需要的,但考虑到单片机资源有限,可能先实现整数显示更实际。 然后,回顾之前的代码,显示字符的函数是OLED_ShowChar,参数是x, y坐标和字符。显示数字的话,可以写一个OLED_ShowNum函数,接收数字、位数等参数。例如,显示一个整数,指定显示几位,足的位数补零或者空格。或者处理长整型,考虑数字的长度,自动调整显示位置。 需要注意数字到字符的转换,比如将数字123转换为'1','2','3',然后循环调用OLED_ShowChar显示每个字符。这里需要处理每一位数字,可能需要用到取模和除法运算来分解数字的每一位。 还要考虑显示的位置,每个字符占8个像素宽度(假设使用8x16字体),所以每显示一个数字,x坐标需要增加8,以正确排列数字。例如,显示在x=0的位置,第一个字符在0,第二个在8,依此类推。 另外,用户可能希望有左对齐或右对齐的选项,比如显示数字右对齐,前面补零或空格。例如,显示数字5为“ 5”或者“005”,取决于位数设定。这需要在函数中添加参数来控制填充方式。 还需要考虑负数的情况,如果数字是负数,需要在最前面显示负号,然后处理绝对值部分。这时候需要检查数字是否为负,如果是,显示负号,并将数字转换为正数处理。 还有错误处理,比如如果传入的位数足以显示数字,比如要显示1234但只给3位,这时候可能需要截断或者全显示,根据用户需求决定如何处理。可能需要在函数内计算数字的实际位数,并与传入的位数比较,动态调整。 另外,考虑到资源有限的单片机,函数应尽可能高效,避免使用过大的缓冲区或复杂的运算。例如,避免使用sprintf这样的库函数,因为它可能会增加代码大小和内存占用。手动分解数字会更高效。 最后,需要测试这个函数是否能正确显示各种情况,比如0、负数、最大最小值等,确保在同情况下都能正常工作。 总结下来,步骤应该是: 1. 创建一个显示数字的函数,比如OLED_ShowNum。 2. 处理正负数,显示负号。 3. 分解数字的每一位,转换为字符。 4. 根据指定的位数,补零或空格。 5. 循环调用OLED_ShowChar显示每个字符。 6. 更新x坐标,确保数字正确排列。 需要确保代码与之前的字符显示函数兼容,并且用户能够轻松调用这个新函数来显示他们需要的数字。</think>好的,我们可以在原有代码基础上扩展数字显示功能。以下是基于之前OLED模块代码的数字显示函数实现: ```c /*-------- 步骤1:添加数字显示函数 --------*/ // 功能:在指定位置显示整数 // 参数:x横坐标(0-127), y页地址(0-7), num要显示的数字, len显示位数(1-5) void OLED_ShowNum(unsigned char x, unsigned char y, int num, unsigned char len) { unsigned char t, temp; unsigned char enshow = 0; // 前导零标志 // 处理负数 if(num < 0) { OLED_ShowChar(x, y, '-'); x += 8; // 每个字符占8列宽度 num = -num; len--; // 减少一位用于符号显示 } // 逐位分解数字 for(t=0; t<len; t++) { temp = (num / OLED_Pow(10, len-t-1)) % 10; // 前导零处理:当遇到零数字或最后一位时开始显示 if(enshow==0 && t<(len-1)) { if(temp == 0) { OLED_ShowChar(x + 8*t, y, ' '); continue; } else enshow = 1; } OLED_ShowChar(x + 8*t, y, temp + '0'); } } /*-------- 步骤2:添加幂运算辅助函数 --------*/ // 计算10的幂次方(用于数字分解) int OLED_Pow(int x, unsigned int y) { unsigned int i; int result = 1; for(i=0; i<y; i++) result *= x; return result; } /*-------- 步骤3:添加浮点数显示函数(可选)--------*/ // 显示格式:x.y精度为小数点后1位 void OLED_ShowFloat(unsigned char x, unsigned char y, float num) { int integer = (int)num; int decimal = (int)((num - integer)*10); OLED_ShowNum(x, y, integer, 3); OLED_ShowChar(x+24, y, '.'); // 显示小数点 OLED_ShowChar(x+32, y, (decimal >=0) ? (decimal+'0') : '0'); } /*-------- 使用示例 --------*/ void main() { // ... 初始化代码同上 ... OLED_ShowNum(0, 1, 1234, 4); // 显示"1234" OLED_ShowNum(0, 2, -56, 3); // 显示"-56" OLED_ShowNum(0, 3, 7, 2); // 显示" 7"(前导空格) OLED_ShowFloat(0, 4, 25.8); // 显示"25.8" while(1); } ``` 关键功能说明: 1. `OLED_ShowNum()`特点: - 支持负数显示 - 自动前导空格处理(避免显示多余零) - 可指定显示位数(适合对齐显示) - 坐标自动计算(每个数字占8像素宽) 2. 增强功能: ```c // 扩展功能:无符号长整型显示(0-4294967295) void OLED_ShowULong(unsigned char x, unsigned char y, unsigned long num, unsigned char len) { unsigned char t; unsigned char temp; for(t=0; t<len; t++) { temp = (num / OLED_Pow(10, len-t-1)) % 10; OLED_ShowChar(x + 8*t, y, temp + '0'); } } // 格式的数字显示(支持16进制) void OLED_ShowHex(unsigned char x, unsigned char y, unsigned char hex) { OLED_ShowChar(x, y, (hex/16 >9) ? (hex/16-10+'A') : hex/16+'0'); OLED_ShowChar(x+8, y, (hex%16 >9) ? (hex%16-10+'A') : hex%16+'0'); } ``` 常见问题解决方案: 1. 显示错位问题: - 检查字库是否匹配(必须使用8像素宽字体) - 确认x坐标计算:每个字符占8列,x坐标应依次+8 2. 显示数值异常: - 数值范围检查:int型范围为-32768~32767 - 浮点数精度限制:建议放大10倍用整数处理 3. 性能优化建议: - 对频繁刷新的数据使用显示缓冲 - 长数字显示时建议分段处理 - 使用查表法代替OLED_Pow()函数 建议将以下宏定义添加到配置部分: ```c #define MAX_INT_DIGITS 5 // 最大显示5位整数 #define FLOAT_PRECISION 1 // 默认显示1位小数 ``` 这个数字显示框架可以方便地扩展应用于: - 实时时钟显示 - 传感器数据展示(温度、湿度等) - 计数器数值显示 - 系统状态参数监控
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值