程序员编程艺术:第四章、现场编写类似strstr/strcpy/strpbrk的函数

2023-05-16

               第四章、现场编写类似strstr/strcpy/strpbrk的函数   

 



前奏

    有网友向我反应,之前三章(http://t.cn/hgVPmH)的面试题目,是否有点太难了。诚如他所说,绝大部分公司的面试题不会像微软等公司的面试题目出的那么变态,或复杂。

    面试考察的是你对基础知识的掌握程度,及编程能力是否过硬的一种检测,所以,扎实基础知识,提高编程能力,比去看什么所谓的面经,或去背面试题目的答案强多了。

    很多中、小型公司自己的创造能力,包括人力,物力资源都有限,所以,他们的面试题目除了copy一些大公司的题库之外(当然,考察你对基础知识的掌握情况,是肯定不会放过的),还有一个途径就是让你在限定时间内(如十分钟),当场实现一些类似strcpy/strcat/strpbrk等库函数,这个主要看你对细节的把握,以及编程能力是否之扎实了。

    同时,本章里出现的代码(除了第4节的c标准库部分源码)都是个人限定在短时间内(正好,突出现场感)编写的,很多问题,难免有所考虑不周。所以,如果你发现本章任何一段代码有任何问题,恳请不吝指正。


第一节、字符串查找
1.1题目描述:
给定一个字符串A,要求在A中查找一个子串B。
如A="ABCDF",要你在A中查找子串B=“CD”。

分析:比较简单,相当于实现strstr库函数,主体代码如下:

//在字符串中查找指定字符串的第一次出现,不能找到则返回-1      
int strstr(char *string, char *substring)      
{     
	if (string == NULL || substring == NULL)        
		return -1;        

	int lenstr = strlen(string);     
	int lensub = strlen(substring);     

	if (lenstr < lensub)        
		return -1;         

	int len = lenstr - lensub;  
	int i,j;
	for (i = 0; i <= len; i++)   //复杂度为O(m*n)     
	{     
		for (j = 0; j < lensub; j++)     
		{     
			if (string[i+j] != substring[j])     
				break;     
		}     
		if (j == lensub)     
			return i + 1;     
	}     
	return -1;     
}    

    读者反馈@xiaohui5319:楼主啊,对于你那个strstr的函数,我觉得有点小问题。我查了一下C标准库的源码,它给的声明是这样的,两个参数都有const。

char *

STRSTR (const char *haystack_start, const char *needle_start)

    而且标准库中没有调用strlen函数,因为假如你是标准库的设计者,strlen()函数还没设计出来,你怎么去计算两个字符串的长度?是不是只能通过指针移动来实现,我觉得这些都是微软要考察的地方。

    此外:还有int lenstr=strlen(string);这是不安全的?
    strlen函数的返回类型是size_t型,也就是无符号整型,假如我的数组长度很长(假如是用堆分配的,可以很大很大),长过2的31次方减1的话,会发生一处,你这lenstr就会变成负值了
    用size_t类型最保险。

    以后,本编程艺术系列中有任何问题,暂未来得及及时修正,请读者多加思考,多加辨明

    上述程序已经实现了在字符串中查找第一个子串的功能,时间复杂度为O(n*m),也可以用KMP算法,复杂度为O(m+n)。为人打通思路,提高他人创造力,我想,这是狂想曲与其它的面试解答所不同的地方,也是我们写狂想曲系列文章的意义与价值之所在。

1.2、题目描述

在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。 

代码则可以如下编写:

//查找第一个只出现一次的字符,     
//copyright@ yansha     
//July、updated,2011.04.24.     
char FirstNotRepeatChar(char* pString)     
{     
	if(!pString)     
		return '\0';     

	const int tableSize = 256;    
	//有点要提醒各位注意,一般常数的空间消耗,如这里的256,我们也认为此空间复杂度为O(1)。  
	int hashTable[tableSize] = {0}; //存入数组,并初始化为0     

	char* pHashKey = pString;     
	while(*(pHashKey) != '\0')     
		hashTable[*(pHashKey++)]++;     

	while(*pString != '\0')     
	{     
		if(hashTable[*pString] == 1)     
			return *pString;     

		pString++;     
	}     
	return '\0';  //没有找到满足条件的字符,退出     
}  

代码二,bitmap:

# include<stdio.h>  
# include<string.h>  

const int N = 26;  
int bit_map[N];  

void findNoRepeat(char *src)  
{  
	int pos;  
	char *str = src;  
	int i ,len = strlen(src);  

	//统计  
	for(i = 0 ; i < len ;i ++)  
		bit_map[str[i]-'a'] ++;  

	//从字符串开始遍历 其bit_map==1 那么就是结果  
	for(i = 0 ; i < len ; i ++)  
	{  
		if(bit_map[str[i]-'a'] == 1)  
		{  
			printf("%c",str[i]);  
			return ;  
		}  
	}  
}  

int main()  
{     
	char *src = "abaccdeff";  
	findNoRepeat(src);  
	printf("\n");  
	return 0;  
}  

第二节、字符串拷贝
题目描述:
要求实现库函数strcpy,
原型声明:extern char *strcpy(char *dest,char *src);
功能:把src所指由NULL结束的字符串复制到dest所指的数组中。  
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。  
返回指向dest的指针。

    分析:如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案

//得2分     
void strcpy( char *strDest, char *strSrc )     
{     
	while( (*strDest++ = * strSrc++) != '\0' );     
}      

//得4分     
void strcpy( char *strDest, const char *strSrc )      
{     
	//将源字符串加const,表明其为输入参数,加2分     
	while( (*strDest++ = * strSrc++) != '\0' );     
}      

//得7分     
void strcpy(char *strDest, const char *strSrc)      
{     
	//对源地址和目的地址加非0断言,加3分     
	assert( (strDest != NULL) && (strSrc != NULL) );     
	while( (*strDest++ = * strSrc++) != '\0' );     
}      

//得9分     
//为了实现链式操作,将目的地址返回,加2分!     
char * strcpy( char *strDest, const char *strSrc )      
{     
	assert( (strDest != NULL) && (strSrc != NULL) );     
	char *address = strDest;      
	while( (*strDest++ = * strSrc++) != '\0' );      
	return address;     
}    

//得10分,基本上所有的情况,都考虑到了  
//如果有考虑到源目所指区域有重叠的情况,加1分!     
char * strcpy( char *strDest, const char *strSrc )      
{     
	if(strDest == strSrc) { return strDest; }  
	assert( (strDest != NULL) && (strSrc != NULL) );     
	char *address = strDest;      
	while( (*strDest++ = * strSrc++) != '\0' );      
	return address;     
}

第三节、小部分库函数的实现
    考察此类编写同库函数一样功能的函数经常见于大大小小的IT公司的面试题目中,以下是常见的字符串库函数的实现,希望,对你有所帮助,有任何问题,欢迎不吝指正:

//@yansha:字串末尾要加结束符'\0',不然输出错位结果  
char *strncpy(char *strDes, const char *strSrc, unsigned int count)      
{      
    assert(strDes != NULL && strSrc != NULL);      
    char *address = strDes;      
    while (count-- && *strSrc != '\0')      
        *strDes++ = *strSrc++;   
    *strDes = '\0';  
    return address;      
}   

//查找字符串s中首次出现字符c的位置   
char *strchr(const char *str, int c)   
{   
    assert(str != NULL);   
    for (; *str != (char)c; ++ str)   
        if (*str == '\0')   
            return NULL;   
        return str;   
}   

int strcmp(const char *s, const char *t)   
{   
    assert(s != NULL && t != NULL);   
    while (*s && *t && *s == *t)   
    {   
        ++ s;   
        ++ t;   
    }   
    return (*s - *t);   
}   

char *strcat(char *strDes, const char *strSrc)   
{   
    assert((strDes != NULL) && (strSrc != NULL));   
    char *address = strDes;   
    while (*strDes != '\0')   
        ++ strDes;   
    while ((*strDes ++ = *strSrc ++) != '\0')   
        NULL;   
    return address;   
}   

int strlen(const char *str)   
{   
    assert(str != NULL);   
    int len = 0;   
    while (*str ++ != '\0')   
        ++ len;   
    return len;   
}   

//此函数,梦修改如下     
char *strdup_(char *strSrc)     
//将字符串拷贝到新的位置     
{     
    if(strSrc!=NULL)     
    {     
        char *start=strSrc;     
        int len=0;     
        while(*strSrc++!='\0')     
            len++;     

        char *address=(char *)malloc(len+1);     
        assert(address != NULL);  

        while((*address++=*start++)!='\0');      
        return address-(len+1);      
    }     
    return NULL;     
}     

//多谢laoyi19861011指正  
char *strstr(const char *strSrc, const char *str)   
{   
    assert(strSrc != NULL && str != NULL);   
    const char *s = strSrc;   
    const char *t = str;   
    for (; *strSrc != '\0'; ++ strSrc)   
    {   
        for (s = strSrc, t = str; *t != '\0' && *s == *t; ++s, ++t)   
            NULL;   
        if (*t == '\0')   
            return (char *) strSrc;   
    }   
    return NULL;   
}   

char *strncat(char *strDes, const char *strSrc, unsigned int count)   
{   
    assert((strDes != NULL) && (strSrc != NULL));   
    char *address = strDes;   
    while (*strDes != '\0')   
        ++ strDes;   
    while (count -- && *strSrc != '\0' )   
        *strDes ++ = *strSrc ++;   
    *strDes = '\0';   
    return address;   
}   

int strncmp(const char *s, const char *t, unsigned int count)   
{   
    assert((s != NULL) && (t != NULL));   
    while (*s && *t && *s == *t && count --)   
    {   
        ++ s;   
        ++ t;   
    }   
    return (*s - *t);   
}   

char *strpbrk(const char *strSrc, const char *str)   
{   
    assert((strSrc != NULL) && (str != NULL));   
    const char *s;   
    while (*strSrc != '\0')   
    {   
        s = str;   
        while (*s != '\0')   
        {   
            if (*strSrc == *s)   
                return (char *) strSrc;   
            ++ s;   
        }   
        ++ strSrc;   
    }   
    return NULL;   
}   

int strcspn(const char *strSrc, const char *str)   
{   
    assert((strSrc != NULL) && (str != NULL));   
    const char *s;   
    const char *t = strSrc;   
    while (*t != '\0')   
    {   
        s = str;   
        while (*s != '\0')   
        {   
            if (*t == *s)   
                return t - strSrc;   
            ++ s;   
        }   
        ++ t;   
    }   
    return 0;   
}   

int strspn(const char *strSrc, const char *str)   
{   
    assert((strSrc != NULL) && (str != NULL));   
    const char *s;   
    const char *t = strSrc;   
    while (*t != '\0')   
    {   
        s = str;   
        while (*s != '\0')   
        {   
            if (*t == *s)   
                break;   
            ++ s;   
        }   
        if (*s == '\0')   
            return t - strSrc;   
        ++ t;   
    }   
    return 0;   
}   

char *strrchr(const char *str, int c)   
{   
    assert(str != NULL);   
    const char *s = str;   
    while (*s != '\0')   
        ++ s;   
    for (-- s; *s != (char) c; -- s)   
        if (s == str)   
            return NULL;   
        return (char *) s;   
}   

char* strrev(char *str)   
{   
    assert(str != NULL);   
    char *s = str, *t = str, c;   
    while (*t != '\0')   
        ++ t;   
    for (-- t; s < t; ++ s, -- t)   
    {   
        c = *s;   
        *s = *t;   
        *t = c;   
    }   
    return str;   
}   

char *strnset(char *str, int c, unsigned int count)   
{   
    assert(str != NULL);   
    char *s = str;   
    for (; *s != '\0' && s - str < count; ++ s)   
        *s = (char) c;   
    return str;   
}   

char *strset(char *str, int c)   
{   
    assert(str != NULL);   
    char *s = str;   
    for (; *s != '\0'; ++ s)   
        *s = (char) c;   
    return str;   
}   

//@heyaming  
//对原 strtok 的修改,根据MSDN,strToken可以为NULL.实际上第一次call strtok给定一字串,  
//再call strtok时可以输入NULL代表要接着处理给定字串。  
//所以需要用一 static 保存没有处理完的字串。同时也需要处理多个分隔符在一起的情况。  
char *strtok(char *strToken, const char *str)  
{  
    assert(str != NULL);  
    static char *last;  

    if (strToken == NULL && (strToken = last) == NULL)  
        return (NULL);  

    char *s = strToken;  
    const char *t = str;  
    while (*s != '\0')  
    {  
        t = str;  
        while (*t != '\0')  
        {  
            if (*s == *t)  
            {  
                last = s + 1;  
                if (s - strToken == 0) {  
                    strToken = last;  
                    break;  
                }  
                *(strToken + (s - strToken)) = '\0';  
                return strToken;  
            }  
            ++ t;  
        }  
        ++ s;  
    }  
    return NULL;  
}  

char *strupr(char *str)   
{   
    assert(str != NULL);   
    char *s = str;   
    while (*s != '\0')   
    {   
        if (*s >= 'a' && *s <= 'z')   
            *s -= 0x20;   
        s ++;   
    }   
    return str;   
}   

char *strlwr(char *str)   
{   
    assert(str != NULL);   
    char *s = str;   
    while (*s != '\0')   
    {   
        if (*s >= 'A' && *s <= 'Z')   
            *s += 0x20;   
        s ++;   
    }   
    return str;   
}   

void *memcpy(void *dest, const void *src, unsigned int count)   
{   
    assert((dest != NULL) && (src != NULL));   
    void *address = dest;   
    while (count --)   
    {   
        *(char *) dest = *(char *) src;   
        dest = (char *) dest + 1;   
        src = (char *) src + 1;   
    }   
    return address;   
}   

void *memccpy(void *dest, const void *src, int c, unsigned int count)   
{   
	assert((dest != NULL) && (src != NULL));   
	while (count --)   
	{   
		*(char *) dest = *(char *) src;   
		if (* (char *) src == (char) c)   
			return ((char *)dest + 1);   
		dest = (char *) dest + 1;   
		src = (char *) src + 1;   
	}   
	return NULL;   
}   

void *memchr(const void *buf, int c, unsigned int count)   
{   
	assert(buf != NULL);   
	while (count --)   
	{   
		if (*(char *) buf == c)   
			return (void *) buf;   
		buf = (char *) buf + 1;   
	}   
	return NULL;   
}   

int memcmp(const void *s, const void *t, unsigned int count)   
{   
	assert((s != NULL) && (t != NULL));   
	while (*(char *) s && *(char *) t && *(char *) s == *(char *) t && count --)   
	{   
		s = (char *) s + 1;   
		t = (char *) t + 1;   
	}   
	return (*(char *) s - *(char *) t);   
}   

//@big:  
//要处理src和dest有重叠的情况,不是从尾巴开始移动就没问题了。  
//一种情况是dest小于src有重叠,这个时候要从头开始移动,  
//另一种是dest大于src有重叠,这个时候要从尾开始移动。  
void *memmove(void *dest, const void *src, unsigned int count)   
{  
	assert(dest != NULL && src != NULL);  
	char* pdest = (char*) dest;  
	char* psrc = (char*) src;  

	//pdest在psrc后面,且两者距离小于count时,从尾部开始移动. 其他情况从头部开始移动  
	if (pdest > psrc && pdest - psrc < count)   
	{  
		while (count--)   
		{  
			*(pdest + count) = *(psrc + count);  
		}  
	} else   
	{  
		while (count--)   
		{  
			*pdest++ = *psrc++;  
		}  
	}  
	return dest;  
}  

void *memset(void *str, int c, unsigned int count)   
{   
	assert(str != NULL);   
	void *s = str;   
	while (count --)   
	{   
		*(char *) s = (char) c;   
		s = (char *) s + 1;   
	}   
	return str;   
}  
 
   测试:以上所有的函数,都待进一步测试,有任何问题,欢迎任何人随时不吝指出。

第四节、c标准库部分源代码

    为了给各位一个可靠的参考,以下,我摘取一些c标准框里的源代码,以飨各位:

char * __cdecl strcat (char * dst,const char * src)  
{  
    char * cp = dst;  

    while( *cp )  
        cp++;                   /* find end of dst */  

    while( *cp++ = *src++ ) ;       /* Copy src to end of dst */  

    return( dst );                  /* return dst */  

}  

int __cdecl strcmp (const char * src,const char * dst)  
{  
    int ret = 0 ;  

    while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)  
        ++src, ++dst;  

    if ( ret < 0 )  
        ret = -1 ;  
    else if ( ret > 0 )  
        ret = 1 ;  

    return( ret );  
}  

size_t __cdecl strlen (const char * str)  
{  
    const char *eos = str;  

    while( *eos++ ) ;  

    return( (int)(eos - str - 1) );  
}  

char * __cdecl strncat (char * front,const char * back,size_t count)  
{  
    char *start = front;  

    while (*front++)  
        ;  
    front--;  

    while (count--)  
        if (!(*front++ = *back++))  
            return(start);  

        *front = '\0';  
        return(start);  
}  

int __cdecl strncmp (const char * first,const char * last,size_t count)  
{  
    if (!count)  
        return(0);  

    while (--count && *first && *first == *last)  
    {  
        first++;  
        last++;  
    }  

    return( *(unsigned char *)first - *(unsigned char *)last );  
}  

/* Copy SRC to DEST.  */  
char *  
strcpy (dest, src)  
char *dest;  
const char *src;  
{  
    reg_char c;  
    char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);  
    const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;  
    size_t n;  

    do  
    {  
        c = *s++;  
        s[off] = c;  
    }  
    while (c != '\0');  

    n = s - src;  
    (void) CHECK_BOUNDS_HIGH (src + n);  
    (void) CHECK_BOUNDS_HIGH (dest + n);  

    return dest;  
}  

char * __cdecl strncpy (char * dest,const char * source,size_t count)  
{  
    char *start = dest;  

    while (count && (*dest++ = *source++))    /* copy string */  
        count--;  

    if (count)                              /* pad out with zeroes */  
        while (--count)  
            *dest++ = '\0';  

        return(start);  
}

有关编程艺术的修订

    程序员编程艺术系列的Github地址已于今天建立:https://github.com/nateriver520/The-Art-Of-Programming-By-July,我们急切的想得到读者的反馈,意见,建议,以及更好的思路,算法,和代码优化的建议。所以,如果你发现了本编程艺术系列中的任何一题,任何一章中的错误,问题,与漏洞,欢迎随时fork到本github中,thanks


版权所有,本人对本blog内所有任何内容享有版权及著作权。实要转载,请以链接形式注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

程序员编程艺术:第四章、现场编写类似strstr/strcpy/strpbrk的函数 的相关文章

  • Ubuntu下实现串口通信

    在ubuntu下使用cutecom可以接受串口消息也可以给串口发送消息 基本信息 xff1a 库 xff1a Python 的 serial 硬件 xff1a 电脑 Ubuntu18 04系统 USB Jeston AGX Xavier x
  • 4.FreeRTOS调度器的启动简易分析

    FreeRTOS调度器的启动简易分析 架构 xff1a Cortex M3版本 xff1a FreeRTOS V9 0 0前言 xff1a 上一篇我分析了关于一个任务的创建过程 xff0c 既然创建了任务 xff0c 自然是要用 那么Fre
  • ARM40-A5应用——与网络时间的同步1(概述)

    ARM40 A5应用 与网络时间的同步1 xff08 概述 xff09 2018 6 28 版权声明 xff1a 本文为博主原创文章 xff0c 允许转载 本文介绍ARM40 A5本地系统时间 硬件时间 时区 网络时间 ntpdate nt
  • 如何有效阅读《C++ Primer》那么厚的书

    我就是那种正面刚大部头的选手 xff0c 这些年读过的工作相关的 砖头 大概有 c 43 43 primer xff0c Windows核心编程 xff0c 算法导论 xff0c unix网络编程 xff0c STL源码剖析 等等吧 xff
  • 【Arduino 语法——结构体】

    Arduino 语法 结构体 1 0 项目结构 1 1 setup 1 2 loop 1 3 main 2 0 控制语句 2 1 break 2 2 continue 2 3 while 2 4 do while 2 5 for 2 6 i
  • 【MKS_GEN_L 主板使用说明书】

    MKS GEN L 主板使用说明书 1 描述2 特征3 主板封装3 1 尺寸图3 2 接线图3 2 1 MKS GEN L V1 0系统连接图3 2 2 MKSGEN L V2 1系统连接图 4 引脚排列5 GEN LV2 1驱动设置5 1
  • 【基于腾讯云的远程机械臂小车】

    基于腾讯云的远程机械臂小车 1 项目来源 1 1 项目概述 1 2 系统结构 1 3 设计原理 2 硬件搭建 2 1 CH32V307开发板 2 2 Arduino mega2560 2 3 富斯I6遥控器 2 4 机械臂小车 2 5 ES
  • 电脑之间快速传输超大文件(100GB以上)的方法

    引言 假如有这样一个场景 xff0c 你买了一台新的电脑 但是老电脑上存放着多年累积的数据 几百G之多 你要花时间把旧电脑上的数据导到新电脑上去 xff0c 这很费精力 于是你想有没有更快速的方法立马挪过去呢 xff1f 本文提供了五种方法
  • 《软件架构设计》(Yanlz Unity SteamVR 云技术 5G AI=VR云游戏=框架编程 架构设计 设计重构 游戏框架 框架入门 架构师 UML MVC ECS 立钻哥哥 ==)

    软件架构设计 软件架构设计 版本 作者 参与者 完成日期 备注 YanlzFramework 1910 V01 1 0 严立钻 2019 10 19 软件架构设计 发布说明 xff1a 43 43 43 43 软件架构设计 xff1a 是对
  • 进程的切换过程

    切换方式 进程的切换 xff0c 实质上就是被中断运行进程与待运行进程的上下文切换 从主观上来理解 只分为两步 xff1a 1 切换新的页表 xff0c 然后使用新的虚拟地址空间 2 切换内核栈 xff0c 加入新的内容 PCB控制块 xf
  • SLAM之camera(Intel RealSense D435)调试第一弹:Win10平台下getting started

    参见官方的getting started文档 https software intel com en us realsense d400 get started xff0c 这个quick start guide是Intel RealSen
  • Cmake的 debug和release

    Cmake的 debug版本和release版本 xff08 转 xff09 debug版本的项目生成的可执行文件需要有调试信息并且不需要进行优化 xff0c 而release版本的不需要调试信息但是需要优化 这些特性在gcc g 43 4
  • 【Kubernetes】K8s官方文档使用技巧

    学习K8s有很多技巧 其中一个技巧就是要多浏览官方 https kubernetes io zh 的说明文档 对于英语基础不是太好的 K8s官方还提供了中文版的页面 点击 文档 我们就进入了K8s文档的主页 主页上看起来也没多少知识点 别急
  • (六)定时器/计数器

    xff08 六 xff09 定时器 计数器 一 简介 定时器和计数器是两个名字 xff0c 但是原理上来说是一样的 xff0c 都是对脉冲进行计数 xff0c 区别在于时钟来源 xff0c 如果来自内部时钟信号 xff0c 由于内部时钟通常
  • Windows下令QProcess弹出CMD界面

    研究了快一下午 xff0c 来回看了QProcess文档中 xff0c 关于start execute statedDetached相关接口的调用说明 xff0c 然而并没有什么用处 差点就准备调用CreateProcess API的接口
  • Linux aarch64交叉编译之cJSON解析器

    对于cJSON项目的交叉编译 xff0c 该项目难度并不大 xff0c 灵活性也较强 该文章的目标是编译一套aarch64 Linux Debian嵌入式版本上可以运行的版本库 xff0c 基本无坑 老套路 xff0c 先把linux桌面版
  • Linux docker(03)可使用GPU渲染的x11docker实战总结

    该系列文章的目的旨在之前的章节基础上 xff0c 使用x11docker构建一个可以使用GPU的docker容器 该容器可以用于3D图形渲染 XR 等使用GPU渲染的程序调试和运行 0 why docker 为什么非要用x11docker
  • 北斗卫星导航系统介绍

    北斗卫星导航系统 导言 2020年3月9日 xff0c 我国在西昌卫星发射中心用长征三号乙运载火箭 xff0c 成功发射北斗系统第五十四颗导航卫星 距离北斗三号系统建成 xff0c 仅一步之遥 从双星导航定位到54颗北斗嵌满星空 xff0c
  • PyQt vs Tkinter – 更好的 GUI 库

    PyQt 和 Tkinter 的比较 在本文中 xff0c 我将分享我自己使用两个 GUI 库 PyQt 和 Tkinter 的旅程和个人经验 我还对具有相同小部件的 Tkinter 和 PyQt GUI 进行了并排比较 本文比较了两个 P
  • Selenium 中的 XPath

    Selenium 中的 XPath 是什么 xff1f Selenium 中最常用的定位器之一 xff0c XPath xff08 也称为 XML 路径 xff09 xff0c 通过页面的 HTML 格式支持您的指南 使用 HTML DOM

随机推荐

  • Centos7 安装yum源

    一 安装wget的rpm包 xff1a 1 下载wget的rpm包 首先去 http mirrors 163 com centos 7 os x86 64 Packages 下找到wget的rpm包 xff0c 复制链接 xff0c 使用c
  • Redis开启远程连接

    1 开启远程连接 redis默认是不支持远程连接 xff0c 需要手动开启 xff0c 在redis conf文件中 xff0c 找到下方法代码 xff1a bind 127 0 0 1 1 这里只允许127 0 0 1登录 xff0c 注
  • NVIDIA NeMo 简介——教程和示例

    NVIDIA NeMo 是一个用于构建新的最先进对话式 AI 模型的工具包 NeMo 有自动语音识别 ASR 自然语言处理 NLP 和文本转语音 TTS 模型的单独集合 每个集合都包含预构建模块 xff0c 其中包含训练数据所需的一切 每个
  • 2010 Qt开发者大会参会总结

    参加了一天的会议该好好的总结一下 1 QML和Meego会在下一步成为重点 2 Qt和Meego在一段发展时期内会有一些过渡性的库和方案 3 Qt在下一个版本会有可能将模块分解开 4 QML的开发效率会很高 xff0c 也很炫 xff0c
  • 人工智能——你需要知道的一切

    什么是人工智能 xff1f 人工智能 一词是美国数学家和计算机科学家约翰 麦卡锡于 1956 年创造的 人工智能是机器像人类一样学习和工作的能力 人工智能的历史可以追溯到古代 机器展示基本人工智能的第一个记录示例是工程师 Wilhelm S
  • 什么是迭代开发

    移动和 Web 开发行业正在快速发展 xff0c 开发人员可以使用新的工具和方法来创建更好的应用程序 为取得成功 xff0c 企业和开发人员必须紧跟软件开发生命周期和技术的最新发展 软件开发生命周期帮助公司高效地交付高质量的产品并减少错误
  • 如何安全升级 TiDB

    作为一个快速成长的开源 NewSQL 数据库 xff0c TiDB经常发布新特性和改进 如果您是 TiDB 用户 xff0c 您可能会发现很难决定是否升级您的版本 您可能也想知道如何让您的升级之旅更安全 更顺畅 xff0c 甚至不被企业注意
  • 推流是什么,直播为什么要推流

    直播可以快速准确地传递现场信息 xff0c 给大家带去强烈的现场感 xff0c 越来越多的人通过网站和手机来观看直播 在这里 xff0c 我们将通过本文系统地向大家阐述直播中另一个重要的操作环节推流 在搜索引擎上有很多朋友咨询推流是什么 x
  • 科学计算与MATLAB语言课程笔记——专题〇 初识matlab

    一 matlab优势 不需要过多了解各种数值计算方法的具体细节和计算公式 xff0c 也不需要繁琐的底层编程 可以专注与实际问题的分析和设计 xff0c 大大地提高工作效率和质量 二 matlab语言的重要功能 matlab matrix
  • 程序员编程艺术第三十四~三十五章:格子取数问题,完美洗牌算法

    第三十四 三十五章 xff1a 格子取数 xff0c 完美洗牌算法 作者 xff1a July caopengcs 绿色夹克衫 致谢 xff1a 西芹 new xff0c 陈利人 xff0c Peiyush Jain xff0c 白石 xf
  • 机器学习面试150题:不只是考SVM xgboost 特征工程

    前言 本博客曾经在10 13年连续4年整理过各大公司数据结构和算法层面的笔试题 面试题 xff0c 与此同时 xff0c 2012年起 xff0c AI越发火热 xff0c 各大公司开始陆续招AI方面的人才 xff0c 很多同学也会从网上找
  • 通俗理解LDA主题模型

    通俗理解LDA主题模 0 前言 印象中 xff0c 最开始听说 LDA 这个名词 xff0c 是缘于rickjin在2013年3月写的一个LDA科普系列 xff0c 叫LDA数学八卦 xff0c 我当时一直想看来着 xff0c 记得还打印过
  • [汇总III]微软等公司数据结构+算法面试第1-80题[前80题首次集体亮相]

    整理 III 微软等公司数据结构 43 算法面试 第1 80题 汇总 首次一次性汇总 公布 由于这些题 xff0c 实在太火了 所以 xff0c 应广大网友建议要求 xff0c 在此把之前已整理公布的前80题 xff0c 现在 xff0c
  • 微软公司等数据结构+算法面试100题(第1-100题)全部出炉

    微软等公司数据结构 43 算法面试100题 第1 100题 首次完整亮相 作者 July 2010年12月6日 更新 xff1a 现今 xff0c 这100题的答案已经全部整理出来了 xff0c 微软面试100题2010年版全部答案集锦 x
  • 读完《大数据时代》的一点儿心得

    工作一段时间之后 xff0c 总喜欢读读书 xff0c 这是多年养成下来的一个习惯 读书使人避恶 xff0c 读书使人向善 xff0c 读书使人聪慧 xff0c 读书使人高尚 xff0c 我们都是聪明人 xff0c 对吧 xff1f 哈哈哈
  • 永久勘误:微软等面试100题答案V0.2版[第1-20题答案]

    微软等面试100题答案V0 2版部分答案精选 第1 20题 作者 July 何海涛等网友 开诚布公 xff0c 接受读者检验 本文 xff0c 是根据我之前上传的 xff0c 微软等面试100题 xff0c 的答案V0 2版 第1 20题答
  • 十二之续、快速排序算法的深入分析

    十二之续 快速排序算法的深入分析 作者 July 二零一一年二月二十七日 前言 一 快速排序最初的版本 二 Hoare版本的具体分析 三 Hoare变种版本 四 快速排序的优化版本 五 快速排序的深入分析 六 Hoare变种版本与优化后版本
  • 程序员编程艺术:第一章、左旋转字符串

    第一章 左旋转字符串 作者 xff1a July xff0c yansha caopengcs 时间 xff1a 二零一一年四月十四日 题目描述 xff1a 定义字符串的左旋转操作 xff1a 把字符串前面的若干个字符移动到字符串的尾部 x
  • 程序员编程艺术:第二章、字符串是否包含问题

    程序员编程艺术 xff1a 第二章 字符串是否包含问题 作者 xff1a July xff0c yansha xff0c caopengcs 时间 xff1a 二零一一年四月二十三日 致谢 xff1a 老梦 xff0c nossiac xf
  • 程序员编程艺术:第四章、现场编写类似strstr/strcpy/strpbrk的函数

    第四章 现场编写类似strstr strcpy strpbrk的函数 前奏 有网友向我反应 xff0c 之前三章 xff08 http t cn hgVPmH xff09 的面试题目 xff0c 是否有点太难了 诚如他所说 xff0c 绝大