首页 > 系统相关 >Linux环境编程--功能函数编写1

Linux环境编程--功能函数编写1

时间:2023-08-03 18:22:05浏览次数:38  
标签:Linux -- 编程 st int mode printf include buf

Linux系统编程实例1
1.实现一个计算文件大小的函数

方法1(标准IO):

函数使用:

int fseek(FILE *stream, long offset, int whence); 返回值:成功0 失败-1

long int ftell(FILE *stream);返回值:返回位置标识符的当前值。如果发生错误,则返回 -1L

long file_size(const char* path)
{
    FILE* fp = fopen(path,"r");
    if(NULL == fp)
  {
      perror("fopen");
      return -1;
  }
    fseek(fp,0,SEEK_END);
    long size = ftell(fp);
    fclose(fp);
    return size;
}

方法2(系统IO):

函数使用:

off_t lseek(int fd, off_t offset, int whence); 返回值:成功返回调整后位置指针的位置 失败-1

int file_size(const char* path)
{
    int fd = open(path,O_RDONLY);
    if(0 > fp)
  {
      perror("open");
      return -1;
  }
    int len = fseek(fp,0,SEEK_END);
  close(fd);
  return len;
}
2.使用系统IO实现一个带覆盖检测的cp命令

./a.out file1 file2

1、判断argc个数

2、以读方式打开file1

3、如果file2已存在,询问是否覆盖 是覆盖或者不存在:以写方式清空打开file2

4、循环读file1,写入file2,直到file1读取完毕

5、关闭文件

标准IO

#include <stdio.h>

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

    FILE* file1 = fopen(argv[1],"r");
    if(NULL == file1)
    {
        printf("被拷贝文件不存在,请检查\n");
        return 0;
    }

    FILE* file2 = fopen(argv[2],"r");
    if(file2)
    {
        printf("目标文件已存在,是否覆盖?(y/n)");
        char cmd = getchar();
        if('y' != cmd && 'Y' != cmd)
        {
            printf("已停止拷贝\n");
            fclose(file1);
            fclose(file2);
            return 0;
        }
        fclose(file2);
    }
    //    重新写方式打开file2
    file2 = fopen(argv[2],"w");
    if(NULL == file2)
    {
        printf("文件权限受限,请检查\n");
        fclose(file1);
        return 0;
    }

    //    以二进制方式循环读写文件
    char buf[1024] = {};
    size_t buf_size = sizeof(buf);
    int ret = 0;

    while(ret = fread(buf,1,buf_size,file1))
    {
        fwrite(buf,1,ret,file2);
    }

    fclose(file1);
    fclose(file2);
}

系统IO

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

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

    int src = open(argv[1],O_RDONLY);
    if(0 > src)
    {
        printf("原文件不存在,请检查\n");
        return 0;
    }

    int dest = open(argv[2],O_WRONLY|O_CREAT|O_EXCL,0644);
    if(0 > dest) //O_EXCL 配合O_CREAT,如果文件存在则失败
    {
        printf("目标文件已存在,是否覆盖(y/n)?");
        char cmd = getch();
        if('y' != cmd && 'Y' != cmd)
        {
            printf("停止拷贝\n");
            close(src);
            return 0;
        }
        printf("开始覆盖\n");
        dest = open(argv[2],O_WRONLY|O_TRUNC);    //O_TRUNC 文件如果存在,则清空打开
    }

    char buf[4096] = {};
    int ret = 0;
    while(ret = read(src,buf,sizeof(buf)))
    {
        write(dest,buf,ret);    
    }
    close(src);
    close(dest);
    printf("拷贝完成\n");
}
3.实现一个函数,可以删除某文件的[n,m)个字节
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>

bool del_file_part(const char* path,size_t n,size_t m)
{
	int fd = open(path,O_RDWR);
	if(0 > fd)
	{
		perror("open");
		return false;
	}

	//	计算文件大小
	int len = lseek(fd,0,SEEK_END);
	if(n > len) return false;
	if(m > len) m = len;

	char buf[4096] = {};
	lseek(fd,m,SEEK_SET);
	int ret = 0;
	while(ret = read(fd,buf,sizeof(buf)))
	{
		lseek(fd,n,SEEK_SET);
		write(fd,buf,ret);
		m += ret;
		n += ret;
		lseek(fd,m,SEEK_SET);
	}

	ftruncate(fd,len-(m-n));
	close(fd);
	return true;
}

int main(int argc,const char* argv[])
{
	printf("%d\n",del_file_part("hehe.txt",5,10));
}
4.实现一个完整的 ls -l 的功能

int stat(const char *pathname, struct stat *buf);

功能:根据文件路径获取文件的属性

buf:输出型参数 int fstat(int fd, struct stat *buf);

功能:根据文件描述符获取文件的属性

结构体 stat

struct stat 
{ 
    dev_t st_dev; // 设备ID 
    ino_t st_ino; // inode节点号 
    mode_t st_mode; // 文件的类型和权限 
    nlink_t st_nlink; // 硬链接数 
    uid_t st_uid; // 用户ID 
    gid_t st_gid; // 组ID 
    dev_t st_rdev; // 特殊设备ID 
    off_t st_size; // 总字节数 
    blksize_t st_blksize; // IO块总字节数 
    blkcnt_t st_blocks; // 占用大小512字节的内存块数量 
    struct timespec st_atim; // 最后访问时间 
    struct timespec st_mtim; // 最后修改时间 
    struct timespec st_ctim; // 最后状态修改时间 
#define st_atime st_atim.tv_sec /* Backward compatibility */ 
#define st_mtime st_mtim.tv_sec 
#define st_ctime st_ctim.tv_sec 
};

代码:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <dirent.h>
#include <limits.h>

//	显示文件类型
void file_type(mode_t mode)
{
	switch(mode & S_IFMT)
	{
		case S_IFSOCK:	printf("s"); break;	
		case S_IFLNK:	  printf("l"); break;	
		case S_IFREG:  	printf("-"); break;	
		case S_IFBLK:	  printf("b"); break;	
		case S_IFDIR: 	printf("d"); break;	
		case S_IFIFO: 	printf("p"); break;	
	}
}

//	显示文件权限
void file_mode(mode_t mode)
{
	printf("%c",mode & S_IRUSR?'r':'-');	
	printf("%c",mode & S_IWUSR?'w':'-');	
	printf("%c",mode & S_IXUSR?'x':'-');	
	printf("%c",mode & S_IRGRP?'r':'-');	
	printf("%c",mode & S_IWGRP?'w':'-');	
	printf("%c",mode & S_IXGRP?'x':'-');	
	printf("%c",mode & S_IROTH?'r':'-');	
	printf("%c",mode & S_IWOTH?'w':'-');	
	printf("%c",mode & S_IXOTH?'x':'-');	
}

//	显示用户名
void user_name(uid_t uid)
{
	struct passwd* pwd = getpwuid(uid);
	printf("%s ",pwd->pw_name);
}

//	显示组名
void group_name(gid_t gid)
{
	struct group* grp = getgrgid(gid);
	printf("%s ",grp->gr_name);
}

//	显示最后时间
void show_time(time_t st_time)
{
	struct tm* t = localtime(&st_time);
	printf("%02d月\t%02d %02d:%02d ",t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min);
}

//	计算目录层数
int dir_count(const char* path)
{
	DIR* dir = opendir(path);
	int count = 0;
	for(struct dirent* d=readdir(dir); d; d=readdir(dir))
	{
		count += (DT_DIR == d->d_type);	
	}
	closedir(dir);
	return count;
}

//	ls -l
void list_file_stat(const char* path)
{
	//	获取文件属性
	struct stat buf = {};
	if(stat(path,&buf))
	{
		perror("stat");
		return;
	}

	file_type(buf.st_mode);//	显示文件类型
	file_mode(buf.st_mode);//	显示文件权限
	printf(" %d ",S_ISDIR(buf.st_mode)?dir_count(path):1);//	计算目录层数
	user_name(buf.st_uid);//	显示用户名
	group_name(buf.st_gid);//	显示组名
	printf("%8lu ",buf.st_size);// 显示文件大小
	show_time(buf.st_mtime);//	显示最后时间
	printf("%s\n",path);// 显示文件名
}

void ls(const char* path)
{
	DIR* dir = opendir(path);
	if(NULL == dir)
	{
		perror("opendir");
		return;
	}
	//	备份原工作路径
	char buf[PATH_MAX] = {};//PATH_MAX 是 #include <limits.h>宏定义
	getcwd(buf,PATH_MAX);

	//	修改工作路径
	chdir(path);
	for(struct dirent* d = readdir(dir); d; d = readdir(dir))
	{
		if('.' != d->d_name[0])
			list_file_stat(d->d_name);	
	}

	//	还原原工作路径
	chdir(buf);
	closedir(dir);
}

int main(int argc,const char* argv[])
{
	if(1 == argc)
	{
		ls(".");	
	}
	else
	{
		ls(argv[1]);	
	}
}
5.实现 rm -rf 的功能(容易破坏系统,运行前备份,检查)
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>

void rm_rf_dir(const char* path)
{
	if(0 == rmdir(path)) return;

	//	备份当前工作路径
	char buf[PATH_MAX] = {};
	getcwd(buf,PATH_MAX);
	//	设置工作路径
	if(chdir(path)) return;

	DIR* dir = opendir(".");
	for(struct dirent* d=readdir(dir); d; d=readdir(dir))
	{
		if(DT_DIR == d->d_type)	
		{
			if(strcmp(d->d_name,".") && strcmp(d->d_name,".."))//防止进入前一级目录删除
			{
				rm_rf_dir(d->d_name);	
			}
		}
		else
		{
			unlink(d->d_name);	
		}
	}
	closedir(dir);
	//	还原工作路径
	chdir(buf);
	rmdir(path);
}

int main(int argc,const char* argv[])
{
	if(2 != argc)
	{
		printf("User: ./RM dir\n");
		return 0;
	}
	rm_rf_dir(argv[1]);
}

标签:Linux,--,编程,st,int,mode,printf,include,buf
From: https://www.cnblogs.com/bigflyny/p/17604122.html

相关文章

  • 高并发性能指标:QPS、TPS、RT、吞吐量
    QPS,每秒查询QPS:QueriesPerSecond意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。互联网中,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。TPS,每秒事务TPS:是TransactionsPerSecond的缩写......
  • Mybatis-Plus代码生成器的使用
    通常我们在做项目的时候,要手动搭建项目的结构,如controller,service,mapper,entity,是不是很麻烦,特别是数据库表特别多时,现在介绍一下使用MybatisPlus时怎么自动生成这些代码。首先要在项目的pom.xml里引入必要的依赖,如下:<dependency><groupId>com.baomidou</groupId><ar......
  • 在vscode的界面的竖线光标变成灰色方块,怎么解决?Mark一下
    在vscode的界面的竖线光标变成灰色方块,怎么解决?补充一下,也有可能是setting.json中设置所致,可以去看看setting.json中是否将cursorstyle设置为了block......
  • Excel分类后数字类型的内容值后面变为0
    背景在工作中经常遇到从日志或者其他地方拷贝过来的文本,里面使用其他分隔符进行分割。然而,使用Excel的分列功能进行分列后,发现数字类型的数值后面变为0。有时候我们就是需要原先的数值,该怎么办呢?比如,有如下的数据,以竖线|作为分割符。|员工编号|销售量|商品单价|销售额|20180......
  • 学习Java第13天
    逻辑运算符packageoperator;//**逻辑运算符publicclassDemo05{publicstaticvoidmain(String[]args){//**与(**and)或(or)**非(取反)booleana=true;booleanb=false;System.out.println("a&&b:"+(a&&b));//*逻辑与运算:两个变量都为真,结果才为true**......
  • vmware中克隆虚拟机无法上网的解决办法
    1、首先编辑网卡配置文件,vi/etc/sysconfig/network-scripts/ifcfg-eth0,将HWADDR和UUID两个参数删除或者注释掉,然后保存退出。2、清空/etc/udev/rules.d/70-persistent-net.rules文件,>/etc/udev/rules.d/70-persistent-net.rules3、重启虚拟机 ......
  • 强化学习——策略梯度之Reinforce
    1、策略梯度介绍相比与DQN,策略梯度方法的区别主要在于,我们对于在某个状态下所采取的动作,并不由一个神经网络来决定,而是由一个策略函数来给出,而这个策略函数的目的,就是使得最终的奖励的累加和最大,这也是训练目标,所以训练会围绕策略函数的梯度来进行。2、策略函数以Reinforce算法......
  • wangEditor 图片粘贴上传,实现图文粘贴,图片自动上传
    ​ 1.编辑器修改(可选) 1.1在 ueditor/config.json 中添加代码块    /* 上传word配置 */    "wordActionName":"wordupload",/* 执行上传视频的action名称 */    "wordFieldName":"upfile",/* 提交的视频表单名称 */    "wordPathFormat":......
  • AWVS安装使用
    AWVS安装使用1.双击exe文件,然后点击下一步。2.选择我接受,然后下一步。3.选择路径(我选择的默认路径)然后下一步。4.还是下一步。5.设置邮箱,用户名密码,用户名[email protected]密码12345678.a然后下一步。6.设置端口:3443,勾选允许远程访问awvs然后下一步。7.创建桌面快捷方式,然后......
  • ubuntu相关
    1网卡地址/etc/netplannetwork:ethernets:ens33:dhcp4:noaddresses:[192.168.21.204/24]optional:trueroutes:-to:defaultvia:192.168.21.2nameservers:addresses:[192.168.21.2,8.8.......