zoukankan      html  css  js  c++  java
  • 面试题之strcpy/strlen/strcat/strcmp的实现

    阿里的电面要我用C/C++实现一个字符串拷贝的函数,虽然以前写过 strcpy 的函数实现,但时间过去很久了,再加上有点紧张,突然就措手不及了。最后写是写出来了,但没考虑异常的情况,面试官好像很不满意。(T_T),写篇文章记录一下,以免日后重蹈覆辙。

    一、字符串拷贝strcpy

    函数strcpy的原型是char* strcpy(char* des , const char* src),des 和 src 所指内存区域不可以重叠且 des 必须有足够的空间来容纳 src 的字符串。

    #include <assert.h>
    #include <stdio.h>
    
    char* strcpy(char* des, const char* src)
    {
    	assert((des!=NULL) && (src!=NULL)); 
    	char *address = des;  
    	while((*des++ = *src++) != '')  
    		;  
    	return address;
    }

    要知道 strcpy 会拷贝'',还有要注意:

    • 源指针所指的字符串内容是不能修改的,因此应该声明为 const 类型。

    • 要判断源指针和目的指针为空的情况,思维要严谨,这里使用assert(见文末)。

    • 要用一个临时变量保存目的串的首地址,最后返回这个首地址。

    • 函数返回 char* 的目的是为了支持链式表达式,即strcpy可以作为其他函数的实参。


    二、字符串长度strlen

    函数strlen的原型是size_t strlen(const char *s),其中 size_t 就是 unsigned int。

    #include <assert.h>
    #include <stdio.h>
    
    int strlen(const char* str)
    {
    	assert(str != NULL);
    	int len = 0;
    	while((*str++) != '')
    		++len;
    	return len;
    }

    strlen 与 sizeof 的区别:

    • sizeof是运算符,strlen是库函数。

    • sizeof可以用类型、变量做参数,而strlen只能用 char* 变量做参数,且必须以结尾。

    • sizeof是在编译的时候计算类型或变量所占内存的大小,而strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度。

    • 数组做sizeof的参数不退化,传递给strlen就退化为指针了。


    三、字符串连接strcat

    函数strcat的原型是char* strcat(char* des, char* src),des 和 src 所指内存区域不可以重叠且 des 必须有足够的空间来容纳 src 的字符串。

    #include <assert.h>
    #include <stdio.h>
    
    char* strcat(char* des, const char* src)   // const表明为输入参数 
    {  
    	assert((des!=NULL) && (src!=NULL));
    	char* address = des;
    	while(*des != '')  // 移动到字符串末尾
    		++des;
    	while(*des++ = *src++)
    		;
    	return address;
    }


    四、字符串比较strcmp

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

    • 若s1==s2,返回零;
    • 若s1>s2,返回正数;
    • 若s1<s2,返回负数。

    即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇为止。

    #include <assert.h>
    #include <stdio.h>
    
    int strcmp(const char *s1,const char *s2)
    {
    	assert((s1!=NULL) && (s2!=NULL));
        while(*s1 == *s2)
        {
            if(*s1 == '')
                return 0;
             
            ++s1;
            ++s2;
        }
        return *s1 - *s2;
    }






    附:assert()断言

    assert是宏,而不是函数。它的原型定义在头文件 assert.h 中:

    void assert( int expression );

    宏 assert 经常用于在函数开始处检验传入参数的合法性,可以将其看作是异常处理的一种高级形式。assert 的作用是先计算表达式expression,然后判断:

    • 如果表达式值为假,那么它先向stderr打印错误信息,然后通过调用 abort 来终止程序运行。

    • 如果表达式值为真,继续运行后面的程序。

    注意:assert只在 DEBUG 下生效,在调试结束后,可以通过在#include <assert.h>语句之前插入#define NDEBUG来禁用assert调用。




    个人站点:http://songlee24.github.com



  • 相关阅读:
    如何从零开始创建一个IT信息系统
    Linux常用命令
    vue.js 3.2.20: 用rem实现移动端和pc的兼容
    vue.js3.2.6:路由处理404报错(vue-router@4.0.11)
    vue.js项目在nginx上部署:使spring后端记录真实ip地址
    vue.js 3.0.5:用vue-i18n开发i18n国际化功能(vue-i18n@9.2.0)
    前台项目基础框架之spring boot后端(spring boot v2.5.4)
    前台项目基础框架之vue前端(vue@3.2.6)
    intellij idea 2021.2:为一个spring boot项目改名
    git:修改项目的remote地址(git version 2.30.2)
  • 原文地址:https://www.cnblogs.com/songlee/p/5738091.html
Copyright © 2011-2022 走看看