初识C语言·文件操作

目录

1 关于文件

i)文件的基本知识

ii)数据文件的分类

2 文件打开和关闭

i)流和标准流

ii)文件指针

iii)文件打开和关闭

3 文件的顺序读写

i) fgetc fputc

ii) fgets fputs

iii) fscanf fprintf

iv) fwrite fread

4 对比一组函数 scanf/fscanf/sscanf/printf/fprintf/sprintf  

5 文件的随机读写

6 文件读取结束的判定

7 文件缓冲区


1 关于文件

i)文件的基本知识

在电脑中文件是随处可见的,那你思考过为什么存在“文件”吗?当我们运行程序的时候,程序一旦结束,在内存中存储的数据也会被销毁,我们如果想要保存数据,以方便下一次使用的话,就需要用到文件,也就是说,文件是可以用来保存数据的

那什么是文件呢?从文件的功能性分类的话,文件可以分为程序性文件和数据文件程序性文件包括源文件(.c后缀),目标文件(windows后缀为.obj),可执行程序(windows后缀为.exe),我们本章着重介绍的是数据文件,程序文件会在后面的预编译章节介绍。在之前的章节我们处理数据的输入输出都是在终端处理的,如键盘,电脑屏幕,但有点时候我们会把信息输入到磁盘里面,读取数据的时候让磁盘输入数据给内存,在从内存中读取数据,计算机读取数据分为好几个等级,从速度快慢分为寄存器,缓存,内存,硬盘等等,那么本场要学习的就是如何从磁盘从读取数据。

要使用文件,我们肯定要知道文件标识是由什么组成的,⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀,例如c:\code\test.txt,就是一个完整的文件名,文件路径是c:\code\,文件名主干是test,文件后缀就是txt,为了方便起见,我们一般把文件标识称作为文件名。

ii)数据文件的分类

数据文件被分为二进制文件文本文件,有的文件创建好了之后不是给使用者看的,是给计算机看的,但是计算机只能识别二进制的1 0,所以会有二进制文件,那么同理可得,文本文件就是给使用者看的,如果当你使用了记事本打开一个文件发现全是乱码,那么它八九不离十的是二进制文件了。

二进制文件是数据在内存中不加转化,直接输出到外存的文件,数据文件需要经过ASCII码值的转化,再输出到外存,所以以ASCII码值存储的文件都是文本文件。

那么一个数据是怎么在内存中存储的呢?

字符一律以ASCII码值的形式存储,数值类型的数据可以用二进制的形式存储也可以用ASCII码值的形式存储,以10000来举个例子,10000的二进制是这样的,(VS2019测试)如果直接以二进制的形式存储,就只会占4个字节,如果是ASCII码值的形式存储,那么就会占5个字节,1占一个字节,其余的每个0占一个字节

00000000 00000000 00100111 00010000

当我们使用二进制存储的时候,10000的二进制存储就会变为00 00 27 10,那么因为VS是小端存储,所以屏幕上看到的就是10 27 00 00

int main()
{int a = 10000;FILE* pf = fopen("data.txt", "wb");fwrite(&a, 4, 1, pf);fclose(pf);pf = NULL;return 0;
}

使用fwrite函数创建该文件,并且以二进制的形式存入,最后我们使用二进制的方式打开该文件,得到的就是:

2 文件打开和关闭

i)流和标准流

计算机输出数据和输入数据的时候需要外接到同设备,而通过不同的外接设备输入输出的数据的时候操作都不一样,那么计算机为了简化这一过程,就引用了流的概念,可以理解为计算机将数据不管三七二十一的一股脑给丢进去一个地方,计算机需要数据的时候就去里面拿就行了,那个地方就是流,C语言一般画面,文件,键盘的输入输出的时候都是通过流完成的,那么我们要使用流或者是输入数据到流里面,就需要打开流,使用完再关闭流。

可是实际上我们之前写代码的时候并没有过打开流关闭流这个操作,这是因为C语言默认打开了三个流,这三个流被称为标准流,stdin,stdout,stderr

stdin被称为标准输入流,大多数情况从键盘输入,scanf使用的时候就需要使用到这个流。

stdout被称为标准输出流,大多数情况从屏幕输出,printf使用的时候就需要使用到这个流。

stderr被称为标准错误流,大多数情况写也是从屏幕输出的。

当然,流也是由类型的,这三个流的类型是FILE*,FILE的英文意思就是文件,也就是文件指针,C语言中,FILE*的使用也是用来维护各种流的使用的。

ii)文件指针

文件类型指针就是FILE*,简称文件指针,而每个使用的文件在内存中都开辟了一块文件信息区,文件的相关信息,而这些信息保存在一个结构体变量里面,这个结构体变量就是FILE*,在vs2013关于FILE*的声明是这样的:

struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_tmpfname;};
typedef struct _iobuf FILE;

   创建了一个结构体变量_iobuf,最后重命名为了FILE,而在VS2022声明就没有那么详细了,VS2022的的声明如下:

当然我们只需要关心怎么用FILE*就行,至于文件指针的源码,是不用了解那么多的,我们使用FILE*访问文件信息区的时候就可以找到文件的相关信息,也就是说我们可以利用文件指针间接找到与该文件相关的文件

iii)文件打开和关闭

 文件打开的时候会返回一个指针指向该文件的文件信息区,也就是建立了指针和文件的关系,那么我们使用完之后就应该关闭文件,C语言中打开文件使用的是fopen函数,关闭文件使用的是fclose函数,f就是file,open就是打开的意思,close就是关闭的意思。

//打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件
int fclose ( FILE * stream );

这是他们的参数,fopen的第一个参数就是文件名,第二个是打开模式,fclose参数就是文件指针,也就是用来接受fopen函数返回的文件指针。

文件的打开模式有许多种,如下:

模式有很多种,感兴趣可以自行使用一下。注意如果文件不存在的话,就会创建一个这样的文件放在该代码的路径下,这是相对路径,如果想要指定路径放的话,就是绝对路径:

	FILE* pf = fopen("C:\\Users\\users\\OneDrive\\data.txt", "w");

只需要在文件名前面加上文件路径就行了,但是要注意的是\要写两个,这是前面转义字符的知识,为了防止\和其他字符结合形成转义字符。

但是多次是用"w"打开文件的时候,每次打开都会先让文件里面的内容清空,这个小现象需要注意一下。


3 文件的顺序读写

i) fgetc fputc

fgetc是字符输入函数,fputc是字符输出函数,均适用于所有文件输入输出流。

int main()
{FILE* pf = fopen("data.txt", "w");assert(pf);char array[26] = { 0 };for (int i = 0; i < 26; i++){fputc('a' + i, pf);}for (int j = 0; j < 26; j++){array[j] = fgetc(pf);}for (int j = 0; j < 26; j++){printf("%c ", array[j]);}fclose(pf);pf = NULL;return 0;
}

 我们创建好文件指针之后,需要判断一下指针是不是空指,最后还要关闭指针,并且置为空指针,这里和动态开辟函数类似,我们给文件里面存好数据之后,第一遍是打印不出来我们想要的26个字符的,因为这里的文件打开模式是w,是写入,那么运行第二次时,我们把w换成r就fgetc函数就开始操作了。

如果fgetc函数读取失败返回或者是读取到了文件尾就会返回eof,也就是文件结束标志,那么函数就结束了,如果fputc写入失败的话也是返回的eof。

在读取文件的时候,字符函数都是一个字符一个字符的读取或者写入的,当读取完一个字符后,光标往后移动,指向下一个字符,所以如果不用for循环的话,想要打印就需要重复写这两行代码:

	int ch = fgetc(pf);printf("%c ", ch);

实际上fgetc函数等效于getc函数,只是getc函数在库中可以等效为宏。


ii) fgets fputs

fgets是文本行输入函数,fputs是文本行输出函数,均适用于所有输入输出流,文本行其实就是字符串。

fgets和gets函数是非常不像的,fgets函数有三个参数:

char * fgets ( char * str, int num, FILE * stream );

fgets函数会从流里面读取num -1个字符,并将这些字符存到指针str里面,且最后一个元素置为\0,读取过程中如果碰到了换行符 文件末尾 或者是读取了num - 1个字符,以先到者为准,读取num - 1个字符,第num个字符是\0,如果读取失败,返回的是空指针,如果读着读着莫名读取到了文件尾,那么返回的就是eof。

fputs就没有什么好介绍的了,就是将字符串放进去而已,puts输出之后会自动换行,fputs不会,这是他们的区别。

参考代码:

int main(){FILE* pf = fopen("data.txt", "r");assert(pf);char arr[10] = { 1,2,3,4,5,6,7,8,9,10 };fputs("xxxxxxx", pf);fgets(arr, 6, pf);for (int i = 0; i < 6; i++){printf("%c ", arr[i]);}return 0;
}

iii) fscanf fprintf

fscanf fprintf这两个函数是格式化输入输出函数,也就是要用到占位符,适用于所有流,可以这么说scanf能做的,fscanf都可以做,fprintf同理,fscanf就比scanf多了一个参数,fscanf是从文件中读取数据,如果第一个参数是stdin,也就是标准输入流的话,就是从键盘里面输入数据了,fprintf同理可得,如果第一个参数是stdout,也就是标准输出流的话,就是从屏幕上打印,这是函数原型:

int fscanf ( FILE * stream, const char * format, ... );
int fprintf ( FILE * stream, const char * format, ... );
int main()
{FILE* pf = fopen("data.txt", "r");assert(pf);char ch = 0;//fputs("1 2 3 4 5 6 7 8 9 10", pf);fscanf(pf, "%c",&ch);printf("%c", ch);fclose(pf);pf = NULL;return 0;
}

这就是从文件里面读取数据,如果我们想要从键盘读取,只需把流换成stdin就行了,那么这是读文件的操作,如果是写文件,就可以用到fprintf:

int main()
{struct St {int age;char name[20];double score;};FILE* pf = fopen("data.txt", "r");assert(pf);struct St st = { 10,"zhangsan",99.9};fscanf(pf, "%d %s %lf", &(st.age), st.name, &(st.score));fprintf(stdout, "%d %s %.1f", st.age, st.name, st.score);fclose(pf);pf = NULL;return 0;
}

iv) fwrite fread

fwrite fread是二进制输入输出函数,只适用于文件    

 这是cplusplus里面的记述,fwrite有四个参数,意思就是从流里面写进去count个大小为size的元素,用到的是指针,文章最开始就用了这个函数,存的是10000,因为只用存一个10000,所以第三个参数是1,fread同理可得。

因为是二进制输入输出函数,所以写入的时候用到的是wb,读取的时候用到的是rb:

int main()
{FILE* pf = fopen("data.txt", "wb");struct St{int age;//10char name[20];//zhangsandouble score;//99.9}st = {10,"zhangsan",99.9};fwrite(&st,sizeof(st),1,pf);fclose(pf);pf = NULL;return 0;
}

这是我们用二进制的方式写进了文件里面:

文本文件写进去是这样的:

可以看到有明显的差别,因为字符都是以ASCII码值的形式存储,所以结果不变,但是其他数据就变化大了,当然我们是看不懂的,计算机看得懂,比如用fread函数就看懂了:

int main()
{FILE* pf = fopen("data.txt", "rb");struct St{int age;//10char name[20];//zhangsandouble score;//99.9}st;fread(&st, sizeof(st), 1, pf);printf("%d %s %lf", st.age, st.name, st.score);fclose(pf);pf = NULL;return 0;
}

4 对比一组函数 scanf/fscanf/sscanf/printf/fprintf/sprintf  

scanf printf都是标准流的格式化函数,fscanf fprintf是所有流的格式化函数,scanf printf能做的

fscanf fprintf都可以做,可以理解为fscanf fprintf包含了scanf printf,前面介绍了这两组函数,这里就不介绍了

sscanf sprintf:

sprintf的作用是将格式化的数据放到指针指向的空间里面,sscanf的作用是从指针指向的空间种读取格式化的数据(代码如下):

int main()
{struct XY{char name[10];int age;float score;}xy = {"ziyou",18,100.8};char arr[100] = { 0 };sprintf(arr, "%s %d %f", xy.name, xy.age, xy.score);printf("%s", arr);return 0;
}

创建好一个结构体变量之后,再创建一个字符数组用来存放sprintf输出的数据,那么格式化的占位符是必不可少的,因为数组名是首元素地址,也就是指针,所以写上了arr,最后打印出来如下:

因为我在fprintf写参数的时候已经空格了,空格也会输出进去,所以打出来也是带空格的。

int main()
{struct XY{char name[10];int age;float score;}xy = { "zhangsan",12,12.2 }, tem = { 0 };char arr1[100] = { 0 };sprintf(arr1, "%s %d %f", xy.name, xy.age, xy.score);sscanf(arr1, "%s %d %f", tem.name, &(tem.age), &(tem.score));printf("%s %d %f", tem.name,tem.age,tem.score);return 0;
}

sscanf是从arr1里面读取数据,然后放在了结构体里面,sprintf是输出到arr1里面,相较于前面的两组函数,这组函数是没有用到文件指针的,但是指针是用到了,由此可见指针的重要性。


5 文件的随机读写

文件的随机读写介绍三个函数 fseek ftell rewind:

int main()
{FILE* pf = fopen("data.txt", "r");assert(pf);for (int i = 0; i < 26; i++){fputc('a' + i, pf);}char ch = fgetc(pf);printf("%c ", ch);//ach = fgetc(pf);printf("%c ", ch);//bch = fgetc(pf);printf("%c ", ch);//cch = fgetc(pf);printf("%c ", ch);//dch = fgetc(pf);printf("%c ", ch);//efclose(pf);pf = NULL;return 0;
}

这段代码的意思就是文件里面有英文字母26个,使用fgetc函数一个一个读取,最后的打印结果应该是a b c d e,运行到d的时候文件指针,也就是光标,指向的是e,那么如果我们想要让文件指针回到最开始的位置,使得最后的打印结果还是a,就可以用到rewind:

int main()
{FILE* pf = fopen("data.txt", "r");assert(pf);for (int i = 0; i < 26; i++){fputc('a' + i, pf);}char ch = fgetc(pf);printf("%c ", ch);//ach = fgetc(pf);printf("%c ", ch);//bch = fgetc(pf);printf("%c ", ch);//cch = fgetc(pf);printf("%c ", ch);//drewind(pf);ch = fgetc(pf);printf("%c ", ch);//efclose(pf);pf = NULL;return 0;
}

rewind的参数就是一个文件指针,所以想要让文件指针回到起始位置用到一个rewind就行了。

那么如果我们想指定位置开始读取呢?这里用到的函数就是fseek函数,随机读取函数,可以

使文件指针指向最开始到结尾的任意位置:

它有3个参数,第一个参数是文件指针,第二个是偏移量,第三个是计算偏移量的起始位置,偏移量很好理解,光标指向第一个字符的时候偏移量就是0,往后一次偏移量增加1,那么第三个参数写的时候有三个选择,SEEK_SET,SEEK_CUR,SEEK_END,CUR就是当前位置的意思,SET就是起始位置的意思,END就是末尾的意思,所以移动光标的时候需要先确定好计算偏移量的起始位置,然后确定偏移量,从起始位置开始,往左计算偏移量就是负数,往右计算就是正数。

那么如果我懒我不想计算偏移量,我想直接知道现在的偏移量呢?只需要用ftell函数就是,参数就是文件指针,这个函数的返回值就是当前的偏移量。

如下:

int main()
{FILE* pf = fopen("data.txt", "r");assert(pf);for (int i = 0; i < 26; i++){fputc('a' + i, pf);}char ch = fgetc(pf);printf("%c ", ch);//ach = fgetc(pf);printf("%c ", ch);//bch = fgetc(pf);printf("%c ", ch);//cch = fgetc(pf);printf("%c ", ch);//dint num = ftell(pf);printf("%d ", num);//rewind(pf);fseek(pf, -2, SEEK_CUR);ch = fgetc(pf);printf("%c ", ch);//cfclose(pf);pf = NULL;return 0;
}

6 文件读取结束的判定

文件读取结束分为正常读取到了结尾和读到一半遇到错误了,那么我们如何判断文件是不是正常结束呢?这里用到的函数是feof,但是使用feof的前提是文件已经读取完了(不管是哪种结束),需要注意的是feof不能用来判断文件是不是读取结束了,这是前提,不要搞混淆了。

feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束。

同理得ferror的作用是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到错误结束。

当读取文本文件的时候,fgetc如果正常读取结束返回的是eof,fgets如果正常读取结束返回的是NULL,这也是它们的区别。

当读取二进制文件的时候,判断fread返回的值是否小于文件中的实际字符数,因为fread函数的返回值是读取到的个数。

文本文件代码示范:

int main(void)
{int c; // 注意:int,⾮char,要求处理EOFFILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环{ putchar(c);}//判断是什么原因结束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);
}

二进制代码示范:

enum { SIZE = 5 };
int main(void)
{double a[SIZE] = {1.,2.,3.,4.,5.};FILE *fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin","rb");size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组if(ret_code == SIZE) {puts("Array read successfully, contents: ");for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);putchar('\n');} else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);pf = NULL;
}

7 文件缓冲区

前面提到程序从计算机中读取数据的时候分为了好几个层次,其中包括看文件缓冲区,那么缓冲区的作用是是什么呢?
程序运行的时候内存会为每个正在使用的文件开辟缓冲区,读取数据的时候,数据就会往先往里面放,直到缓冲区装满了,才会一并送到磁盘中,相同的,如果程序需要输入数据,系统会将输入的数据放到输入缓冲区里面区,直到输入缓冲区满了,才会从磁盘输入到程序里面去。

那么缓冲区存在的意义是什么呢?

有人会说为什么不输出一个就给磁盘一个,实际上调用函数的时候,计算机底层也会被调用起来,所以看似工作的有程序,内存等,实际上还有计算机各个部分都是调用起来的,如果输出一个就传送一个出去,那其他部分的工作就是进行不下去,所以缓冲区存在的意义就是为了提高工作效率。

int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)了printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭⽂件的时候,也会刷新缓冲区pf = NULL;return 0;
}

我们先給文件一串字符串,然后让程序休眠10秒,也就是Sleep,Sleep需要引用到的头文件是windows,程序休眠的这10秒,我们打开文件就会发现abcdef是没有被写进去的,这个时候我们使用fflush刷新一下缓冲区,再去打开文件,就会发现abcdef写进去了,这个时候关闭文件,需要注意的是关闭文件的时候缓冲区也会被刷新,验证的方法就是把fclose提前,不使用fflush,这个时候也会发现文件过了10秒之后abcdef出现在了文件里面。

正因为缓冲区的存在,在进行关于文件类操作的时候,需要刷新缓冲区或者是关闭文件,不然很可能导致读写文件出现问题。


感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658996.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware虚拟机安装macOS

VMware虚拟机安装macOS 文章目录 VMware虚拟机安装macOS先看效果一、准备工作①&#xff1a;镜像资源下载②&#xff1a;虚拟机③&#xff1a;安装macOS所必要的插件 二、开始安装①&#xff1a;创建新的虚拟机②&#xff1a;自定义硬件③&#xff1a;开启虚拟机 先看效果 一、…

新东方财报解读:新一轮增长逻辑或蕴于电商业务?

从财报表现来看&#xff0c;教育市场的元气在持续提升。 近日&#xff0c;新东方、好未来等上市公司陆续公布了2023年9-11月的业绩表现。其中&#xff0c;好未来实现营收3.7亿美元&#xff0c;同比增长60.5%&#xff1b;归母净亏损2394.6万美元&#xff0c;亏幅同比收窄53.6%。…

Redis常见数据类型[上]

目录 前言&#xff1a; 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 数据结构和内部编码 内部编码&#xff1a; 单线程架构 引出单线程模型&#xff1a; 为什么单线程还这么快&#xff1f; String字符串 字符串数据类型&#xff1a; 常见命令&#xff1a; S…

嵌入式学习第十五天!(内存管理、链表)

1. 内存管理&#xff1a; 1. malloc void *malloc(size_t size); 功能&#xff1a;申请堆区空间 参数&#xff1a;size&#xff1a;申请堆区空间的大小 返回值&#xff1a;返回获得的空间的首地址&#xff0c;失败返回NULL 2. free void free(void *ptr); 功能&#xff1a;释…

信效度检验2(SPSS

目录 1.效度介绍&#xff1a;2.效度检验&#xff1a;小结&#xff1a; 1.效度介绍&#xff1a; 用于研究题项设计是否合适 2.效度检验&#xff1a; 点击 降维->因子 把涉及到因变量的问题放入即可&#xff1a; 勾选&#xff1a; 得到输出结果&#xff1a; KMO值 0.7…

如何使用wireshark解析二进制文件

目录 目录 1.将已有的packet raw data按照下面格式写入文本文件中 a. Raw IP packet b. Ethernet packet 2.用wiershark导入hex文件 3.设置对应的packet类型 a. Raw IP packet b. Ethernet packet 1.将已有的packet raw data按照下面格式写入文本文件中 a. Raw IP pac…

汽车燃油泵数据分析:全球市场的年复合增长率将达到10%左右

燃油泵是汽车配件行业的专业术语。是电喷汽车燃油喷射系统的基本组成之一&#xff0c;位于车辆油箱内部&#xff0c;燃油泵在启动和发动机运转时工作&#xff0c;如果发动机停止而点火开关仍处于ON时&#xff0c;HFM-SFI控制模块关闭燃油泵的电源&#xff0c;以避免意外点火。 …

OpenCV与机器学习:使用opencv实现KNN

使用opencv实现KNN 前言OpenCV实现KNN生成随机数据使用matplotlib绘制数据OpenCV用于KNN训练生成新数据并观察预测 前言 KNN算法&#xff0c;即K-Nearest Neighbor&#xff0c;是一种简单的机器学习算法。它的基本思想是&#xff1a;如果一个样本在特征空间中的K个最相似&…

标注数据集 --labelimg

前言&#xff1a;我们想要训练自己的数据集时&#xff0c;通常需要自己标注数据集。无论是标注成yolo可识别的txt格式还是voc数据集的xml格式。使用labelimg标注都是一个不错的选择。 下面我们就从创建环境&#xff0c;使用labelimg进行标注两个方面来说明。 1.创建labelimg环境…

ADI 配合 USRP 使用的相控阵天线 cn0566

相控阵天线 在这里插入图片描述

Python实战:爬取微博,获取南京地铁每日客流数据

在这篇文章中&#xff0c;我们将使用 Python 进行网络爬虫&#xff0c;爬取微博上的南京地铁每日客流数据。 一、分析网页 在“南京地铁”微博主页搜索“昨日客流”关键词&#xff0c;搜索到每天发布的昨日客流数据。 “南京地铁”微博主页地址https://weibo.com/u/26382762…

基于视觉的移载协作机器人机床上下料末端纠偏算法

摘 要 针对复合机器人在机床上下料中的定位方法,本文主要关注识别机床卡盘和末端作业面的定位。首先分 析了复合机器人在机床上下料过程中的工作原理及其基本结构,包括 AGV (自动导引车)和协作机器人 的功能及特点。然后,详细阐述了如何使用视觉系统和纠偏算法来…

京东采销急眼,隔空喊话“针对”拼多多,焦虑之下为哪般?

农历新年将至&#xff0c;无论是线下各大商超还是线上电商平台&#xff0c;皆为年终大促而“忙的不亦乐乎”&#xff0c;尤其是近期发生的京东采销人员在直播间向拼多多喊话&#xff0c;“恳请拼多多停止屏蔽&#xff0c;恳请拼多多直接比价”&#xff0c;更是将年底这场朴实无…

flink cdc,standalone模式下,任务运行一段时间taskmanager挂掉

在使用flink cdc&#xff0c;配置任务运行&#xff0c;过了几天后&#xff0c;任务无故取消&#xff0c;超时&#xff0c;导致taskmanager挂掉&#xff0c;相关异常如下&#xff1a; 异常1&#xff1a; did not react to cancelling signal interrupting; it is stuck for 30 s…

ElasticSearch基础用法

什么是ElasticSearch? Elasticsearch是一个开源的、分布式的、实时的搜索和分析引擎。它允许用户近乎实时地存储、检索大量数据&#xff0c;并能够高效地对其进行全文搜索、聚合和分析。 部署ES和Kibana 通常采用docker-compose部署ES&#xff08;ElasticSearch&#xff09;服…

寒假思维训练day17 C. Equal Frequencies

不知不觉已经过了差不多一个月了&#xff0c;坚持一件事情还是有点收获的&#xff0c;今天更新一道1600的构造。 寒假训练计划day17 摘要&#xff1a; Part1 题意 Part2 题解 (有数学推导&#xff0c;latex形式) Part3 代码 (C版本&#xff0c;有详细注释) Part4 我对构造题…

基于YOLOv7算法的高精度实时安全帽和背心目标检测系统(PyTorch+Pyside6+YOLOv7)

摘要&#xff1a;基于YOLOv7算法的高精度实时安全帽和背心目标检测系统可用于日常生活中检测与定位安全帽和安全背心&#xff0c;此系统可完成对输入图片、视频、文件夹以及摄像头方式的目标检测与识别&#xff0c;同时本系统还支持检测结果可视化与导出。本系统采用YOLOv7目标…

【电子科技大学】计算机高级图形学总复习

第一章&#xff1a;绪论 图形学和图像学 走样的原因和反走样 走样指的是&#xff1a;用离散量表示连续量引起的失真 反走样&#xff1a;为了提高图形的显示质量&#xff0c;需要减少或消除因走样带来的阶梯形或闪烁的效果&#xff0c;用于减少或消除这种效果的方法称为反走样…

【51单片机Keil+Proteus8.9】门锁控制电路

门锁控制电路 二、设计思路 电路设计 1.电源部分&#xff1a;使用BATTERY为整个电路提供电源&#xff0c;可以在电路中加入一个电 源开关&#xff0c;以便控制电源的开启和关闭。 2.处理器部分&#xff1a;使用AT89C51芯片作为主处理器&#xff0c;通过编写程序实现门锁的 …

《Lua程序设计》-- 学习9

迭代器和泛型for 迭代器和闭包 迭代器&#xff08;iterator&#xff09;是一种可以让我们遍历一个集合中所有元素的代码结构。在Lua语言中&#xff0c;通常使用函数表示迭代器&#xff1a;每一次调用函数时&#xff0c;函数会返回集合中的“下一个”元素。 一个闭包就是一个…