第11章 字符串和字符串函数
本章介绍以下内容:
函数:gets()、gets_s()、fgets()、puts()、fputs()、strcat()、strncat()、strcmp()、strncmp()、strcpy()、strncpy()、sprintf()、strchr()
创建并使用字符串
使用C库中的字符和字符串函数,并创建自定义的字符串函数
使用命令行参数
字符串是C语言中最有用、最重要的数据类型之一。虽然我们一直在使用字符串,但是要学的东西还很多。C 库提供大量的函数用于读写字符串、拷贝字符串、比较字符串、合并字符串、查找字符串等。通过本章的学习,读者将进一步提高自己的编程水平。
11.1 表示字符串和字符串I/O
字符串是以空字符(\0)结尾的char类型数组。
puts()函数也属于stdio.h系列的输入/输出函数。但是,与printf()不同的是,puts()函数只显示字符串,而且自动在显示的字符串末尾加上换行符。
11.1.1 在程序中定义字符串
1.字符串字面量(字符串常量)
用双引号括起来的内容称为字符串字面量(string literal),也叫作字符串常量(string constant)。
双引号中的字符和编译器自动加入末尾的\0字符,都作为字符串储存在内存中
从ANSI C标准起,如果字符串字面量之间没有间隔,或者用空白字符分隔,C会将其视为串联起来的字符串字面量。
如果要在字符串内部使用双引号,必须在双引号前面加上一个反斜杠(\)
字符串常量属于静态存储类别(static storage class),这说明如果在函数中使用字符串常量,该字符串只会被储存一次,在整个程序的生命期内存在,即使函数被调用多次。用双引号括起来的内容被视为指向该字符串储存位置的指针。这类似于把数组名作为指向该数组位置的指针。
printf()将打印该字符串首字符的地址(如果使用ANSI之前的实现,可能要用%u或%lu代替%p)
*"space farers"表示该字符串所指向地址上储存的值,应该是字符串*"space farers"的首字符。
2.字符串数组和初始化
一种方法是用足够空间的数组储存字符串。
const char m1[40] = "Limit yourself to one line's worth.";
const表明不会更改这个字符串。
这种形式的初始化比标准的数组初始化形式简单得多:
注意最后的空字符。没有这个空字符,这就不是一个字符串,而是一个字符数组。
在指定数组大小时,要确保数组的元素个数至少比字符串长度多1(为了容纳空字符)。所有未被使用的元素都被自动初始化为0(这里的0指的是char形式的空字符,不是数字字符0)
让编译器计算数组的大小只能用在初始化数组时。如果创建一个稍后再填充的数组,就必须在声明时指定大小。声明数组时,数组大小必须是可求值的整数。在C99新增变长数组之前,数组的大小必须是整型常量,包括由整型常量组成的表达式。
char crumbs[n]; // 在C99标准之前无效,C99标准之后这种数组是变长数组
字符数组名和其他数组名一样,是该数组首元素的地址。
还可以使用指针表示法创建字符串
const char * pt1 = "Something is pointing at me.";
该声明和下面的声明几乎相同:
const char ar1[] = "Something is pointing at me.";
pt1和ar1都是该字符串的地址。在这两种情况下,带双引号的字符串本身决定了预留给字符串的存储空间。尽管如此,这两种形式并不完全相同。
3.数组和指针
在数组形式中,ar1是地址常量。不能更改ar1,如果改变了ar1,则意味着改变了数组的存储位置(即地址)。可以进行类似ar1+1这样的操作,标识数组的下一个元素。但是不允许进行++ar1这样的操作。递增运算符只能用于变量名前(或概括地说,只能用于可修改的左值),不能用于常量。
该变量最初指向该字符串的首字符,但是它的值可以改变。因此,可以使用递增运算符。例如,++pt1将指向第 2 个字符(o)。
字符串字面量被视为const数据。由于pt1指向这个const数据,所以应该把pt1声明为指向const数据的指针。这意味着不能用pt1改变它所指向的数据,但是仍然可以改变pt1的值(即,pt1指向的位置)。如果把一个字符串字面量拷贝给一个数组,就可以随意改变数据,除非把数组声明为const。
总之,初始化数组把静态存储区的字符串拷贝到数组中,而初始化指针只把字符串的地址拷贝给指针。
4.数组和指针的区别
char heart[] = "I love Tillie!";
const char *head = "I love Millie!";
两者主要的区别是:数组名heart是常量,而指针名head是变量。
首先,两者都可以使用数组表示法
其次,两者都能进行指针加法操作:
但是,只有指针表示法可以进行递增操作:
假设想让head和heart统一,可以这样做:
head = heart; /* head现在指向数组heart */
这使得head指针指向heart数组的首元素。
但是,不能这样做:
heart = head; /* 非法构造,不能这样写 */
这类似于x = 3;和3 = x;的情况。赋值运算符的左侧必须是变量(或概括地说是可修改的左值)
另外,还可以改变heart数组中元素的信息:
数组的元素是变量(除非数组被声明为const),但是数组名不是变量
建议在把指针初始化为字符串字面量时使用const限定符
总之,如果不修改字符串,不要用指针指向字符串字面量。
5.字符串数组
图11.2 矩形数组和不规则数组
综上所述,如果要用数组表示一系列待显示的字符串,请使用指针数组,因为它比二维字符数组的效率高。但是,指针数组也有自身的缺点。mytalents 中的指针指向的字符串字面量不能更改;而yourtalentsde 中的内容可以更改。所以,如果要改变字符串或为字符串输入预留空间,不要使用指向字符串字面量的指针
11.1.2 指针和字符串
显示两个指针的值。所谓指针的值就是它储存的地址。mesg 和 copy 的值都是0x0040a000,说明它们都指向的同一个位置。因此,程序并未拷贝字符串。语句copy = mesg;把mesg的值赋给copy,即让copy也指向mesg指向的字符串
11.2 字符串输入
如果想把一个字符串读入程序,首先必须预留储存该字符串的空间,然后用输入函数获取该字符串。
11.2.1 分配空间
最简单的方法是,在声明时显式指明数组的大小:
char name[81];
11.2.2 不幸的gets()函数
gets()函数简单易用,它读取整行输入,直至遇到换行符,然后丢弃换行符,储存其余字符,并在这些字符的末尾添加一个空字符使其成为一个 C 字符串。它经常和 puts()函数配对使用,该函数用于显示字符串,并在末尾添加换行符。程序清单11.6中演示了这两个函数的用法。
问题出在 gets()唯一的参数是 words,它无法检查数组是否装得下输入行
如果输入的字符串过长,会导致缓冲区溢出(buffer overflow),即多余的字符超出了指定的目标空间。
11.2.3 gets()的替代品
1.fgets()函数(和fputs())
fgets()函数的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets()将读入n-1个字符,或者读到遇到的第一个换行符为止。
如果fgets()读到一个换行符,会把它储存在字符串中。这点与gets()不同,gets()会丢弃换行符。
fgets()函数的第3 个参数指明要读入的文件。如果读入从键盘输入的数据,则以stdin(标准输入)作为参数,该标识符定义在stdio.h中。
因为 fgets()函数把换行符放在字符串的末尾(假设输入行不溢出),通常要与 fputs()函数(和puts()类似)配对使用,除非该函数不在字符串末尾添加换行符。fputs()函数的第2个参数指明它要写入的文件。如果要显示在计算机显示器上,应使用stdout(标准输出)作为该参数。程序清单11.7演示了fgets()和fputs()函数的用法。
fputs()不在字符串末尾添加换行符
fputs()函数返回指向 char的指针。如果一切进行顺利,该函数返回的地址与传入的第 1 个参数相同。但是,如果函数读到文件结尾,它将返回一个特殊的指针:空指针(null pointer)。该指针保证不会指向有效的数据,所以可用于标识这种特殊情况。在代码中,可以用数字0来代替,不过在C语言中用宏NULL来代替更常见(如果在读入数据时出现某些错误,该函数也返回NULL)。
首先,如何处理掉换行符?一个方法是在已储存的字符串中查找换行符,并将其替换成空字符:
while (words[i] != '\n') // 假设\n在words中
i++;
words[i] = '\0';
其次,如果仍有字符串留在输入行怎么办?一个可行的办法是,如果目标数组装不下一整行输入,就丢弃那些多出的字符:
while (getchar() != '\n') // 读取但不储存输入,包括\n
continue;
空字符(或'\0')是用于标记C字符串末尾的字符,其对应字符编码是0。由于其他字符的编码不可能是 0,所以不可能是字符串的一部分。
空指针(或NULL)有一个值,该值不会与任何数据的有效地址对应。通常,函数使用它返回一个有效地址表示某些特殊情况发生,例如遇到文件结尾或未能按预期执行。
空字符是整数类型,而空指针是指针类型。两者有时容易混淆的原因是:它们都可以用数值0来表示。但是,从概念上看,两者是不同类型的0。另外,空字符是一个字符,占1字节;而空指针是一个地址,通常占4字节。
2.gets_s()函数
gets_s()只从标准输入中读取数据,所以不需要第3个参数。
如果gets_s()读到换行符,会丢弃它而不是储存它。
如果gets_s()读到最大字符数都没有读到换行符,会执行以下几步。首先把目标数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针。接着,调用依赖实现的“处理函数”(或你选择的其他函数),可能会中止或退出程序。
当输入与预期不符时,gets_s()完全没有fgets()函数方便、灵活。也许这也是gets_s()只作为C库的可选扩展的原因之一。鉴于此,fgets()通常是处理类似情况的最佳选择。
3.s_gets()函数
读取整行输入并用空字符代替换行符,或者读取一部分输入,并丢弃其余部分。既然没有处理这种情况的标准函数,我们就创建一个,在后面的程序中会用得上。
丢弃输入行余下的字符保证了读取语句与键盘输入同步。
11.2.4 scanf()函数
scanf()更像是“获取单词”函数,而不是“获取字符串”函数
无论哪种方法,都从第1个非空白字符作为字符串的开始。如果使用%s转换说明,以下一个空白字符(空行、空格、制表符或换行符)作为字符串的结束(字符串不包括空白字符)。如果指定了字段宽度,如%10s,那么scanf()将读取10 个字符或读到第1个空白字符停止(先满足的条件即是结束输入的条件)
图11.3 字段宽度和scanf()
scanf()函数返回一个整数值,该值等于scanf()成功读取的项数或EOF(读到文件结尾时返回EOF)。
根据输入数据的性质,用fgets()读取从键盘输入的数据更合适。例如,scanf()无法完整读取书名或歌曲名,除非这些名称是一个单词。scanf()的典型用法是读取并转换混合数据类型为某种标准形式。例如,如果输入行包含一种工具名、库存量和单价,就可以使用scanf()。否则可能要自己拼凑一个函数处理一些输入检查。如果一次只输入一个单词,用scanf()也没问题。
在%s转换说明中使用字段宽度可防止溢出
11.3 字符串输出
11.3.1 puts()函数
puts()函数很容易使用,只需把字符串的地址作为参数传递给它即可。
puts()在显示字符串时会自动在其末尾添加一个换行符。
用双引号括起来的内容是字符串常量,且被视为该字符串的地址。另外,储存字符串的数组名也被看作是地址。在第5个puts()调用中,表达式&str1[5]是str1数组的第6个元素(r),puts()从该元素开始输出。与此类似,第6个puts()调用中,str2+4指向储存"pointer"中i的存储单元,puts()从这里开始输出。
puts()如何知道在何处停止?该函数在遇到空字符时就停止输出,所以必须确保有空字符。
由于dont缺少一个表示结束的空字符,所以它不是一个字符串,因此puts()不知道在何处停止。它会一直打印dont后面内存中的内容,直到发现一个空字符为止。
11.3.2 fputs()函数
fputs()函数是puts()针对文件定制的版本。
fputs()函数的第 2 个参数指明要写入数据的文件。如果要打印在显示器上,可以用定义在stdio.h中的stdout(标准输出)作为该参数。
与puts()不同,fputs()不会在输出的末尾添加换行符。
line数组中的字符串显示在下一行
line数组中的字符串也显示在下一行
如果混合使用 fgets()输入和puts()输出,每个待显示的字符串末尾就会有两个换行符。这里关键要注意:puts()应与gets()配对使用,fputs()应与fgets()配对使用。
11.3.3 printf()函数
printf()也把字符串的地址作为参数
printf()不会自动在每个字符串末尾加上一个换行符。因此,必须在参数中指明应该在哪里使用换行符。例如:
printf("%s\n", string);
和下面的语句效果相同:
puts(string);
printf()的形式更复杂些,需要输入更多代码,而且计算机执行的时间也更长(但是你觉察不到)。
使用 printf()打印多个字符串更加简单。
11.4 自定义输入/输出函数
完全可以在getchar()和putchar()的基础上自定义所需的函数。
/* put1.c -- 打印字符串,不添加\n */
#include <stdio.h>
void put1(const char * string)/* 不会改变字符串 */
{
while (*string != '\0')
putchar(*string++);
}
用数组表示法编写这个函数稍微复杂些:
int i = 0;
while (string[i]!= '\0')
putchar(string[i++]);
要为数组索引创建一个额外的变量。
许多C程序员会在while循环中使用下面的测试条件:
while (*string)
使用带方括号的写法是为了提醒用户:该函数处理的是数组。
用const char * string可以提醒用户:实际参数不一定是数组。
11.5 字符串函数
ANSI C把这些函数的原型放在string.h头文件中。其中最常用的函数有 strlen()、strcat()、strcmp()、strncmp()、strcpy()和 strncpy() 还有sprintf()函数,其原型在stdio.h头文件中
11.5.1 strlen()函数
fit()函数把第39个元素的逗号替换成'\0'字符。puts()函数在空字符处停止输出,并忽略其余字符。然而,这些字符还在缓冲区中,下面的函数调用把这些字符打印了出来
所以put()显示该字符并继续输出直至遇到原来字符串中的空字符
11.5.2 strcat()函数
strcat()(用于拼接字符串)函数接受两个字符串作为参数。该函数把第2个字符串的备份附加在第1个字符串末尾,并把拼接后形成的新字符串作为第1个字符串,第2个字符串不变。strcat()函数的类型是char *(即,指向char的指针)。strcat()函数返回第1个参数,即拼接第2个字符串后的第1个字符串的地址。
11.5.3 strncat()函数
strcat()函数无法检查第1个数组是否能容纳第2个字符串
用strlen()查看第1个数组的长度
用strncat(),该函数的第3 个参数指定了最大添加字符数。例如,strncat(bugs, addon, 13)将把 addon字符串的内容附加给bugs,在加到第13个字符或遇到空字符时停止
11.5.4 strcmp()函数
由于非零值都为“真”,所以许多经验丰富的C程序员会把该例main()中的while循环头写成:while (strcmp(try, ANSWER))
strcmp()函数只会比较try中第1个空字符前面的部分。所以,可以用strcmp()比较储存在不同大小数组中的字符串
ASCII标准规定,在字母表中,如果第1个字符串在第2个字符串前面,strcmp()返回一个负数;如果两个字符串相同,strcmp()返回0;如果第1个字符串在第2个字符串后面,strcmp()返回正数
如果两个字符串开始的几个字符都相同会怎样?一般而言,strcmp()会依次比较每个字符,直到发现第 1 对不同的字符为止
char 类型实际上是整数类型,所以可以使用关系运算符来比较字符
strcmp()函数比较字符串中的字符,直到发现不同的字符为止,这一过程可能会持续到字符串的末尾。而strncmp()函数在比较两个字符串时,可以比较到字符不同的地方,也可以只比较第3个参数指定的字符数
11.5.5 strcpy()和strncpy()函数
如果希望拷贝整个字符串,要使用strcpy()函数
strcpy()函数相当于字符串赋值运算符
strcpy()第2个参数(temp)指向的字符串被拷贝至第1个参数(qword[i])指向的数组中。拷贝出来的字符串被称为目标字符串,最初的字符串被称为源字符串
target = "So long"; /* 语法错误 */
strcpy()接受两个字符串指针作为参数,可以把指向源字符串的第2个指针声明为指针、数组名或字符串常量;而指向源字符串副本的第1个指针应指向一个数据对象(如,数组),且该对象有足够的空间储存源字符串的副本。记住,声明数组将分配储存数据的空间,而声明指针只分配储存一个地址的空间
第一,strcpy()的返回类型是 char *,该函数返回的是第 1个参数的值,即一个字符的地址。第二,第 1 个参数不必指向数组的开始。这个属性可用于拷贝数组的一部分
strcpy()把源字符串中的空字符也拷贝在内
strcpy()和 strcat()都有同样的问题,它们都不能检查目标空间是否能容纳源字符串的副本。拷贝字符串用 strncpy()更安全,该函数的第 3 个参数指明可拷贝的最大字符数
strncpy(target, source, n)把source中的n个字符或空字符之前的字符(先满足哪个条件就拷贝到何处)拷贝至target中
这样做确保储存的是一个字符串。如果目标空间能容纳源字符串的副本,那么从源字符串拷贝的空字符便是该副本的结尾;如果目标空间装不下副本,则把副本最后一个元素设置为空字符。
11.5.6 sprintf()函数
sprintf()函数声明在stdio.h中,而不是在string.h中
sprintf()的第1个参数是目标字符串的地址。其余参数和printf()相同,即格式字符串和待写入项的列表
sprintf()的用法和printf()相同,只不过sprintf()把组合后的字符串储存在数组formal中而不是显示在屏幕上
11.5.7 其他字符串函数
ANSI C库有20多个用于处理字符串的函数,下面总结了一些常用的函数
11.6 字符串示例:字符串排序
11.6.1 排序指针而非字符串
11.6.2 选择排序算法
选择排序算法(selection sort algorithm)
利用for循环依次把每个元素与首元素比较。如果待比较的元素在当前首元素的前面,则交换两者。循环结束时,首元素包含的指针指向机器排序序列最靠前的字符串。然后外层for循环重复这一过程,这次从input的第2个元素开始。当内层循环执行完毕时,ptrst中的第2个元素指向排在第2的字符串。这一过程持续到所有元素都已排序完毕
11.7 ctype.h字符函数和字符串
第7章中介绍了ctype.h系列与字符相关的函数。虽然这些函数不能处理整个字符串,但是可以处理字符串中的字符
11.8 命令行参数
C编译器允许main()没有参数或者有两个参数(一些实现允许main()有更多参数,属于对标准的扩展)。main()有两个参数时,第1个参数是命令行中的字符串数量。过去,这个int类型的参数被称为argc (表示参数计数(argument count))。系统用空格表示一个字符串的结束和下一个字符串的开始。因此,上面的repeat示例中包括命令名共有4个字符串,其中后3个供repeat使用。该程序把命令行字符串储存在内存中,并把每个字符串的地址储存在指针数组中。而该数组的地址则被储存在 main()的第 2 个参数中。按照惯例,这个指向指针的指针称为argv(表示参数值[argument value])。
11.8.1 集成环境中的命令行参数
11.8.2 Macintosh中的命令行参数
11.9 把字符串转换为数字
数字既能以字符串形式储存,也能以数值形式储存。把数字储存为字符串就是储存数字字符。例如,数字213以'2'、'1'、'3'、'\0'的形式被储存在字符串数组中。以数值形式储存213,储存的是int类型的值
C要求用数值形式进行数值运算(如,加法和比较)。但是在屏幕上显示数字则要求字符串形式,因为屏幕显示的是字符
如果需要整数,可以使用atoi()函数(用于把字母数字转换成整数),该函数接受一个字符串作为参数,返回相应的整数值
如果字符串仅以整数开头,atio()函数也能处理,它只把开头的整数转换为字符。例如, atoi("42regular")将返回整数42
在我们所用的C实现中,如果命令行参数不是数字,atoi()函数返回0。然而C标准规定,这种情况下的行为是未定义的。因此,使用有错误检测功能的strtol()函数(马上介绍)会更安全
stdlib.h头文件,因为从ANSI C开始,该头文件中包含了atoi()函数的原型。除此之外,还包含了 atof()和 atol()函数的原型。atof()函数把字符串转换成 double 类型的值, atol()函数把字符串转换成long类型的值。atof()和atol()的工作原理和atoi()类似,因此它们分别返回double类型和long类型
strtol()把字符串转换成long类型的值,strtoul()把字符串转换成unsigned long类型的值,strtod()把字符串转换成double类型的值。这些函数的智能之处在于识别和报告字符串中的首字符是否是数字。而且,strtol()和strtoul()还可以指定数字的进制
long strtol(const char * restrict nptr, char ** restrict endptr, int base);
这里,nptr是指向待转换字符串的指针,endptr是一个指针的地址,该指针被设置为标识输入数字结束字符的地址,base表示以什么进制写入数字
首先注意,当base分别为10和16时,字符串"10"分别被转换成数字10和16。还要注意,如果end指向一个字符,*end就是一个字符。因此,第1次转换在读到空字符时结束,此时end指向空字符。打印end会显示一个空字符串,以%d转换说明输出*end显示的是空字符的ASCII码
对于第2个输入的字符串,当base为10时,end的值是'a'字符的地址。所以打印end显示的是字符串"atom",打印*end显示的是'a'字符的ASCII码。然而,当base为16时,'a'字符被识别为一个有效的十六进制数,strtol()函数把十六进制数10a转换成十进制数266
strtol()函数最多可以转换三十六进制,'a'~'z'字符都可用作数字。strtoul()函数与该函数类似,但是它把字符串转换成无符号值。strtod()函数只以十进制转换,因此它值需要两个参数
许多实现使用 itoa()和 ftoa()函数分别把整数和浮点数转换成字符串。但是这两个函数并不是 C标准库的成员,可以用sprintf()函数代替它们,因为sprintf()的兼容性更好
11.10 关键概念
11.11 本章小结
C字符串是一系列char类型的字符,以空字符('\0')结尾。字符串可以储存在字符数组中。字符串还可以用字符串常量来表示,里面都是字符,括在双引号中(空字符除外)。编译器提供空字符。因此,"joy"被储存为4个字符j、o、y和\0。strlen()函数可以统计字符串的长度,空字符不计算在内。
字符串常量也叫作字符串——字面量,可用于初始化字符数组。为了容纳末尾的空字符,数组大小应该至少比容纳的数组长度多1。也可以用字符串常量初始化指向char的指针。
函数使用指向字符串首字符的指针来表示待处理的字符串。通常,对应的实际参数是数组名、指针变量或用双引号括起来的字符串。无论是哪种情况,传递的都是首字符的地址。一般而言,没必要传递字符串的长度,因为函数可以通过末尾的空字符确定字符串的结束。
fgets()函数获取一行输入,puts()和 fputs()函数显示一行输出。它们都是 stdio.h 头文件中的函数,用于代替已被弃用的gets()。
C库中有多个字符串处理函数。在ANSI C中,这些函数都声明在string.h文件中。C库中还有许多字符处理函数,声明在ctype.h文件中。
给main()函数提供两个合适的形式参数,可以让程序访问命令行参数。第1个参数通常是int类型的argc,其值是命令行的单词数量。第2个参数通常是一个指向数组的指针argv,数组内含指向char的指针。每个指向char的指针都指向一个命令行参数字符串,argv[0]指向命令名称,argv[1]指向第1个命令行参数,以此类推。
atoi()、atol()和atof()函数把字符串形式的数字分别转换成int、long 和double类型的数字。strtol()、strtoul()和strtod()函数把字符串形式的数字分别转换成long、unsigned long和double类型的数字。
相关文章:
第11章 字符串和字符串函数
本章介绍以下内容: 函数:gets()、gets_s()、fgets()、puts()、fputs()、strcat()、strncat()、strcmp()、strncmp()、strcpy()、strncpy()、sprintf()、strchr() 创建并使用字符串 使用C库中的字符和字符串函数,并创建自定义的字符串函数 使用…...
TypeScript项目配置
前言 我们需要建立tsconfig.json 作用 用于标识 TypeScript 项目的根路径; 用于配置 TypeScript 编译器; 用于指定编译的文件。 重要字段 files - 设置要编译的文件的名称; include - 设置需要进行编译的文件,支持…...
【Spring面试】二、BeanFactory与IoC容器的加载
文章目录 Q1、BeanFactory的作用是什么?Q2、BeanDefinition的作用是什么?Q3、BeanFactory和ApplicationContext有什么区别?Q4、BeanFactory和FactoryBean有什么区别?Q5、说下Spring IoC容器的加载过程(※)Q…...
Android嵌套事务
这时候旋转设备还是会重置秒表。旋转设备时Android会重新创建活动。如果你的活动包含一个 < fragment >元素,每次重新创建活动时,它会重新插入片段的一个新版本。老片段被丢掉,所有实例变量会设置其初始值。在这个特定的例子中…...
如何让项目准时上线?
项目为什么容易延期? 1、软件研发是一项创造性工作 项目延期是一种普遍现象,管理者最为头疼的一个问题。但是外人并不理解。明明是你们自己做的计划,怎么总会出现这么多问题。说到底,这是由于我们的工作特性决定的。我们做的是一…...
ChatGPT 和 Elasticsearch:APM 工具、性能和成本分析
作者:LUCA WINTERGERST 在本博客中,我们将测试一个使用 OpenAI 的 Python 应用程序并分析其性能以及运行该应用程序的成本。 使用从应用程序收集的数据,我们还将展示如何将 LLMs 成到你的应用程序中。 在之前的博客文章中,我们构建…...
不使用辅助变量的前提下实现两个变量的交换
package operator; //不用第三个辅助变量,实现两个数的交换 public class Demo08 {public static void change(int a, int b){a ab;b a-b;a a-b;System.out.println(a);System.out.println(b);}public static void main(String[] args) {change(900,3000);} }后续…...
SV-DJS-i13电梯对讲网关
SV-DJS-i13电梯对讲网关 DJS-I13 是一款主要应用于电梯场景的对讲设备,可以将电梯原有模拟通话器的模拟信号转换成数字信号,不仅有稳定性好、电信级音质的优点,且完美兼容当下所有基于SIP的主流IPPBX/软交换/IMS平台,如Asterisk, Broadsoft,…...
论文解析-基因序列编码算法DeepSEA
论文解析-DeepSEA 参考亮点功能 方法数据集来源数据 实验评估评估DeepSEA预测染色质特征的性能评估DeepSEA在变异序列上的DHS预测性能数据集结果 参考 Zhou, J., Troyanskaya, O. Predicting effects of noncoding variants with deep learning–based sequence model. Nat Me…...
计组与操作系统
非科班出身的程序员,还是得补一下相关理论课程,最近看了下九曲阑干关于CSAPP的视频,学习了一下计算机组成原理,这里列一下相关知识点。 计算机组成原理: 数的表示与运算:CSAPP第二章 指令系统࿰…...
Pytorch中张量矩阵乘法函数(mm, bmm, matmul)使用说明,含高维张量实例及运行结果
Pytorch中张量矩阵乘法函数使用说明 1 torch.mm() 函数1.1 torch.mm() 函数定义及参数1.2 torch.bmm() 官方示例 2 torch.bmm() 函数2.1 torch.bmm() 函数定义及参数2.2 torch.bmm() 官方示例 3 torch.matmul() 函数3.1 torch.matmul() 函数定义及参数3.2 torch.matmul() 规则约…...
如何在matlab绘图的标题中添加变量?变量的格式化字符串输出浅析
文章目录 matlab的格式化输出控制符字段宽度、精度和对齐方式的控制matlab的格式化输出总结 matlab的格式化输出控制符 Matlab在画图的时候,采用title函数可以增加标题,该函数的输入是一个字符串,有时候我们想在字符串中添加一些变量&#x…...
Spring MVC 八 - 内置过滤器
SpringMVC内置如下过滤器: Form DataForwarded HeadersShallow ETagCORS Form Data 浏览器可以通过HTTP GET或HTTP POST提交form data(表单数据),但是非浏览器客户端可以通过HTTP PUT、HTTP DELETE、HTTP PATCH提交表单数据。但…...
@Change监听事件与vue监听属性:watch的区别?
change 和 watch 是 Vue 中用于处理数据变化的两种不同方式。 1. change: - change 是一个事件监听器,用于监听特定DOM元素的变化事件,通常用于表单元素(如输入框、下拉框等)的值变化。 - 它在用户与表单元素交互并提交了变化时触…...
C++面试记录之中望软件
上次面试体验不好,记录了,这次同样记录一次体验不好的面试,中望软件…直接写了名字,因为真的很无语😓 记录一下我不知道的问题 忘记录音了😢 1. main函数之前做了什么? 我:实话我…...
多功能翻译工具:全球翻译、润色和摘要生成 | 开源日报 0914
openai-translator/openai-translator Stars: 18.1k License: AGPL-3.0 这个项目是一个多功能翻译工具,由 OpenAI 提供支持。 可以进行全球单词翻译、单词润色和摘要生成等操作提供三种模式:翻译、润色和摘要支持 55 种不同语言的互相转换支持流模式允…...
在 Vue.js 中,使用 watch 监听data变量如:对象属性/data变量
watch 监听对象属性 在 Vue.js 中,使用 watch 监听对象属性的变化时,应该将属性名作为字符串传递给 watch 选项。 示例如下: javascript watch: {addform.isCheck1: function(newValue) {console.log(newValue);var quantity this.addform…...
vue中预览xml并高亮显示
项目中有需要将接口返回的数据流显示出来,并高亮显示; 1.后端接口返回blob,类型为xml,如图 2.页面中使用pre code标签: <pre v-if"showXML"><code class"language-xml">{{xml}}</code></pre> …...
MFC中嵌入显示opencv窗口
在MFC窗体中建立一个Picture Control控件,用于显示opencv窗口 在属性中设置图片控件的资源ID为IDC_PIC1 主要的思路: 使用GetWindowRect可以获取图片控件的区域 使用cv::resizeWindow可以设置opencv窗口的大小,适合图片控件的大小 使用cvGetWindowHandle函数可以获取到ope…...
金鸣识别网页版:轻松实现表格识别的神器
来百度APP畅享高清图片 金鸣识别网页版是一款功能强大的在线识别工具,它可对图片或PDF中的表格文本内容进行识别,还支持各种证票的结构化识别。以下是以表格识别为例,对金鸣识别网页版的操作说明进行详细介绍: 首先,打…...
DasViewer可以设置打开指定文件吗?
答:会员可以。工具里面选择坐标转换,输入源数据,设置好源坐标和目标坐标以及路径。根据两张坐标系的性质选择转换方式。 DasViewer是由大势智慧自主研发的免费的实景三维模型浏览器,采用多细节层次模型逐步自适应加载技术,让用户在极低的电脑…...
uniapp微信小程序用户隐私保护指引弹窗组件
<template><view v-if"showPrivacy" :class"privacyClass"><view :class"contentClass"><view class"title">用户隐私保护指引</view><view class"des">感谢您选择使用我们的小程序&am…...
Java的反射应用(Method和Class)
记录:473 场景:使用java.lang.reflect.Method和java.lang.Class类,根据Java反射原理实现使用指定字符串类名和方法名称,调用对应对象和对应方法。 版本:JDK 1.8。 1.使用Java反射调用指定类的指定方法 (1)参数说明…...
Java之泛型系列--Class使用泛型的方法(有示例)
原文网址:Java之泛型系列--Class使用泛型的方法(有示例)_IT利刃出鞘的博客-CSDN博客 简介 本文用示例介绍Java在方法前加泛型的使用。 类类型的写法 对象所对应的类的泛型写法 Class classAClass<T> classAClass<?> classB Class与Class<?&g…...
【【无用的知识之串口学习】】
无用的知识之串口学习 USART串口协议 •通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统 •通信协议:制定通信的规则,通信双方按照协议规则进行数据收发 就是我们并不能在芯片上设计完全部的一下子完成所有的设计&am…...
9月13日上课内容 第三章 ELK日志分析系统
本章结构 ELK日志分析系统简介 ELK日志分析系统分为 Elasticsearch Logstash Kibana 日志处理步骤 1.将日志进行集中化管理 2.将日志格式化(Logstash) 并输出到Elasticsearch 3.对格式化后的数据进行索引和存储 (Elasticsearch) 4.前端数据的展示(Kibana) Elasticsearch介…...
不知道有用没用的Api
encodeURIComponent(https://www.baidu.com/?name啊啊啊) decodeURIComponent(https%3A%2F%2Fwww.baidu.com%2F%3Fname%3D%E5%95%8A%E5%95%8A%E5%95%8A) encodeURI(https://www.baidu.com/?name啊啊啊) decodeURI(https://www.baidu.com/?name%E5%95%8A%E5%95%8A%E5%95%8A) …...
(2023,LENS 视觉模型 LLM)迈向可见的语言模型:通过自然语言的镜头来看计算机视觉
Towards Language Models That Can See: Computer Vision Through the LENS of Natural Language 公众号:EDPJ(添加 VX:CV_EDPJ 进交流群获取资料) 目录 0. 摘要 1. 简介 2. 相关工作 2.1 大语言模型能力 2.2 解决视觉和…...
线段树上树剖再拿线段树维护:0914T4
cp 一种常见套路: 如果在线段树上进行一段区间修改,那么必然是一段右节点一段左节点 这个过程其实就是zkw的本质 下面都要用zkw来理解 考虑原题,有一棵不规则的线段树 类似zkw,在这类题目中,我们要先把开区间变成闭…...
互联网医院系统|互联网医院探索未来医疗的新蓝海
随着互联网技术的飞速发展,互联网医院应运而生,为人们带来全新的医疗体验。本文将深入探讨互联网医院的开发流程、系统优势以及未来发展方向,带您领略医疗领域的新蓝海。互联网医院的开发流程是一个结合技术、医疗和用户需求的复杂过程。首先…...
接推广网站/品牌咨询
5节创建者模式 第1节:工厂方法模式 第2节:抽象工厂模式 第3节:建造者模式 第4节:原型模式 第5节:单例模式 7节结构型模式 第1节:适配器模式 第2节:桥接模式 第3节:组合模式 第4节&…...
wordpress 用户管理插件/目前最流行的拓客方法
UE4的下载和安装(UE4开发环境的搭建) 使用 UE4 开发游戏之前,必须先搭建开发环境,具体包括: UE4 引擎的下载和安装 Visual Studio 下载和安装 UE4 的下载和安装 首先,打开任意一个浏览器输入 UE4 官方…...
wordpress改页面/最有效的推广方式
【Links】 https://download.qt.io/official_releases/ https://download.qt.io/official_releases/qt/ https://download.qt.io/official_releases/qtcreator/ 备注: Qt Creator是跨平台的Qt IDE,Qt Creator是Qt被Nokia收购后推出的一款新的轻量级集成…...
企业网站排名怎么做/淘宝关键词优化技巧
要求: 用户在输入框输入内容时,上面的大号字体盒子con显示(这里面的字号更大) 实现思路: 表单检测用户输入:给表单添加键盘事件同时把快递单号里面的值value获取过来赋值给con盒子innerText做为内容如果…...
推广网站发布文章/排名第一的手机清理软件
值此钱包阵亡之际,想必大多数人除了收快递之外,难得的停止放飞自我那么几天了。所以我们想来聊点相对严肃的话题,比如双十一前夕,一个小卖家的猝死。6年拿过十一次红点设计大奖的杰出中国设计师——沈文蛟,在11月10日&…...
wordpress中文主题 wp-cms/网页广告怎么投放
JDK安装 1、双击–next 更改安装路径 c、指定JRE安装目录 C:\Java\jre1.8.0_144,点击“下一步” 创建一个新文件放jre d、安装完成,点击“关闭” 3、JDK 环境变量配置 (1)新建–变量名:JAVA_HOME、变量值…...