几个字符串操作函数(深析)

1、mystrupr -- 将小写字母转换为大写(my-string-up)

#include

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

int main()
{
    char str[] = "Hello World";
    mystrupr(str);
    printf("%s",str);
    return 0;
}

核心代码:

while(*str)
   {
       if(*str >= 'a' && *str <= 'z')
        *str -= 'a' - 'A';
       str++;
   }

小写字母的ASCII要大32

即'a' - 'A' == 32,所以换成32也可

2、mystrlen -- 计算字符串长度(my-string-lenth)

#include

int mystrlen(char *str)
{
   int len=0;
   while(*str++)
   {
       len++;
   }
   return len;
}

int main()
{
    char str[] = "Hello World";
    printf("%d",mystrlen(str));
    return 0;
}

注意:函数命名时,返回什么类型就用什么类型

3、mystrcpy -- 复制(赋值)字符串(my-string-copy)  

因为字符串不能直接用”=“进行赋值,要用mystrcpy,所以我觉得也可以叫赋值字符串

#include

char *mystrcpy(char *str1,const char *str2)
{
    while(*str2 != '\0')
    {
        *str1 = *str2;
        str2++;
        str1++;
    }
    *str1 = '\0';
    return str1;
}
int main()
{
    char s1[30],s2[30],s3[30];
    gets(s1);
    mystrcpy(s3,mystrcpy(s2,s1));
    printf("%s\n",s1);
    printf("%s\n",s2);
    printf("%s",s3);
    return 0;
}

函数部分可以有所改进:

1)while条件中,由(*str2 != '\0')改为(*str1++ = *str2++),指针的移动和复制都在一行中运行,更加简洁,同时后面的*str1 = '\0';也不用了

2)return str1;可能存在问题,因为在前面的操作中,指针是指向最后一个字符的,返回后可能对后面有影响,所以要再定义一个指针进行储存

注意:while可以是空主体,但不要忘了结尾

改进后:

#include

char *mystrcpy(char *str1,const char *str2)
{
    char *start = str2;
    while(*str1++ = *str2++);
    return start;
}
int main()
{
    char s1[30],s2[30],s3[30];
    gets(s1);
    mystrcpy(s3,mystrcpy(s2,s1));
    printf("%s\n",s1);
    printf("%s\n",s2);
    printf("%s",s3);
    return 0;
}

改进过后我又有了新发现:

我对while(*str1++ = *str2++);这个经典的 C 语言字符串拷贝深入研究了一下

第一个点:++的前后置

前置

int i = 5;
int j = ++i;  // i 先增加到 6,然后 j 被赋值为 6
printf("i = %d, j = %d\n", i, j);  // 输出: i = 6, j = 6

 在int j = ++i;中,有两个步骤,++和=,因为++在前,所以先把i加1,再把增加后的i赋给j

后置

int i = 5;
int j = i++;  // j 被赋值为 5,然后 i 增加到 6
printf("i = %d, j = %d\n", i, j);  // 输出: i = 6, j = 5

同理,只是++在后,先把i赋给j,再把i加1

就是一个运行循序的问题

第二个点:while的新理解

首先,括号里面不仅仅是一个用来判断的条件,准确来说是一个可以有操作的语句,也就是表达式

正如代码中的赋值,++自增操作

其次,如果循环主体只有一句,可以不用{},(这与if、for一样)

也可以没有主体,但一定要以结尾,

记得之前上课时,还因为如下情况,被批评    ̄へ ̄

while(条件);//这里

{
   主体
}

 特殊情况是要加那个分号的:

while(*str1++ = *str2++);
第三个点:条件判断

*str1++ = *str2++这个表达式的值就是*str1,循环就是以这个指针指向'\0'结束

我不禁产生'\0'和0,抑或是其它含0的,是否都有false的含义

我发现:只有'\0'没有真值,即false含义,但指向它的指针,即空指针是有false含义

从deepseek中得到以下结果:

数据类型 值为 0 或包含 0 布尔上下文中的意义
整数 0 false
整数 非零(如 10-1 true
字符串 '\0'(字符串结束符) 不影响字符串指针的真值
指针 NULL 或 0 false
指针 非空指针 true
浮点数 0.0 false
浮点数 非零(如 0.1-0.5 true
while(*str1++ = *str2++);

 总结一下这个表达式:把str2的字符逐一赋值给str1,每一次先赋值,然后同时自增移动,根据赋值表达式的值为左值,所以表达式的值为指针*str1,循环以*str1指向'\0'结束,因此实现了字符串的拷贝,并且'\0'也拷贝上了。

4、mystrcat -- 连接字符串(my-sting-cat)

这个cat不是猫,在计算机领域,有显示和连接之意

#include

char *mystrcat(char *str1,char *str2)
{
    char *end=str1;
    while(*str1)
    {
        str1++;
    }
    while(*str1++ = *str2++);
    return end;
}

int main(void)
{
    char s1[100] = "Winter ", s2[60] = "is ", s3[30] = "comming.";
    mystrcat(s1, mystrcat(s2, s3));
    printf("%s", s1);
    return 0;
}

1)这个地方我有所悟:定义一个指针end指向指针 str1,本质上是保存了str1的第一个字符的地址,地址是不变的(前提是在程序的每一次运行中,因为操作系统会动态分配内存),尽管后面str1的内容发生了改变,但它第一个字符的地址不会改变,最后返回的指针end,仍指向同一个字符串的第一个字符

换句话说,字符串后面的字符改变后,改变之前指向第一个字符的指针仍指的是同一字符串,并不会产生新的字符串

在思考的过程中,我又再想,指针str1是'W'的地址,指针end是str1的地址,把'W'比作一个地点,而str1就这个地点的地图,而end又是标记str1这个地图的位置的地图,看似形象,但指针的移动又该怎么解释呢?

最后眼前一亮:指针的全称是指针变量,变量!!

变量是在内存中的一片空间,空间里是用来表示01的开关,以二进制来表示这个变量的值

现在在内存中开辟一片空间,这个空间命名为str1,在这个空间中某一段通过开关表示的二进制数(根据ASCII码)表示出字母,储存其中

而地址并不是由空间里的开关(存储单元)表示,开关(储存单元)用于存储数据,也就是数字,字符等,

char *end=str1;

总结一下这段代码:作用时让指针重新指回第一个字节

向内存申请一片空间,命名为end

(空间由起始地址和大小【多少个字节】决定,命名是为了方便访问)

空间内的数据为另一片空间str1的地址,

而str1是s2的虚参,一个指针一个字符型数组,本质上是一个东西(数组是只能指向第一位,不能移动的指针),

所以str1有双重身份,

作数组时,str1空间内的数据是'Winter'的ASCLL码,作指针时,str1空间内的数据是'Winter'的'W'的地址

补:与指针相比,数组除了不能移动,也不能被赋值,因为数组名还叫做常量指针(int*const)

想要赋值,可以用循环逐一赋值,抑或用指针来遍历

2)三种情况:

最终指向'\0'

 while(*str1)
    {
        str1++;
    }

 越界

 while(*str1++);

 指向'\0',但跳过第一个字符

 while(*++str1);

5、mystrcmp -- 比较字符串(my-string-compare)

#include 

int mystrcmp(const char *s1, const char *s2)
{
    while(*s1 != '\0' && *s2 != '\0')
    {
        if(*s1 == *s2)
        {
            s1++;
            s2++;
        }
        else if(*s1 > *s2)
            return 1;
        else
            return -1;
    }
    return 0;
}

int main()
{
    char s1[30], s2[30];
    scanf("%s", s1);
    scanf("%s", s2);
    if (mystrcmp(s1, s2) > 0)
    {
        printf("%s > %s\n", s1, s2);
    }
    if (mystrcmp(s1, s2) == 0)
    {
        printf("%s == %s\n", s1, s2);
    }
    if (mystrcmp(s1, s2) < 0)
    {
        printf("%s < %s\n", s1, s2);
    }
    return 0;
}

优化:

#include 

int mystrcmp(const char *s1, const char *s2)
{
    while(*s1 && *s2 && *s1 == *s2)
    {
        s1++;
        s2++;
    }
    return *s1 - *s2; //更简洁
}

int main()
{
    char s1[30], s2[30];
    scanf("%s", s1);
    scanf("%s", s2);
    if (mystrcmp(s1, s2) > 0)
    {
        printf("%s > %s\n", s1, s2);
    }
    if (mystrcmp(s1, s2) == 0)
    {
        printf("%s == %s\n", s1, s2);
    }
    if (mystrcmp(s1, s2) < 0)
    {
        printf("%s < %s\n", s1, s2);
    }
    return 0;
}

6、myatoi -- 数字字符转换整数(my-ASCII-to-integer)

#include 

int myatoi(const char *s)
{
    int num = 0;
    while(*s != '\0')
    {
        if(*s >= '0' && *s <= '9')
        {
            num = *s - '0' + num * 10;
        }
        s++;
    }
    return num;
}

int main(void)
{
    char s1[30] = "ab6@0gap49$";
    char s2[30] = "5rt1";
    int x = myatoi(s1);
    int y = myatoi(s2);
    int z = x + y;
    printf("%d + %d = %d\n", x, y, z);
    return 0;
}

字符变整数,减一个'0'即可

拨开云雾终见月,愿你写代码,如诗般轻盈~~

"今天是我的生日,愿你们也能在代码的世界里找到属于自己的快乐!"

你可能感兴趣的:(c语言,c++,算法)