zoukankan      html  css  js  c++  java
  • [面试] 常见重写字符串库函数的面试题 “一网打尽”

    传说常见的一个笔试题:不使用中间变量求const字符串长度。函数接口声明如下:int strlen(const char *p);
    思路分析:
    在字符串中通常可以利用最后一个结束符’\0’,但此处参数为const,只读,那么我们不能打他的主意。
    函数运行过程中不占用内存基本不可能,除非都使用了寄存器。“不使用中间变量”只是说程序员不能显示的申请内存而已,即不能有局部变量或者动态内存申请。
    如果函数自动申请栈内存或者使用寄存器存储变量,或者使用立即数寻址即常量,那么就相当于“不使用中间变量”。
    从函数原型看,返回值为int,那么在函数内部必定需要一个地方存储这个值,要么是常数要么是寄存器。长度不为1时不能一次就求出来,说明必须有递归调用,这样递归时函数会自动申请栈内存,这样就相当于程序员“不使用中间变量”了。中间返回的值通过寄存器自动保存,最后一次返回时拷贝到int中去。C/C++中也有临时对象的概念,都是程序在运行过程中由编译器在栈中自动申请的对象,对程序员不可见,也相当于“不使用中间变量”
    这种问题都是利用常量,或者将变量的申请交给编译器在递归过程中自动在栈中申请,也就是借刀杀人了。
    #include <iostream>
    #include <cstring>
    using namespace std;
    char* strcpy(char *dst, const char *src) {
        char *cp = dst;
        while(*cp++ = *src++)   // 未考虑重叠,重叠的时候从后向前考虑一样!
            ;               /* Copy src over dst */
        return dst;
    }
    
    char* strncpy(char *dst, const char *src, size_t num);
    
    char* 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;
    }
    size_t strlen(const char *str) {
         size_t len = 0;
         while(*str++)
              ++len;
         return len;
    }
    int strcmp(const char *src1, const char *src2) {
        int ret = 0 ;
        while(!(ret = *src1 - *src2) && *src2)
            ++src1, ++src2;
        if(ret < 0)
            ret = -1;
        else if(ret > 0)
            ret = 1;
        return ret;
    }
    ///-------------------------
    /// 方法 1
    char* strstr(char* str1, const char* str2) {
        int len = strlen(str2);
        if(!len) return str1;
        while(*str1) {
            if(*str1 == *str2 && strncmp(str1, str2, len) == 0) {
                return str1;
            }
            ++str1;
        }
        return NULL;
    }
    /// 方法2
    char* strstr2(char *str1, const char* str2) {
        int i;
        if(*str2) {
            while(*str1) {
                for(i = 0; *(str1+i) == *(str2+i); i++) {
                    if(!*(str2+i+1)) return str1;
                }
                ++str1;
            }
            return NULL;
        }
        return str1;
    }
    /// 方法3  strstr3 估计kmp可以okay!
    /* memcpy example */
    void* Memcpy(void *dst, const void *src, size_t size) {
        char *psrc;
        char *pdst;
        if(NULL == dst || NULL == src) return NULL;
        if(src < dst && src + size > dst) {
            psrc = (char*)src + size - 1;
            pdst = (char*)dst + size - 1;
            while(size--) {
                *pdst-- = *psrc--;
            }
        }
        else {
            psrc = (char*)src;
            pdst = (char*)dst;
            while(size--) {
                *pdst++ = *psrc++;
            }
        }
        return dst;
    }
    int main() {
        cout << "Hello world!" << endl;
        return 0;
    }
    /*
    struct {
      char name[40];
      int age;
    } person, person_copy;
    
    int main () {
      char myname[] = "Pierre de Fermat";
    
      // using memcpy to copy string:
      memcpy ( person.name, myname, strlen(myname)+1 );
      person.age = 46;
    
      // using memcpy to copy structure:
      memcpy ( &person_copy, &person, sizeof(person) );
    
      printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );
    
      return 0;
    }
    */
    

  • 相关阅读:
    bootstrap-table设置表头宽度无效的解决方案
    bootstrap-table设置某列序号自增
    arguments.callee
    javascript中break和continue
    javascript数据类型
    <script>标签的属性
    javascript核心
    javascript中数据属性与访问器属性
    解决ie9以下下不支持html5和媒体查询(Media Queries)
    用firefox获取html页面元素的Xpath
  • 原文地址:https://www.cnblogs.com/robbychan/p/3787153.html
Copyright © 2011-2022 走看看