吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8486|回复: 26
收起左侧

[C&C++ 原创] 【一起学C】C语言面试题必考:字符串操作函数,内存操作函数实现

  [复制链接]
奉聪 发表于 2017-1-24 14:29
本帖最后由 奉聪 于 2017-1-25 14:54 编辑



*******前言*******

我数一下,我发了几个帖子,1、2、3?

哈哈哈,没几个哈,感谢吾爱,让我学到了很多,乐于分享,共同进步!

最近也是在学c语言,也看了少许面试题

指针,数据结构,字符串操作肯定是重点

今天分享出来的是,一些字符串操作函数和一些内存操作函数的手动实现

内容应该不难,如有错误还请朋友们指出,我会认真改正的,希望一起学习进步


*******目录*******

字符串常见函数:

strlen、strcmp、strcpy、strlwr、strrev、strset、strstr、strupr、itoa、atoi、atof、ftoa

(希望初学者能够尝试用 下标访问指针访问两种方式实现)

内存操作少许函数:

memccpy、memchr、memcpy、memicmp、memmove、memset

(希望读者能够认真手动实现)


当然实际开发中,这些函数直接调用就行了,

但是面试的时候,这是基础知识,这是考察你的基本功 和 砍你工资的大斧

因为简单,所以代码注释少,有疑惑的请告诉我,乐于交流

*******字符串函数*******

1.strlen:计算字符串长度(不包含'\0')

实现想法:遍历字符串,直到'\0'结束

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//指针法
unsigned int mystrlenaddr(const char * str)  //为什么使用const char,我们只计数不对原数据进行改变
{
        int length = 0;  //长度初始化为0
        while (*str++)
        {
                length++;
        }
        return length;
}


void main()
{
        char * str = "fengcong is fucking too handsome";  //32个
        //printf("%d\n", strlen(str));
        printf("%d\n", mystrlenaddr(str));

        system("pause");
}

2.strcmp:比较字符串大小(一般用于字符串排序)

实现想法:依次从字符串开始一直找到不同的那个字符进行比较,得出大小

[C] 纯文本查看 复制代码
#include<string.h>
#include<stdio.h>
#include<stdlib.h>

//掌握指针法
int mystrcmp(char const * str1, const char * str2)
{
        while (*str1 == *str2 && *str1 != '0')  //一直找到两个字符串不同的地方
        {
                str1++;
                str2++;
        }
        if (*str1 > *str2)
                return 1;
        else if (*str1 < *str2)
                return -1;
        else
                return 0;
}

void main()
{
        char * str = "feng1";
        char * str1 = "feng2";

        //printf("%d\n", strcmp(str, str1));

        printf("%d\n", mystrcmp(str, str1));


        system("pause");
}

3.strcpy:用于字符串复制(复制包含'\0')

实现想法:一直复制到'\0'结束

[C] 纯文本查看 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

//指针法
char * mystrcpyaddr(char * dest, const char * source)
{
        if (dest == NULL || source == NULL)
        {
                return NULL;   //如果目的操作或者源为空,那么久直接返回
        }

        while (*dest++ = *source++)  //装X写法
                ;
        return dest;
}

//下标法
char * mystrcpyindex(char * dest, const char * source)
{
        if (dest == NULL || source == NULL)
        {
                return NULL;   //如果目的操作或者源为空,那么久直接返回
        }
        int i = 0;
        while (source != '\0')
        {
                dest = source;
                i++;
        }
        dest = source; //因为要把最后的\0拷贝过去
        return dest;
}

void main()
{
        char * str = "fengcong is fucking too handsome";
        char str1[100]; //目的字符数组
        //strcpy(str1, str);
        //printf("%s\n", str1);
        mystrcpyindex(str1, str);
        printf("%s\n", str1);


        system("pause");
}

4.strlwr:大写转小写

实现想法:遍历字符串,遇到大写转为小写

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char * mystrlwr(char * str)
{
        char * p1 = str;
        while (*p1)
        {
                if (*p1 >= 'A' && *p1 <= 'Z')
                {
                        *p1 += 32;
                }
                p1++;
        }
        return str;
}

void main()
{
        char str[50] = "FENGCONG IS FUCKING TOO HANDSOME";
        //printf("%s\n", _strlwr(str));
        printf("%s\n", mystrlwr(str));


        system("pause");
}

5.strrev:字符串逆转

实现想法:头首交换,直到中间

[C] 纯文本查看 复制代码
#include<string.h>
#include<stdio.h>
#include<stdlib.h>

char * mystrrev(char * str)
{
        char * p2 = str;
        char * p1 = str;
        while (*p1++)
        {
                ;
        }
        p1 -= 2; //回到最后一个字符
        while (p1 - p2 >= 1)
        {
                char temp = *p1;
                *p1 = *p2;
                *p2 = temp;
                p2++;
                p1--;
        }
        return str;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        //_strrev(str);
        //printf("%s\n", str);
        printf("%s\n",mystrrev(str));

        system("pause");
}

6.strset:将字符串全部设成某字符

实现想法:遍历字符串,每个字符设置某字符,直至'\0'

[C] 纯文本查看 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include<string.h>
#include<stdio.h>
#include<stdlib.h>

char * mystrset(char * str, int value)
{
        char * p1 = str;
        while (*p1)
        {
                *p1 = value;
                p1++;
        }
        return str;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        //printf("%s\n", _strset(str, 'A'));
        printf("%s\n", mystrset(str, 'A'));

        system("pause");
}

7.strstr:寻找母串中是否存在某个子串(稍难)

实现想法:依次比对

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//下标 法
char * mystrstrindex(char * const momstr, const char * const sonstr)//前者指针指向的数据可变,但是指针不可变,后者都不可变
{
        int momlen = strlen(momstr); //母串的长度
        int sonlen = strlen(sonstr); //子串的长度

        for (int i = 0; i < (momlen - sonlen); i++)  //从0开始循环母串,到momlen-sonlen停止
        { 
                int flag = 1;
                for (int j = 0; j < sonlen; j++)
                {

                        if (momstr[i + j] != sonstr[j])
                        {
                                flag = 0;
                                break;  //如果出现不相等就 退出循环,继续从下面一个寻找
                        }
                }
                if (flag)
                {
                        return (&momstr);
                }
        }
        return NULL;
}

//指针法
char * mystrstraddr(char * const momstr, const char * const sonstr)
{
        char * mstr = momstr;  //母串

        while (*mstr)
        {
                char * sstr = sonstr;  //子串
                char * momnowstr = mstr;  //记录现在母串的位置
                int flag = 1;
                while (*sstr != 0)
                {
                        if (*sstr != *momnowstr || *momnowstr == '0')
                        {
                                flag = 0;
                                break;
                        }
                        momnowstr++;
                        sstr++;
                }
                if (flag)
                {
                        return mstr;
                }
                
                mstr++; //母串对比位置+1
        }
        return NULL;
}

void main()
{
        char * str = "fengcong is too fucking handsome";
        //printf("%p", strstr(str, "fengcong"));
        //printf("%p", mystrstrindex(str, "engcong"));
        printf("%p", mystrstraddr(str, "some"));

        system("pause");
}

8.strupr:小写转大写

实现想法:依次遍历,遇到小写转为大写

[C] 纯文本查看 复制代码
#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char * mystrupr(char * str)
{
        char * p1 = str;
        while (*p1)
        {
                if (*p1 >= 'a' && *p1 <= 'z')
                {
                        *p1 -= 32;
                }
                p1++;
        }
        return str;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        //printf("%s\n", _strupr(str));
        printf("%s\n", mystrupr(str));


        system("pause");
}

9.itoa:整数转字符串

[C] 纯文本查看 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

char * myitoa(int value, char * str)
{
        char * pstr = str; //str本身不能改变,一会要返回str
        if (value < 0)
        {
                *pstr = '-';
                pstr++;
                value *= -1; //转变为正数处理
        }
        int wei = 1;  //数至少一位
        int ivalue = value; //用于测试长度
        while ((ivalue /=   10) != 0)
        {
                wei++;
        }

        pstr += wei-1;
        while (value % 10 != 0)
        {
                *pstr-- = (value % 10)+'0';
                value /= 10;
        }
        return str;
}

void main()
{
        int num = -45644;
        char str[20] = { 0 };

        printf("%s", myitoa(num, str));



        system("pause");
}

10.atoi:字符串转整数(遇到非数字字符结束)

[C] 纯文本查看 复制代码
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int myatoi(const char * str)
{
        if (str == NULL)
        {
                return 0;  
        }
        int num = 0; //需要返回的值
        int flag = 1; //记录正负号
        if (*str == '-')
        {
                flag = -1;
                str++;
        }
        else if (*str == '+')
        {
                str++;
        }

        while (*str >= '0' && *str <= '9')
        {
                num= (num * 10 + (*str - '0'));
                str++;
        }

        return num*flag;
}

void main()
{
        char str[20] = "-57124";
        int num = 0;

        printf("%d\n",myatoi(str));



        system("pause");
}


11.atof:字符串转浮点数

[C] 纯文本查看 复制代码
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

double myatof(char const * str)
{
        if (str == NULL)
                return 0;

        //首先判断有无符号位
        int flag = 1;
        if (*str == '-')
        {
                flag = -1;
                str++;
        }
        if (*str == '+')
        {
                str++;
        }
        int zhengshu = 0;  //存储整数部分
        while (*str >= '0' && *str <= '9')
        {
                zhengshu = zhengshu * 10 + (*str - '0');
                *str++;
        }
        //整数部分循环完了
        double xiaoshu = 0.0;  //存储小数部分
        //因为不明符号停止整数循环
        if (*str != '.')
        {
                return (flag * zhengshu);
        }
        else //代表遇到. 结束
        {
                str++; //指向小数部分第一位
                double i = 0.1;
                while (*str >= '0' && *str <= '9')
                {
                        xiaoshu = xiaoshu + (*str - '0')*i;
                        i /= 10;
                        str++;
                }

                return flag *(zhengshu + xiaoshu);
        }
}

void main()
{
        char str[20] = "2.1554";
        double db = 0.0;
        printf("%lf\n", myatof(str));


        system("pause");
}

12.ftoa:浮点数转字符串(浮点数存储不准确,可能有少许误差)

[C] 纯文本查看 复制代码
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

char * myftoa(double db, char * str)
{
        char * pstr = str;
        //先判断 符号位
        if (db < 0)
        {
                *pstr = '-';
                db *= -1;  //转为正数处理
                pstr++;
        }
        //整数部分
        int zhengshu = (int)db;
        int izhengshu = zhengshu; //牺牲于记录整数长度
        int wei = 1;  //整数部分至少一位
        while ((izhengshu /= 10) != 0)
        {
                wei++;
        }
        pstr += wei - 1;
        for (int i = 0; i < wei; i++)
        {
                *pstr-- = zhengshu % 10 + '0';
                zhengshu /= 10;
        }
        pstr += (wei+1);
        *pstr = '.';
        pstr++;
        //小数部分
        double xiaoshu = db - (int)db;
        for (int i = 0; i < 6; i++)
        {
                *pstr++ = (int)(xiaoshu * 10) + '0';
                xiaoshu = xiaoshu * 10 - (int)(xiaoshu * 10);
        }
        return str;
}

void main()
{
        double db = -2.11;
        char str[20] = { 0 };
        printf("%s\n", myftoa(db,str));
        


        system("pause");
}

*******内存操作函数*******

1.memccpy:内存拷贝,直到一个值结束

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
//下标法
void * mymemccpybyindex(void * dest, const void * sor,int val, size_t len)
{
        if (dest == NULL || sor == NULL)
        {
                return NULL;
        }
        for (int i = 0; i < len; i++)
        {
                if( (((char*)dest) = ((char*)sor)) == val)
                        return dest;
        }
        return dest;
}
//指针法
void * mymemccpybyaddr(void * dest, const void * sor,int val, size_t len)
{
        if (dest == NULL || sor == NULL)
        {
                return NULL;
        }
        char * pdest = dest;
        char * psor = sor;
        char * plast = (char *)sor + len;
        while (psor < plast)
        {
                if ((*pdest++ = *psor++) == val)
                        return dest;

        }
        return dest;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        char * pstr = (char[50]) { 0 };  //在栈上开辟一段内存
        //printf("%s\n", memccpy(pstr,str,'s',32));
        printf("%s\n", mymemccpybyaddr(pstr, str, 'f', 32));

        system("pause");
}

2.memchr:某段内存中寻找某个值

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>

void * mymemchar(void * buf, int val, size_t size)
{
        if (buf == NULL)
        {
                return NULL;
        }
        char * p = buf;
        char plast = p + size;
        while (p < plast)
        {
                if (*p == val)
                {
                        return p;
                }
                p++;
        }
        return NULL;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        printf("%s\n", mymemchar(str, 'g', 8));


        system("pause");
}

3.memcpy:拷贝某段内存

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
//下标法
void * mymemcpybyindex(void * dest, const void * sor, size_t len)
{
        if (dest == NULL || sor == NULL)
        {
                return NULL;
        }
        for (int i = 0; i < len; i++)
        {
                ((char*)dest) = ((char*)sor);
        }
        return dest;
}
//指针法
void * mymemcpybyaddr(void * dest, const void * sor, size_t len)
{
        if (dest == NULL || sor == NULL)
        {
                return NULL;
        }
        char * pdest = dest;
        char * psor = sor;
        char * plast = (char * )sor + len;
        while (psor < plast)
        {
                *pdest++ = *psor++;

        }
        return dest;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        char * pstr = (char[50]) { 0 };  //在栈上开辟一段内存

        //printf("%s\n", memcpy(pstr, str, 32));
        printf("%s\n", mymemcpybyaddr(pstr, str, 31));


        system("pause");
}

4.memicmp:比较某段内存大小(一个字节一个字节比较,像strcmp)

注意:切不可用来比较整数,除非一字节整数,因为整数存储方式是高位高字节

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>

int mymemicmpbyaddr(const void * buf1, const void * buf2, size_t size)
{
        char * p1 = buf1;
        char * p2 = buf2;
        int i = 0;
        while(*p1 == *p2 && i < size)
        {
                p1++;
                p2++;
                i++;
        }
        if (*p1 > *p2)
        {
                return 1;
        }
        else if (*p1 < *p2)
                return -1;
        else
                return 0;

}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        char str1[50] = "fengfeng is fucking too handsome";

        printf("%d\n", mymemicmpbyaddr(str, str1, 32));
        system("pause");
}

5.memmove:和memcpy类似,但是memmove采用了中间空间,memcpy是直接拷贝

两者区别之处在于当拷贝地址重复的时候,结果不一样(比较代码可知)

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<malloc.h>
void * mymemmove(void * dest, const void * sor, size_t size)
{
        char * ptemp = malloc(size); //中间 地址
        memcpy(ptemp, sor, size);
        memcpy(dest, ptemp, size);
        free(ptemp);
}


void main()
{
        char str[50] = "fengcong is fucking too handsome";
        //memmove(str + 3, str + 4, 2);
        mymemmove(str + 3, str + 4, 2);
        printf("%s\n",str);



        system("pause");
}

6.memset:对指定内存每个字节赋某个值

[C] 纯文本查看 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>

//下标法
void * mymemsetbyindex(void * dest, int val, size_t len)
{
        if (dest == NULL)
        {
                return NULL;
        }
        if (len == 0)
        {
                return dest;
        }
        char * p = dest;
        for (int i = 0; i < len; i++)
        {
                p = val;
        }
        return dest;
}

//指针法
void * mymemsetbyaddr(void * dest, int val, size_t len)
{
        if (dest == NULL)
        {
                return NULL;
        }
        if (len == 0)
        {
                return dest;
        }
        char * p = dest;
        char * plast = p + len;
        while (p < plast)
        {
                *p++ = val;
        }
        return dest;
}

void main()
{
        char str[50] = "fengcong is fucking too handsome";
        //printf("%s\n", memset(str, 65, 8));
        printf("%s\n", mymemsetbyaddr(str, 65, 8));
        system("pause");
}
*******结束语*******

内容应该都不难,希望大家讨论讨论,认真实现,不要让这基本功成为

面试官挥动大斧砍你工资的把柄

文中代码区,少许地方少*,不知道为什么,请注意添加
再会了,还是那句话,你们开心就好,拜个早年!

= ̄ω ̄=

免费评分

参与人数 9吾爱币 +20 热心值 +9 收起 理由
腾龙细雨 + 1 + 1 我很赞同!
Cizel + 10 + 1 我很赞同!
kai.wu + 1 + 1 一个月前发就好了!
IBinary + 1 + 1 楼主说的很对,当自己实现一边,或者做个经典算法笔记,以后找工作看一遍,对自.
BY丶显示 + 2 + 1 鼓励转贴优秀软件安全工具和文档!
liptm304 + 2 + 1 谢谢@Thanks!
s3233431 + 2 + 1 谢谢分享,学习了
飘荡的心 + 1 + 1 谢谢@Thanks!
lp-cg + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

  • · Aarow|主题: 988, 订阅: 304

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 奉聪 发表于 2017-1-25 13:59
魔术使nqy 发表于 2017-1-25 13:50
楼主,你的C语言在哪里学的啊?有没有视频可以分享一下呢?为什么我学的C比你的少那么多函数的呢?上面你说 ...

尹成C,但是现在360云分享不了,你可以去悬赏贴问问有没有百度云链接
魔术使nqy 发表于 2017-1-25 13:50 来自手机
楼主,你的C语言在哪里学的啊?有没有视频可以分享一下呢?为什么我学的C比你的少那么多函数的呢?上面你说的函数有很多我都没见过的
 楼主| 奉聪 发表于 2017-1-24 14:32
hishzzjm 发表于 2017-1-24 14:39
收藏一下,正学语言来着
hyp888 发表于 2017-1-24 14:40
好乱啊,排版难看呢
若轩大大 发表于 2017-1-24 14:53
我们期末实验报告就是自己写字符串库函数
 楼主| 奉聪 发表于 2017-1-24 14:53
hyp888 发表于 2017-1-24 14:40
好乱啊,排版难看呢

我排好了的,他自己乱的
 楼主| 奉聪 发表于 2017-1-24 14:57
若轩大大 发表于 2017-1-24 14:53
我们期末实验报告就是自己写字符串库函数

加油罗!
头像被屏蔽
zhaogang5807 发表于 2017-1-24 15:11
提示: 作者被禁止或删除 内容自动屏蔽
yxhjxne 发表于 2017-1-24 16:14
支持一下!
hello!你很阳光 发表于 2017-1-24 16:25
(敲黑板)这些是重点复习,哈哈哈,乱归乱,但还是能看的,支持一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 04:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表