linux C --深入理解字符串处理函数 strlen() strcpy() strcat() strcmp()

在linux C 编程中,我们经常遇到字符串的处理,最多的就是字符串的长度、拷贝字符串、比较字符串等;当然现在的C库中为我们提供了很多字符串处理函数。熟练的运用这些函数,可以减少编程工作量,这里介绍几个常用的字符串函数,并编写一些程序,如果没有这些库函数,我们将如何实现其功能;

1 求字符串长度函数 strlen

头文件:string.h

函数原型:size_t strlen(const char *s)

功能:求字符串长度(不含字符串结束标志'\0')

如果没有这个函数,我们如何实现strlen呢?

程序如下:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. int mystrlen(const char *p)  
  5. {  
  6.     int i = 0;  
  7.     while(p[i])  
  8.         i++;  
  9.   
  10.     return i;  
  11. }  
  12.   
  13. int main()  
  14. {  
  15.     int len;  
  16.     char str[] = "Helloworld";  
  17.     len = mystrlen(str);  
  18.     printf("len = %d\n",len);  
  19.   
  20.     return 0;  
  21. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ gcc -o strlen strlen.c  
  2. fs@ubuntu:~/qiang/string$ ./strlen  
  3. len = 10  


同样可以实现求字符串长度功能。

既然在讲strlen(),在这里多说明一下,注意strlen()与sizeof()的区别:

sizeof和strlen有以下区别:
 sizeof是一个操作符,strlen是库函数。
 sizeof的参数可以是数据的类型,也可以是变量,而strlen只能以结尾为‘\0‘的字符串作参数。
 编译器在编译时就计算出了sizeof的结果。而strlen函数必须在运行时才能计算出来。并且sizeof计算的是数据类型占内存的大小,而strlen计算的是字符串实际的长度。
 数组做sizeof的参数不退化,传递给strlen就退化为指针了。
注意:有些是操作符看起来像是函数,而有些函数名看起来又像操作符,这类容易混淆的名称一定要加以区分,否则遇到数组名这类特殊数据类型作参数时就很容易出错。最容易混淆为函数的操作符就是sizeof。
说明:指针是一种普通的变量,从访问上没有什么不同于其他变量的特性。其保存的数值是个整型数据,和整型变量不同的是,这个整型数据指向的是一段内存地址。

 

 

2、字符串拷贝函数strcpy()

头文件:string.h

函数原型:char *strcpy(char *dest,const char *src)

功能: 字符串拷贝

参数:src为源串的起始地址,dest为目标串的起始地址

 

如果没有这个函数,我们将如何实现呢?程序如下:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2.   
  3. char *mystrcpy(char *dest,const char *src)  
  4. {  
  5.     char *p;  
  6.     p = dest;  
  7.     while(*src)  
  8.     {  
  9.         *dest++ = *src++;  
  10.     }  
  11.     *dest = '\0';  
  12.   
  13.     return p;  
  14. }  
  15.   
  16. int main()  
  17. {  
  18.     const char str1[] = "Helloworld";  
  19.     char str2[30];  
  20.     mystrcpy(str2,str1);  
  21.     printf("str2 = %s\n",str2);  
  22.   
  23.     return 0;  
  24. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ ./strcpy   
  2. str2 = Helloworld  


同样能够得到结果,当然有了strcpy()会很方便;

 

3、字符串连接接函数strcat

头文件:string.h

函数原型:char  *strcat(char *dest,const char *src)

功能:把字符串src连接到字符串dest的后面

实现方法:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2.   
  3. char *mystrcat(char *dest,const char *src)  
  4. {  
  5.     char *p;  
  6.     p = dest;  
  7.     while(*dest)  
  8.         dest++;  
  9.     while(*src)  
  10.     {  
  11.         *dest++ = *src++;  
  12.     }  
  13.   
  14.     *dest = '\0';  
  15.   
  16.     return p;  
  17. }  
  18.   
  19. int main()  
  20. {     
  21.     char str1[] = "hello";  
  22.     char str2[] = "world";  
  23.     mystrcat(str1,str2);  
  24.   
  25.     printf("str1 = %s\n",str1);  
  26.   
  27.     return 0;  
  28.   
  29. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ gcc -o strcat strcat.c  
  2. fs@ubuntu:~/qiang/string$ ./strcat  
  3. str1 = helloworld  


 

在使用strcat函数时,需要注意,目标数组应该有足够的空间,连接源串。注意,目标字符串'\0'被删除,然后连接源串。如果越界会发生什么呢?我们可以来验证一下:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. int main()  
  5. {  
  6.     char str2[6] = "world";  
  7.     char str1[6] = "hello";  
  8.     strcat(str1,str2);  
  9.     printf("str1 = %s\n",str1);  
  10.   
  11.     return 0;  
  12. }  

 

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ gcc -o strcat1 strcat1.c   
  2. fs@ubuntu:~/qiang/string$ ./strcat1  
  3. str1 = helloworld  
  4. *** stack smashing detected ***: ./strcat1 terminated  
  5. ======= Backtrace: =========  
  6. /lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb76cbd95]  
  7. /lib/i386-linux-gnu/libc.so.6(+0x103d4a)[0xb76cbd4a]  
  8. ./strcat1[0x80484d7]  
  9. /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75e14d3]  
  10. ./strcat1[0x80483d1]  
  11. ======= Memory map: ========  
  12. 08048000-08049000 r-xp 00000000 08:01 830810     /home/fs/qiang/string/strcat1  

当然,下面还有好多,这里就不展示了,我们来看看结果,helloworld能打印出来,编译时也没错误,但执行时告知溢出了。

我们稍微修改程序,大家注意区别:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. int main()  
  5. {  
  6.     char str1[6] = "hello";  
  7.     char str2[6] = "world";  
  8.     strcat(str1,str2);  
  9.     printf("str1 = %s\n",str1);  
  10.     printf("str2 = %s\n",str2);  
  11.       
  12.     return 0;  
  13. }  

输出结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ gcc -o strcat1 strcat1.c   
  2. fs@ubuntu:~/qiang/string$ ./strcat1  
  3. str1 = helloworld  
  4. str2 = orld  

并没有溢出!(实际是溢出了!!!!!!!)

是不是很有意思?大家看看两者程序的区别,只是六七行交换了位置,但一个溢出,一个却不溢出,为什么呢?大家应该知道数据存储的方式吧,第一个程序中:

[cpp] view plaincopy
  1. char str2[6] = "world";  
  2. char str1[6] = "hello";  
  3.       

先定义了str2[],程序为其分配了一段连续的空间,接着定义了str1[],程序会在刚才为str2[]定义的地址后面接着定义一段连续空间,如果接着将str2 接在str1后面,str1原来只定义了6个字节,需要连接在一起需要11个字节,肯定超出了我们定义的地址空间,后面是一片未知区域,会发生溢出;但为什么程序2却没有溢出呢?

[cpp] view plaincopy
  1. char str1[6] = "hello";  
  2. char str2[6] = "world";  

这里就比较巧了,因为str2是在str1后面定义的,str2接在str1后面确实会溢出,但溢出后的一片空间,正好是str2的地址空间,区域是可知的,只是helloworld覆盖掉了原来str2的东西。所以不会溢出,这样说,大家明白吧?

继续看,大家有木有发现,我在程序二中对str2的值进行了打印,不再是原来的world,变成了orld,按道理来讲,str2的值不会改变的啊?大家在这里要清楚str2只是一个地址而已,只负责输出当前地址以后的字符串,以'\0'结束;所以这里的orld是strcat(str1,str2)后str1的值,但为什么是“orld”呢?因为目标字符串的'\0'被删除,然后连接串;

此时str1后面的orld覆盖了原world,但str2原来指向的是w的地址,现在原存放'w'的地址处存放的是'o',所以会输出"orld"!大家是否还有疑问,后面好像还有个'd'没有被覆盖啊,为什么输出的不是"orldd"呢?大家应该明白字符串有个结束符'\0'吧,它将'd'覆盖了,如果大家觉得不好理解,可以画一下图,就比较清楚了;

其实这只是个特例,让大家看一下如果数据溢出造成的后果!

 

4、字符串比较函数strcmp

头文件:string.h

函数原型:int strcmp(const char *s1,const char *s2)

功能:按照ASCII码顺序比较字符串s1和字符串s2的大小

如果没有这个函数,我们如下实现:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2.   
  3. int mystrcmp(const char *s1,const char *s2)  
  4. {  
  5.     int i = 0;  
  6.     while(*s1 || *s2)  
  7.     {  
  8.         if(*s1 > *s2)  
  9.         {  
  10.             return 1;  
  11.         }  
  12.         else if(*s1 < *s2)  
  13.         {  
  14.             return -1;  
  15.         }  
  16.         else  
  17.         {  
  18.             s1++;  
  19.             s2++;  
  20.         }     
  21.     }  
  22.     return 0;  
  23. }  
  24.   
  25. int main()  
  26. {  
  27.     int n;  
  28.     char str1[] = "hell";  
  29.     char str2[] = "hello";  
  30.     n = mystrcmp(str1,str2);  
  31.     printf("n = %d\n",n);  
  32.   
  33.     return 0;  
  34. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ gcc -o strcmp strcmp.c   
  2. fs@ubuntu:~/qiang/string$ ./strcmp  
  3. n = -1  

刚才提到的函数功能:比较两字符串的大小,好像比较抽象,我们其实是比较两个字符串是否相等;下面我们看个题目:

题目:计算字符串中子串出现的次数

什么意思呢?就是helloworldhehehehellowo中,比如说子串"hello"在字符串中出现的次数,如果单纯的用getchar()获取每个字符并比较,会很麻烦,在这里我们可以用strcmp来实现,会很方便,大家可以看看strcmp的具体应用,实现程序如下:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. int main()  
  5. {  
  6.     int i = 0;  
  7.     int count = 0;  
  8.     int len1,len2;  
  9.     char str1[100] = {'\0'};  
  10.     char str2[20] = {'\0'};  
  11.     printf("Please input two strings!\n");  
  12.     scanf("%s%s",str1,str2);  
  13.     len1 = strlen(str1);  
  14.     len2 = strlen(str2);  
  15.   
  16.     while(i + len2 <= len1)  
  17.     {  
  18.         if(!(strncmp(&str1[i],str2,len2)))  
  19.         {  
  20.             count++;  
  21.             i += len2;  
  22.         }  
  23.         else  
  24.             i++;  
  25.     }  
  26.       
  27.     printf("count = %d\n",count);  
  28.   
  29.     return 0;  
  30. }  

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/string$ ./zichuan   
  2. Please input two strings!  
  3. xiaoqiangxiqiangxiaoxiaqiang  
  4. xiao  
  5. count = 2  
  6. fs@ubuntu:~/qiang/string$   


大家看看结果是不是正确的。


附:(转载)

    strcmp 字符串比较函数,strcpy 字符串拷贝函数, strlen 字符串测长函数, strcat字符串连接函数,sprintf格式化字符串拷贝函数等等。因为字符串就是以‘\0’结束的一段内存,这些函数实质上也就是操作内存的函数,所以避免不了的与指针打交道,使得这些函数充满了陷阱,如果这些函数使用不当,很有可能在程序中埋伏下危险的陷阱,使程序的稳定性遭受重创。下面我就字符串使用中一些常见的问题来进行举例说明。

一. strcpy:极度危险的函数,一不小心就会中招,危险指数:四星

       strcpy的原型是这样的: char *strcpy(char *dest, const char *src) 作为常见的字符串复制函数,C库中的实现是不安全的,因为它不做字符串的检查,以至于如果参数传入了非法指针,比如:src不是指向字符串的指针。后果就不堪设想,程序会一直复制,直到遇到‘\0’才结束,这样很有可能就会使得dest指向的内存区域缓冲区溢出,使得导致不程序相干的部分出现错误,这种错误也许就是致命的。所以使用这个函数一定确保第二个参数传入合法的指针。
例子:

[cpp] view plaincopy
  1. #include <string.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4.   
  5. char dest[5] = {'D'};  
  6. char mydata[7] = {'m','y','d','a','t','a','\0'};  
  7.   
  8. int main(void)  
  9. {  
  10.         char i;  
  11.         char source[5];  
  12.         char bound[5] = {'&','&','&','&','&'};  
  13.   
  14.         for (i = 0; i < 5; i++)  
  15.                 source[i] = 'S';  
  16.   
  17.         printf("before strcopy, mydata is %s\n", mydata);  
  18.         strcpy(dest, source);  
  19.         printf("dest is %s\n", dest);  
  20.         printf("after strcopy, mydata is %s\n", mydata);  
  21.   
  22. }  

  程序中定义了两个全局数组,我们知道C语言的全局变量要放在DATA段,而dest与mydata因为定义相连,所以其内存地址是相邻的。程序的目的是复制一个字符串到dest数组,而程序中忘了给source数组最后加上'\0'。所以source就不是一个字符串,用它传递给strcpy就会造成意想不到的后果。本程序中strcpy一直复制内存到dest,直到在遇到‘\0’, 这样就会多复制很多数据到dest,从而意外的覆盖mydata,甚至有时还会导致程序崩溃。在拷贝之前, mydata的数据是 "mydata", 而在拷贝之后造成了意外的修改。

二. strcat 造成缓冲区溢出的隐形杀手,危险指数 三星

        strcat 是将一个字符串连接到另外一个字符串上,其函数原型为char *strcat(char *dest,char *src)。这个函数也很危险,因为C语言的实现也是不安全的,传入非法的指针有可能会造成程序的崩溃。首先保证两个指针都应该指向字符串,其次dest指针指向的空间要足以容的下src指向的字符串,否则会造成缓冲区溢出而破坏其他程序数据。
例子1:

[cpp] view plaincopy
  1. #include <string.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4.   
  5. char dest[5] = {'D''\0'};  
  6. char mydata[7] = {'m','y','d','a','t','a','\0'};  
  7.   
  8. int main(void)  
  9. {  
  10.         char i;  
  11.         char source[5];  
  12.         char bound[5] = {'&','&','&','&','&'};  
  13.   
  14.         for (i = 0; i < 4; i++)  
  15.                 source[i] = 'S';  
  16.         source[4] = '\0';  
  17.         printf("before strcat, mydata is %s\n", mydata);  
  18.         strcat(dest, source);  
  19.         printf("dest is %s\n", dest);  
  20.         printf("after strcat, mydata is %s\n", mydata);  
  21.   
  22. }  

这个例子因为目标dest只有5个字节大小,并且数据占了一个字节,只剩下四个字节位置,而源数据字符串长度为4个字符加一个‘\0’有五个字节大小,所以会多出一个字节覆盖了mydata的数据,多出的‘\0’成为了mydata的第一个字节,导致调用strcat后输出mydata为空。
例子2 :

[cpp] view plaincopy
  1. #include <string.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4.   
  5. char dest[5] = {'D''D''D''D''D'};  
  6. char mydata[7] = {'m','y','d','a','t','a','\0'};  
  7.   
  8. int main(void)  
  9. {  
  10.         char i;  
  11.         char source[5];  
  12.         char bound[5] = {'&','&','&','&','&'};  
  13.   
  14.         for (i = 0; i < 4; i++)  
  15.                 source[i] = 'S';  
  16.         source[4] = '\0';  
  17.         printf("before strcat, mydata is %s\n", mydata);  
  18.         strcat(dest, source);  
  19.         printf("dest is %s\n", dest);  
  20.         printf("after strcat, mydata is %s\n", mydata);  
  21.   
  22. }  

    这个例子中,dest不是字符串(没有‘\0’结尾),导致strcat从地址dest处开始找'\0',找到'\0'后并在此地址上复制source的数据,在本程序中就将source连接到了mydata后面,导致mydata变成了“mydataSSSS”,这样也破坏了程序无关的数据,本程序中还好是破坏的DATA中的数据,如果是其他的数据那么后果不不仅仅是数据改变这么简单了。

三.  strlen 很多malloc函数缓冲区溢出问题的始作俑者 危险指数 二星

     strlen是字符串求长函数,但是它求出的长度不包括‘\0’,所以在用malloc分配内存的时候,很容易少分配一个字节,就这小小的一个字节就会造成缓冲区溢出,我们知道malloc分配的内存区域是有一个头的,这样就有可能破坏其他malloc的头使得内存释放失败,带来一系列连锁反映。因为malloc函数的实现与系统有关,这个不好用程序模拟,但是这种情况确实存在。因此如果用strlen求字符串长度用于malloc一定要记住要加1。

四.  sprintf 同样可以造成缓冲区溢出,危险指数 一星

     sprintf是格式化字符拷贝函数,函数原型是int sprintf( char *buffer, const char *format, … ) 。这个函数的实现也是不安全的,使用这个函数要确保buffer足够大,否则这个函数在不做任何提示的情况下就将buffer溢出,这个函数虽然返回复制的字节数,可以通过这个检查复制了多少个字节,以确定是否缓冲区溢出。但这种亡羊补牢的做法其实没有实际意义。缓冲区溢出的错误已经发生也许会是程序崩溃,检测的时间也许都没有,就算有检测时间,也只是用于提示程序的BUG,在正式的程序中没有多大用处。
例子: 

[cpp] view plaincopy
  1. #include <string.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4.   
  5. char dest[2] = {'D'};  
  6. char mydata[7] = {'m','y','d','a','t','a','\0'};  
  7.   
  8. int main(void)  
  9. {  
  10.         char i;  
  11.         char source[5];  
  12.         char bound[5] = {'&','&','&','&','&'};  
  13.   
  14.         for (i = 0; i < 4; i++)  
  15.                 source[i] = 'S';  
  16.         source[4] = '\0';  
  17.         printf("before sprintf, mydata is %s\n", mydata);  
  18.         sprintf(dest, "%s", source);  
  19.         printf("dest is %s\n", dest);  
  20.         printf("after sprintf, mydata is %s\n", mydata);  
  21.   
  22. }  

 这个例子中,目标缓冲区只有两个字节的大小,而源字符串却是五个字节,sprintf在不进行任何提示的情况下,默默的覆盖了mydata的数据。
总结        

        总上所述,C语言字符串操作函数一般都不对参数做检查,需要调用者确保参数的合法性。如果传入不正确的参数,就会造成缓冲区溢出。轻则数据被修改,重则程序崩溃。最郁闷的是影响到程序中不相关的部分。我前面举的例子都很简单,很容易一眼看出问题的所在,但是大型程序就不会这么简单了,这些错误就是致命的。所以使用C语言的字符串函数时一定要养成良好的习惯,自己检查参数的合法性,然后再调用。目前C语言中这些字符串操作函数都有一些安全的版本就是带n的系列,比如:strncpy,strncat,snprintf。这些函数规定了源字符串的大小,对缓冲区溢出的预防有一定的作用,比如:snprintf,其函数原型是int snprintf(char *str, size_t size, const char *format, ...) 第二个参数size,可以保证复制size个字节,如果要复制的字符串大于size就会截短,从而保证str不会溢出。程序中尽量使用这些安全的版本。良好的习惯是一个程序稳定与健壮的保证,而良好的习惯都是使用这些常用的函数养成的,所以一定要主要这些字符串函数的使用。

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

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

相关文章

VSFTP的主动模式和被动模式

关于VSFTP的主动模式和被动模式一&#xff0c;首先我们看两个例子如下&#xff1a;其中192.168.10.7是服务端&#xff0c;172.16.11.11是客户端被动模式# netstat -an |grep 172.16.11.11tcp 0 0 192.168.10.7:52160 172.16.11.11:16091 TIME_WA…

SpringBoot项目利用maven自定义打包结构

From: https://blog.csdn.net/q15858187033/article/details/80742117 SpringBoot官方提供的demo中&#xff0c;pom.xml文件里引用了官方提供的打包插件 <build> <plugin> <groupId>org.springframework.boot</groupId> …

20169210《Linux内核原理与分析》第十二周作业

Return-to-libc 攻击实验 缓冲区溢出的常用攻击方法是用 shellcode 的地址来覆盖漏洞程序的返回地址&#xff0c;使得漏洞程序去执行存放在栈中 shellcode。为了阻止这种类型的攻击&#xff0c;一些操作系统使得系统管理员具有使栈不可执行的能力。这样的话&#xff0c;一旦程序…

判断android图片是否硬解码(方法)

2019独角兽企业重金招聘Python工程师标准>>> 在oncreate方面的setContentView(R.layout.main); 前面&#xff0c;添加如下代码&#xff1a; getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HAR…

如何解决Mybatis里mapper文件中关于不能用大于小于号

From: https://blog.csdn.net/qq_38659629/article/details/80408185 用<![CDATA[ ]]>标识 比如&#xff1a;<![CDATA[ where auctionEndTime < now()]]> 另外一种方法就是使用转义字符 < < > > & " < …

Linux C 编程技巧--利用有限状态机模型编程

我们知道&#xff0c;一般编写程序时都要画出流程图&#xff0c;按照流程图结构来编程&#xff0c;如果编写一个比较繁琐&#xff0c;容易思维混乱的程序时&#xff0c;我们可以利用有限状态机模型画出一个状态转移图&#xff0c;这样便可以利用画出的逻辑图来编写程序&#xf…

JVM的垃圾回收机制

发现一篇好文章,能够快速的帮助我们理清楚思路,以下内容转载 JVM的内部结构 先说下jvm运行时数据的划分&#xff0c;粗暴的分可以分为堆区(Heap)和栈区(Stack)&#xff0c;但jvm的分法实际上比这复杂得多&#xff0c;大概分为下面几块&#xff1a; 1、程序计数器(Program Conut…

centos配置ssh免密码登录后仍要输入密码的解决方法

From: https://blog.csdn.net/zwbill/article/details/80448939 前言 在搭建Linux集群服务的时候&#xff0c;主服务器需要启动从服务器的服务&#xff0c;如果通过手动启动&#xff0c;集群内服务器几台还好&#xff0c;要是像阿里1000台的云梯Hadoop集群的话&#xff0c;轨…

Linux c学习--从标准输入输出看流和缓冲区

学习标准输入输出&#xff0c;我们都会遇到一个概念&#xff0c;流和缓冲区&#xff0c;但到底什么是流&#xff0c;什么是缓冲区呢&#xff1f; 书《C Primer Plus》上说&#xff0c;C程序处理一个流而不是直接处理文件。后面的解释十分抽象&#xff1a;『流&#xff08;strea…

ubuntu vim8.0源码安装

安装篇 从https://github.com/vim/vim下载相应zip源码文件&#xff0c;利用unzip vim-master.zip 命令解压到当前用户目录&#xff0c;即~&#xff1b; 解压后进入vim的src目录&#xff0c;首先&#xff0c;即运行 sudo apt-get updata &#xff08;更新系统软件源&#xff09;…

Linux C学习---递归函数

最近学习到了递归&#xff0c;刚开始看&#xff0c;真是头大&#xff0c;函数里面嵌套其本身&#xff0c;到底是怎么个流程啊&#xff1f; 现在&#xff0c;咱们先了解下递归函数的数学原理&#xff1a; 高中的时候就出现很多递归函数&#xff0c;应该是在“级数”那里的习题中…

Java判断两个Date是不是同一天

From: https://blog.csdn.net/xingchenbingbuyu/article/details/82734695 Java判断两个Date是不是同一天 1. 利用Calendar Calendar cal1 Calendar.getInstance(); Calendar cal2 Calendar.getInstance(); cal1.setTime(date1); cal2.setTime(date2); boolean sameDay ca…

js二级下拉被flash档住的解决办法

在<object></object>及以内的代码加入到<script>标签对内<script language"javascript" type"text/javascript"> <param name"wmode" value"transparent" />//背景透明 </script> 转载于:https:/…

iOS:以前笔记,未整理版。太多了,先放着吧。。。。。。。

1、**************************************************************** 单例共享 **************************************************************** 单例 共享信息 .m static OneT *newone nil; (instancetype)shalldata { if (newone nil) { newone [[OneT alloc]init]…

C语言经典编程题--哥德巴赫猜想 、完数 、猜数字等

一、 验证歌德巴赫猜想&#xff1a;任意一个不小于6的偶数都可以表示成两个素数的和。从键盘任意给一个符合条件的数&#xff0c;输出相应的两个素数。 素数&#xff1a;指在一个大于1的自然数中&#xff0c;除了1和此整数自身外&#xff0c;没法被其他自然数整除的数 代码如下…

Calendar的DAY_OF_MONTH, DAY_OF_YEAR, DATE的区别

From: https://blog.csdn.net/weixin_34233679/article/details/87286628 cal1.add(Calendar.DAY_OF_MONTH,1); cal1.add(Calendar.DAY_OF_YEAR,1); cal1.add(Calendar.DATE,1); 就单纯的add操作结果都一样&#xff0c;因为都是将日期1 就没有区别说是在月的日期中加1还是…

Cisco网络防火墙配置方法

这篇文章主要介绍了Cisco网络防火墙配置方法,需要的朋友可以参考下  由于网络防火墙默认禁止所有的通信&#xff0c;因为&#xff0c;只有对其进行适当配置后&#xff0c;才能实现正常的网络通信。  如何配置Cisco网络防火墙  1.进入全局配置模式  ciscoasa#configure …

linux远程登录三种方式telnet,ssh,vnc

linux远程连接三种方式telnet&#xff0c;ssh&#xff0c;vnctelnet和ssh服务只能实现基于字符界面的远程控制&#xff0c;如果要基于图形界面进行远程控制&#xff0c;可以借助免费的VNC来完成。一、telnet连接1.首先进入终端&#xff0c;查看是否安装了telnet服务。linux默认…

老司机学习MyBatis之如何通过select返回Map

From: https://blog.csdn.net/Gaomb_1990/article/details/80638177 一、案例 当要查询的结果是一个Map的时候&#xff0c;这里分为两种情况&#xff1a; ①返回单条记录 <select id"getUserByIdReturnMap" resultType"map"> select id, log…

大数据之Yarn——Capacity调度器概念以及配置

试想一下&#xff0c;你现在所在的公司有一个hadoop的集群。但是A项目组经常做一些定时的BI报表&#xff0c;B项目组则经常使用一些软件做一些临时需求。那么他们肯定会遇到同时提交任务的场景&#xff0c;这个时候到底如何分配资源满足这两个任务呢&#xff1f;是先执行A的任务…