《Linux C编程实战》笔记:实现自己的ls命令
关键函数的功能及说明
1.void display_attribute(struct stat buf,char *name)
函数功能:打印文件名为name的文件信息,如
含义分别为:文件的类型和访问权限,文件的链接数,文件的所有者,文件所有者所属的组,文件大小,文件创建的时间
2.void dispaly_single(char *name)
函数功能:输出文件的文件名,如果命令中没有-l选项,则输出文件名时要保证上下对齐,如:
3.void display(int flag,char *pathname)
函数功能:根据命令行参数(存放在flag中)和完整路径名(存放在pathname中)显示目标文件,参数flag可以取以下值或者它们的组合
4.void diaplay_dir(int flag_param,char *path)
函数功能:为显示某个目录下的文件做准备,参数flag_param用于在调用display函数时作为其参数flag的实参,path是要显示的目录
函数流程
准备工作代码:
#include<cstdlib>
#include<cstring>
#include <cstdio>
#include<ctime>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<cerrno>
#include<dirent.h>
#include<linux/limits.h>
#include<pwd.h>
#include<grp.h>
#include<algorithm>
using namespace std;#define PARAM_NONE 0//无参数
#define PARAM_A 1//-a 显示所有文件
#define PARAM_L 2 //-l 一行只显示一个文件的详细信息
#define MAXROWLEN 80 //一行显示的最多字符数int g_leave_len=MAXROWLEN;//一行剩余长度,用于输出对齐
int g_maxlen; //存放某目录下最长文件名的长度
//自定义错误处理函数
void my_err(const char *err_string,int line){fprintf(stderr,"line:%d ",line);perror(err_string);exit(1);
}
int cmp(const void *a, const void *b)
{return ((char *)a)[0] - ((char *)b)[0];
}
顺便了解
pwd.h
和grp.h
是两个C语言标准库头文件,用于处理用户和组的信息,通常用于UNIX和类UNIX系统。
该头文件定义了与用户账户信息相关的结构和函数。主要包括获取和处理用户账户信息的功能,例如用户名、用户ID(UID)、组ID(GID)、用户家目录等。一些常见的函数和结构体包括:
pwd.h
- Password Database:
getpwnam
:通过用户名获取用户信息。getpwuid
:通过用户ID获取用户信息。struct passwd
:用于存储用户账户信息的结构体。该头文件定义了与用户组信息相关的结构和函数。主要包括获取和处理用户组信息的功能,例如组名、组ID(GID)、组成员等。一些常见的函数和结构体包括:
grp.h
- Group Database:
struct group
:用于存储用户组信息的结构体。getgrgid
:通过组ID获取组信息。getgrnam
:通过组名获取组信息。
如果你不清楚函数代码实在干嘛,可以看一下上面的运行结果,这样才知道到底要输出什么
display_attribute代码:
//获取文件属性并打印
void display_attribute(struct stat buf,char *name){char buf_time[32];struct passwd *psd;//从该结构体中获取文件所有者的用户名struct group *grp;//从该结构体中获取文件所有者所属组的组名//获取并打印文件类型if(S_ISLNK(buf.st_mode))printf("l");//符号链接else if(S_ISREG(buf.st_mode))printf("-");//普通文件else if(S_ISDIR(buf.st_mode))printf("d");//目录else if(S_ISCHR(buf.st_mode))printf("c");//字符设备文件else if(S_ISBLK(buf.st_mode))printf("b");//块设配文件else if(S_ISSOCK(buf.st_mode))printf("s");//套接字文件else if(S_ISFIFO(buf.st_mode))printf("f");//FIFO文件//获取并打印文件所有者的权限if(buf.st_mode&S_IRUSR)printf("r");else printf("-");if(buf.st_mode&S_IWUSR)printf("w");else printf("-");if(buf.st_mode&S_IXUSR)printf("x");else printf("-");//获取并打印与文件所有者同组的用户对该文件的操作权限if(buf.st_mode&S_IRGRP)printf("r");else printf("-");if(buf.st_mode&S_IWGRP)printf("w");else printf("-");if(buf.st_mode&S_IXGRP)printf("x");else printf("-");//获取并打印其他用户对该文件的操作权限if(buf.st_mode&S_IROTH)printf("r");else printf("-");if(buf.st_mode&S_IWOTH)printf("w");else printf("-");if(buf.st_mode&S_IXOTH)printf("x");else printf("-");printf(" ");//根据uid与gid获取文件所有者的用户名与组名psd=getpwuid(buf.st_uid);grp=getgrgid(buf.st_gid);printf("%4d",buf.st_nlink);//打印文件的链接数printf("%-8s",psd->pw_name);printf("%-8s",grp->gr_name);printf("%6d",buf.st_size);//打印文件的大小strcpy(buf_time,ctime(&buf.st_mtime));buf_time[strlen(buf_time)-1]='\0';//去掉换行符printf(" %s",buf_time);//打印文件的时间信息
}
struct stat这个结构体在《Linux C编程实战》笔记:文件属性操作函数-CSDN博客 这里放过具体的信息,可以看到主要是从st_mode获取信息
S_ISLNK
是一个宏(macro),通常用于检查给定文件的模式是否表示一个符号链接(Symbolic Link)。这个宏在UNIX和类UNIX系统的系统编程中很常见,特别是在处理文件和目录时。
S_ISLNK
的定义通常在<sys/stat.h>
头文件中,这个头文件包含了有关文件状态(file status)的相关宏和结构体定义。它的典型用法是与st_mode
结构成员一起使用
其他的宏都是类似的作用,用来检查文件具体是那种类型的。
buf.st_mode & S_IRGRP
是一个位运算的操作,用于检查给定文件的权限位
S_IRGRP之类的文件权限的宏在 《Linux C编程实战》笔记:文件读写-CSDN博客 有具体解释过,通过这个操作可以得知文件的具体权限
用
getpwuid
和getgrgid
函数来获取文件或目录的所有者(user)和所属组(group)的相关信息。这两个函数通常与文件状态结构struct stat
中的st_uid
(用户ID)和st_gid
(组ID)成员一起使用。
#include <pwd.h>struct passwd *getpwuid(uid_t uid);
#include <grp.h>struct group *getgrgid(gid_t gid);
struct passwd {char *pw_name; // 用户名char *pw_passwd; // 加密后的密码uid_t pw_uid; // 用户IDgid_t pw_gid; // 主组IDchar *pw_gecos; // 用户的真实姓名等描述信息char *pw_dir; // 用户的主目录char *pw_shell; // 用户的登录shell
};
struct group {char *gr_name; // 组名char *gr_passwd; // 加密后的密码(在 /etc/gshadow 中)gid_t gr_gid; // 组IDchar **gr_mem; // 用户名的数组,表示属于这个组的成员
};
ctime的具体用法也在 《Linux C编程实战》笔记:文件属性操作函数-CSDN博客 有提到
%-8s
的格式时,它包含两个部分:-8
是一个标志(flag),表示左对齐输出,而%s
表示将一个字符串插入到该位置。
%s
:插入一个字符串。-8
:左对齐,并占用最少8个字符的宽度。如果字符串长度不足8个字符,将用空格在右侧填充。
dispaly_single代码:
//在没有使用-l选项时,打印一个文件名,打印时上下对齐
void display_single(char *name){int i,len;//如果本行不足以打印一个文件名则换行if(g_leave_len<g_maxlen){printf("\n");g_leave_len=MAXROWLEN;}len=strlen(name);len=g_maxlen-len;printf("%-s",name);//为了保持对齐,需要填充空格来实现和最长文件名占位相同for(i=0;i<len;i++){printf(" ");}printf(" ");g_leave_len-=(g_maxlen+2);//改行剩下的长度减去最长文件名加两个空格的长度
}
这里主要是格式控制,在准备代码里有每个变量具体的含义,每次输出主要是更新g_leave_len
display代码:
/*
* 根据命令行参数和完整路径名显示目标文件
* 参数flag:命令行参数
* 参数pathname:包含了文件名的路径名
*/
void display(int flag,char *pathname){int i,j;struct stat buf;char name[NAME_MAX+1];//从路径中解析出文件名,其实就是最后一个/后面的字符串了//书中代码是这么来获得的,感觉应该有更好的方法(C语言好像没有split函数,多少会麻烦一些)for(i=0,j=0;i<strlen(pathname);i++){if(pathname[i]=='/'){j=0;continue;}name[j++]=pathname[i];}name[j]='\0';//用lstat而不是stat以方便解析链接文件if(lstat(pathname,&buf)==-1)my_err("stat",__LINE__);switch (flag){case PARAM_NONE://没有选项if(name[0]!='.'){//隐藏的.目录文件就忽略display_single(name);}break;case PARAM_A:display_single(name);break;case PARAM_L:if(name[0]!='.'){display_attribute(buf,name);//详细信息printf(" %s-\n",name);//最后打印文件名}break;case PARAM_A+PARAM_L:display_attribute(buf,name);printf(" %-s\n",name);break;default:break;}
}
NAME_MAX在《Linux C编程实战》笔记:目录操作-CSDN博客
lstat在《Linux C编程实战》笔记:文件属性操作函数-CSDN博客
display_dir代码:
void display_dir(int flag_param,char *path){DIR *dir;struct dirent *ptr;int count=0;char filenames[256][PATH_MAX+1],temp[PATH_MAX+1];//获取该目录下文件总数和最长的文件名dir=opendir(path);if(dir==nullptr)my_err("opendir",__LINE__);while((ptr=readdir(dir))!=nullptr){if(g_maxlen<strlen(ptr->d_name))g_maxlen=strlen(ptr->d_name);//更新最长的文件名长度count++;}closedir(dir);if (count>256){my_err("too maney files under this dir",__LINE__);}int i,j,len=strlen(path);//获取该目录下所有的文件名dir=opendir(path);for(i=0;i<count;i++){ptr=readdir(dir);if(ptr==nullptr)my_err("readdir",__LINE__);strncpy(filenames[i],path,len);filenames[i][len]='\0';strcat(filenames[i],ptr->d_name);//把目录名称和目录下的文件名拼一起filenames[i][len+strlen(ptr->d_name)]='\0';}//给文件名排序//源代码里用的是冒泡,排序不是重点,用一下stl算了,偷个懒qsort(filenames,count,sizeof(filenames[0]),cmp);for(i=0;i<count;i++)display(flag_param,filenames[i]);closedir(dir);//如果命令行中没有-l选项,打印一个换行符if((flag_param&PARAM_L)==0)printf("\n");
}
打开目录和遍历目录的操作我已经演示过了了《Linux C编程实战》笔记:目录操作-CSDN博客
main函数代码:
int main(int argc,char **argv){int i,j,k,num;char path[PATH_MAX+1];char param[32];//保存命令行参数,目标文件名和目录名不在这里int flag_param=PARAM_NONE;//参数种类struct stat buf;//命令行参数的解析,分析 -l、-a、-al、-la选项j=0;num=0;for(i=1;i<argc;i++){if(argv[i][0]=='-'){//是一个命令for(k=1;k<strlen(argv[i]);k++,j++){param[j]=argv[i][k];//把命令的参数(a或l)都放到param数组里}num++;//保存"-"的个数}}//j现在是param数组的长度for(int i=0;i<j;i++){//遍历param数组,看参数都是什么if(param[i]=='a'){flag_param|=PARAM_A;continue;}else if(param[i]=='l'){flag_param|=PARAM_L;continue;}else{//a,l以外的参数,不支持printf("my_ls:invalid option -%c\n",param[i]);exit(1);}}param[j]='\0';//如果没有输入文件名或目录则显示当前目录if((num+1)==argc){//这表示除了参数,没有输入文件或目录strcpy(path,"./");//path变成当前目录path[2]='\0';display_dir(flag_param,path);//用显示目录的函数return 0;}//开始遍历文件或目录i=1;do{//如果不是目标文件或目录,解析下一个命令行参数if(argv[i][0]=='-'){i++;continue;}else{strcpy(path,argv[i]);//如果目标文件或目录不存在,报错并退出if(stat(path,&buf)==-1)my_err("stat",__LINE__);if(S_ISDIR(buf.st_mode)){//argv[i]是一个目录//如果目录的最后一格字符不是'/',就把'/'加上if(path[strlen(argv[i])-1]!='/'){path[strlen(argv[i])]='/';path[strlen(argv[i])+1]='\0';}else path[strlen(argv[i])]='\0';//也是调用显示目录的函数display_dir(flag_param,path);i++;}else{//argv[i]是一个文件display(flag_param,path);i++;}}} while (i<argc);return 0;
}
这里说一下argc和argv,不然可能搞不懂。
运行程序时,如果啥都不跟,直接./a.out这种的话,argc默认为1,argv[0]是程序名字,如果后面带了参数,比如这样
./a.out arg1 arg2 arg3
那argc就是4,argv[1],argv[2],argv[3]存的是参数的字符串
所以argv代码里都是从1开始,因为argv[0]默认存的是程序名称。
编译运行一下
结果还是很完美的
一整个源码也在这,方便直接抄了,但是没有注释
#include<cstdlib>
#include<cstring>
#include <cstdio>
#include<ctime>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<cerrno>
#include<dirent.h>
#include<linux/limits.h>
#include<pwd.h>
#include<grp.h>
#include<algorithm>
using namespace std;
#define PARAM_NONE 0
#define PARAM_A 1
#define PARAM_L 2
#define MAXROWLEN 80int g_leave_len=MAXROWLEN;
int g_maxlen;
//自定义错误处理函数
void my_err(const char *err_string,int line){fprintf(stderr,"line:%d ",line);perror(err_string);exit(1);
}
int cmp(const void *a, const void *b)
{return ((char *)a)[0] - ((char *)b)[0];
}
void display_attribute(struct stat buf,char *name){char buf_time[32];struct passwd *psd;struct group *grp;if(S_ISLNK(buf.st_mode))printf("l");else if(S_ISREG(buf.st_mode))printf("-");else if(S_ISDIR(buf.st_mode))printf("d");else if(S_ISCHR(buf.st_mode))printf("c");else if(S_ISBLK(buf.st_mode))printf("b");else if(S_ISSOCK(buf.st_mode))printf("s");else if(S_ISFIFO(buf.st_mode))printf("f");if(buf.st_mode&S_IRUSR)printf("r");else printf("-");if(buf.st_mode&S_IWUSR)printf("w");else printf("-");if(buf.st_mode&S_IXUSR)printf("x");else printf("-");if(buf.st_mode&S_IRGRP)printf("r");else printf("-");if(buf.st_mode&S_IWGRP)printf("w");else printf("-");if(buf.st_mode&S_IXGRP)printf("x");else printf("-");if(buf.st_mode&S_IROTH)printf("r");else printf("-");if(buf.st_mode&S_IWOTH)printf("w");else printf("-");if(buf.st_mode&S_IXOTH)printf("x");else printf("-");printf(" ");psd=getpwuid(buf.st_uid);grp=getgrgid(buf.st_gid);printf("%4d",buf.st_nlink);printf("%-8s",psd->pw_name);printf("%-8s",grp->gr_name);printf("%6d",buf.st_size);strcpy(buf_time,ctime(&buf.st_mtime));buf_time[strlen(buf_time)-1]='\0';printf(" %s",buf_time);
}void display_single(char *name){int i,len;if(g_leave_len<g_maxlen){printf("\n");g_leave_len=MAXROWLEN;}len=strlen(name);len=g_maxlen-len;printf("%-s",name);for(i=0;i<len;i++){printf(" ");}printf(" ");g_leave_len-=(g_maxlen+2);
}
void display(int flag,char *pathname){int i,j;struct stat buf;char name[NAME_MAX+1];for(i=0,j=0;i<strlen(pathname);i++){if(pathname[i]=='/'){j=0;continue;}name[j++]=pathname[i];}name[j]='\0';if(lstat(pathname,&buf)==-1)my_err("stat",__LINE__);switch (flag){case PARAM_NONE:if(name[0]!='.'){display_single(name);}break;case PARAM_A:display_single(name);break;case PARAM_L:if(name[0]!='.'){display_attribute(buf,name);printf(" %s-\n",name);}break;case PARAM_A+PARAM_L:display_attribute(buf,name);printf(" %-s\n",name);break;default:break;}
}void display_dir(int flag_param,char *path){DIR *dir;struct dirent *ptr;int count=0;char filenames[256][PATH_MAX+1],temp[PATH_MAX+1];dir=opendir(path);if(dir==nullptr)my_err("opendir",__LINE__);while((ptr=readdir(dir))!=nullptr){if(g_maxlen<strlen(ptr->d_name))g_maxlen=strlen(ptr->d_name);count++;}closedir(dir);if (count>256){my_err("too maney files under this dir",__LINE__);}int i,j,len=strlen(path);dir=opendir(path);for(i=0;i<count;i++){ptr=readdir(dir);if(ptr==nullptr)my_err("readdir",__LINE__);strncpy(filenames[i],path,len);filenames[i][len]='\0';strcat(filenames[i],ptr->d_name);filenames[i][len+strlen(ptr->d_name)]='\0';}qsort(filenames,count,sizeof(filenames[0]),cmp);for(i=0;i<count;i++)display(flag_param,filenames[i]);closedir(dir);if((flag_param&PARAM_L)==0)printf("\n");
}
int main(int argc,char **argv){int i,j,k,num;char path[PATH_MAX+1];char param[32];int flag_param=PARAM_NONE;struct stat buf;j=0;num=0;for(i=1;i<argc;i++){if(argv[i][0]=='-'){for(k=1;k<strlen(argv[i]);k++,j++){param[j]=argv[i][k];}num++;}}for(int i=0;i<j;i++){if(param[i]=='a'){flag_param|=PARAM_A;continue;}else if(param[i]=='l'){flag_param|=PARAM_L;continue;}else{printf("my_ls:invalid option -%c\n",param[i]);exit(1);}}param[j]='\0';if((num+1)==argc){strcpy(path,"./");path[2]='\0';display_dir(flag_param,path);return 0;}i=1;do{if(argv[i][0]=='-'){i++;continue;}else{strcpy(path,argv[i]);if(stat(path,&buf)==-1)my_err("stat",__LINE__);if(S_ISDIR(buf.st_mode)){if(path[strlen(argv[i])-1]!='/'){path[strlen(argv[i])]='/';path[strlen(argv[i])+1]='\0';}else path[strlen(argv[i])]='\0';display_dir(flag_param,path);i++;}else{display(flag_param,path);i++;}}} while (i<argc);return 0;
}
相关文章:
《Linux C编程实战》笔记:实现自己的ls命令
关键函数的功能及说明 1.void display_attribute(struct stat buf,char *name) 函数功能:打印文件名为name的文件信息,如 含义分别为:文件的类型和访问权限,文件的链接数,文件的所有者,文件所有者所属的组…...
Python个人代码随笔(观看无益,请跳过)
异常抛错:一般来说,在程序中,遇到异常时,会从这一层逐层往外抛错,一直抛到最外层,由最外层把错误显示在用户终端。 try:raise ValueError("A value error...") except ValueError:print("V…...
Unity中实现ShaderToy卡通火(总结篇)
文章目录 前言一、把卡通火修改为后处理效果1、在Shader属性面板定义属性接收帧缓存纹理2、在片元着色器对其纹理采样后,与卡通火相加输出请添加图片描述 二、我们自定义卡通火1、修改 _CUTOFF 使卡通火显示在屏幕两侧2、使火附近屏幕偏红色 前言 在之前的文章中&a…...
等保2.0的变化
1法律地位得到确认 《中华人民共和国网络安全法》第21条规定“国家实行网络安全等级保护制度”,要求“网络运营者应当按照网络安全等级保护制度要求,履行安全保护义务”;第31条规定“对于国家关键信息基础设施,在网络安全等级保护…...
漏洞复现-网神SecGate3600防火墙敏感信息泄露漏洞(附漏洞检测脚本)
免责声明 文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…...
ArkTS入门
代码结构分析 struct Index{ } 「自定义组件:可复用的UI单元」 xxx 「装饰器:用来装饰类结构、方法、变量」 Entry 标记当前组件是入口组件(该组件可被独立访问,通俗来讲:它自己就是一个页面)Component 用…...
JS中for循环之退出循环
我为大家介绍一下退出循环的两种方法 1.continue 退出本次循环,一般用于排除或者跳过某一个选项的时候,可以使用continue for(let i 0;i<5;i){if(i 3){continue}// 跳过了3console.log(i) //0 1 2 4}2.break 退出整个for循环,一般用于…...
《Global illumination with radiance regression functions》
总结一下最近看的这篇结合神经网络的全局光照论文。 论文的主要思想是利用了神经网络的非线性特性去拟合全局光照中的间接光照部分,采用了基础的2层MLP去训练,最终能实现一些点光源、glossy材质的光照渲染。为了更好的理解、其输入输出表示如下。 首先…...
华南理工C++试卷
诚信应考 , 考试作弊将带来严重后果! 《C程序设计试卷》 注意事项:1. 考前请将密封线内填写清楚; 2. 所有答案请答在试卷的答案栏上; 3.考试形式:闭卷 4. 本试卷共 五 大题,满分100分ÿ…...
0001.WIN7(64位)安装ADS1.2出现L6218错误
用了十多年的笔记本电脑系统出现问题,硬件升级重装以后安装ADS1.2。在编译代码的时候出现L6218错误。如下: 图片是从网上找的,我编译出错的界面没有保留下来。 首先,代码本身没有任何问题 ,代码在win7(32位)下编译没有…...
HBuilderX 配置 夜神模拟器 详细图文教程
在电脑端查看App的效果,不用真机调试,下载一个模拟器就可以了 --- Nox Player,夜神模拟器,是一款 Android 模拟器。他的使用非常安全,最重要的是完全免费。 一. 安装模拟器 官网地址: (yeshen.com) 二.配…...
10、神秘的“位移主题”
神秘的“位移主题” 1、什么是位移主题2、位移主题的消息格式3、位移主题是怎么被创建的4、什么地方会用到位移主题5、位移主题的删除机制 本章主题是:Kafka 中的内部主题(Internal Topic)__consumer_offsets。 __consumer_offsets 在 Kafka …...
【Linux】dump命令使用
dump命令 dump命令用于备份文件系统。使用dump命令可以检查ext2/3/4文件系统上的文件,并确定哪些文件需要备份。这些文件复制到指定的磁盘、磁带或其他存储介质保管。 语法 dump [选项] [目录|文件系统] bash: dump: 未找到命令... 安装dump yum -y install …...
使用 TensorFlow 创建生产级机器学习模型(基于数据流编程的符号数学系统)——学习笔记
资源出处:初学者的 TensorFlow 2.0 教程 | TensorFlow Core (google.cn) 前言 对于新框架的学习,阅读官方文档是一种非常有效的方法。官方文档通常提供了关于框架的详细信息、使用方法和示例代码,可以帮助你快速了解和掌握框架的使用。 如…...
vue实现悬浮窗拖动的自定义指令
首先在自己的项目根目录下建一个 src --> config --> drag.js 然后在main.js中全局引入 //鼠标拖动 import drag from /config/drag; Vue.use(drag); drag.js文件相关代码 import Vue from vue; //使用Vue.directive()定义一个全局指令 //1.参数一:指令的…...
gitee(ssh)同步本地
一、什么是码云 gitee Git的”廉价平替” > 服务器在国内,运行不费劲 在国内也形成了一定的规模 git上的一些项目插件等在码云上也可以找得到 二、创建仓库 三、删除仓库 四、仓库与本地同步 > 建立公钥 五、把仓库同步到本地 六、在本地仓库中创建vue项目…...
Redis新数据类型-Bitmaps
目录 Bitmaps 简介 命令 1. setbit (1) 格式 (2) 实例 2. getbit (1) 格式 (2) 实例 3. bitcount (1) 格式 (2) 实例 4. bitop (1) 格式 (2) 实例 我的其他博客 Bitmaps 简介 Bitmaps 是 Redis 的一种新数据类型,它是一种用于存储位信息的数据结构&…...
web前端之vue组件传参、各种传参的不同写法、语法糖
MENU vue2refemit vue3语法糖refemit(一)语法糖(二) vue2 refemit 子组件 <template><div><el-dialogtitle"新增":visible.sync"dialogFormVisible"close"handleClose"><el-form :model"form"><el-form…...
基于Nexus搭建Maven私服基础入门
什么是Nexus?它有什么优势? 要了解为什么需要nexus的存在,我们不妨从以下几个问题来简单了解一下: 为什么需要搭建私服?如果没有私服会出现什么问题? 对于企业开发而言,如果没有私服,我们所有…...
JavaScript自执行函数:用途、好处
JavaScript中的自执行函数是一个常见的编程技巧,它可以在特定的场景中发挥重要作用。本文将介绍自执行函数的用途、好处,并提供代码示例进行说明。 引言 在JavaScript编程中,自执行函数是一种特殊的函数调用方式,它能够在定义后…...
Git使用无法拉取
错误提示: error setting certificate verify locations: CAfile: C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt CApath: none 问题原因: 这个问题是因为git配置里crt证书的路径不正确导致的 解决办法: 这个路径配置是在C:\Pro…...
来聊聊CAS
什么是CAS CAS全称Compare-And-Swap,是一种无锁编程算法,即比较当前的值与旧值是否相等若相等则进行修改操作(乐观锁机制),该类常用于多线程共享变量的修改操作。而其底层实现也是基于硬件平台的汇编指令,JVM只是封装其调用仅此而…...
【EventBus】EventBus源码浅析
二、EventBus源码解析 目录 1、EventBus的构造方法2、订阅者注册 2.1 订阅者方法的查找过程2.2 订阅者的注册过程1. subscriptionsByEventType 映射:2. typesBySubscriber 映射:2.3 总结订阅者的注册过程 3、事件的发送 3.1 使用Post提交事件3.2 使用p…...
Buck电源设计常见的一些问题(二)MOS管炸机问题
MOS管炸机问题 1.概述2.MOS管的相关参数3.过电压失效4.过电流失效5.静电放电和热失效1.概述 在我们做电源产品或者电机控制器时候,经常会坏MOS管。我相信90%以上的硬件工程师在职场生涯中都会遇到这类问题。然而这类问题也总是让人防不胜防。经常我们都会开玩笑的说,没烧过管…...
Javascript高频面试题
系列文章目录 文章目录 系列文章目录前言1.JavaScript常见数据类型null 和 undefind区别symbol(ES6新增)、bigInt(ES10新增) 2.JavaScript判断数据类型的方式3. 和 区别,分别在什么情况使用?4.变量声明 va…...
锁--07_2---- index merge(索引合并)引起的死锁
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 案例分析生产背景死锁日志表结构执行计划 EXPLAN为什么会用 index_merge(索引合并)为什么用了 index_merge就死锁了解决方案注:M…...
后端打印不了trace等级的日志?-SpringBoot日志打印-Slf4j
在调用log变量的方法来输出日志时,有以上5个级别对应的方法,从不太重要,到非常重要 调用不同的方法,就会输出不同级别的日志。 trace:跟踪信息debug:调试信息info:一般信息warn:警告…...
声明式编程Declarative Programming
接下来要介绍第五种编程范式 -- 声明式编程。分别从它的优缺点、案例分析和适用的编程语言这三个方面来介绍这个歌编程范式。 声明式编程是一种编程范式,其核心思想是通过描述问题的性质和约束,而不是通过描述解决问题的步骤来进行编程。这与命令式编程…...
人工智能与天文:技术前沿与未来展望
人工智能与天文:技术前沿与未来展望 一、引言 随着科技的飞速发展,人工智能(AI)在各个领域的应用越来越广泛。在天文领域,AI也发挥着越来越重要的作用。本文将探讨人工智能与天文学的结合,以及这种结合带…...
JeecgBoot 框架升级至 Spring Boot3 的实战步骤
JeecgBoot 框架升级 Spring Boot 3.1.5 步骤 JEECG官方推出SpringBoot3分支:https://github.com/jeecgboot/jeecg-boot/tree/springboot3 本次更新由于属于破坏式更新,有几个生态内的组件,无法进行找到平替或无法升级,目前尚不完…...
青岛模板网站建设价格/重庆seo顾问
更新源列表 打开"终端窗口",输入"sudo apt-get update" 安装ssh 打开"终端窗口",输入"sudo apt-get install openssh-server"-->回车-->输入"y"-->回车-->安装完成。 查看ssh服务是否启动…...
工作室做网站流程/东莞网站营销
不说废话----------> 1.如果是切四个角的圆角,代码示例: self.picImage.layer.cornerRadius 8; self.picImage.layer.masksToBounds YES; 2.如果是四个角中的某几个角,一个,两个,或者3个,代码示例(切的左下,和右下): UIBezierPath *maskPath [UIBezierPath bezierPathWit…...
网站建设方案项目书/小红书seo软件
一、是什么 在以前文章 (opens new window)中,我们了解到生命周期定义 生命周期(Life Cycle)的概念应用很广泛,特别是在经济、环境、技术、社会等诸多领域经常出现,其基本涵义可以通俗地理解为“从摇篮到坟墓”(Cradle-to-Grave)的整个过程 跟Vue一样,React整个组件…...
wordpress 调用摘要/网络推广需要多少费用
这道题其实利用的就是这样一个事实,如果b|a,c|b,那么c|a,于是就可以利用动态规划算法. 当算法运行到第i个时,如果它能整除第j个,即nums[i] % nums[j] 0,且在j处之前有N个可被j整除的,那么在第…...
网站建设优化重庆/百度产品推广
内建函数 标识id 返回对象的唯一标识,CPython返回内存地址 哈希hash 返回一个对象哈希 类型type 返回对象的类型 类型转换 float() int() bin() hex() oct() bool() list() tuple() dict() set() complex() bytes() bytearray() 输入 input([prompt]) 接收用户输入&…...
asp做登入网站/seo网站推广目的
前言在我们日常的程序开发中,或多或少会遇到一些加密/解密的场景,比如在一些接口调用的过程中,我们(Client)不仅仅需要传递给接口服务(Server)必要的业务参数,还得提供Signature&…...