鱼C论坛

 找回密码
 立即注册
查看: 1249|回复: 12

[已解决]小甲鱼课后习题进阶版strncpy函数

[复制链接]
发表于 2021-11-15 20:35:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 林江楠 于 2021-11-15 20:37 编辑
#include <stdio.h>

#define MAX 1024

int main()
{
        char str1[MAX];
        char str2[MAX];

        char *target1 = str1;
        char *target2 = str2;

        char ch;
        int n;

        printf("请输入一个字符串到 str1 中:");
        fgets(str1, MAX, stdin);

        printf("请输入需要拷贝的字符个数:");
        scanf("%d", &n);

        printf("开始拷贝 str1 的内容到 str2 中...\n");
        while (n--)
        {
               ch = *target2++ = *target1++;
               if (ch == '\0')
               {
                       break;
               }
               if ((int)ch < 0)
               {
                       *target2++ = *target1++;
                       *target2++ = *target1++;
               }
        }

        *target2 = '\0';

        printf("拷贝完毕!\n");
        printf("现在,str2 中的内容是:%s\n", str2);

        return 0;
}

为什么要写那麽多*target2++ = *target1++;
这串代码从while开始就不懂了


为社么能拷贝中英混合的字符串

看不懂
最佳答案
2021-11-15 22:06:13
本帖最后由 wutianlong220 于 2021-11-15 22:18 编辑

先贴上我自己写的答案,测试有效:
#include <stdio.h>
#define MAX 1024


int main(void) {
    
    char str1[MAX] = {'\0'};
    char str2[MAX] = {'\0'};
    int num;
    int start = 0;


    printf("请输入一个字符串到 str1 中:");


    fgets(str1, MAX, stdin);
    
    printf("请输入您需要拷贝的字符个数:");
    scanf("%d",&num);
    
    printf("您输入的字符是:%s\n",str1);
    
    printf("开始拷贝 str1 的内容到 str2 中...\n");

    char *str1_p = str1;
    char *str2_p = str2;


    while((start < num)  &&  *str1_p != '\0'     ) {
        int ch = (int)*str1_p;
        if (ch < 0) { //这里是专门对中文的处理,因为中文是4个字节,3个负数1个0,所以指针需要复制3次
            *str2_p++ = *str1_p++;
            *str2_p++ = *str1_p++;
            *str2_p++ = *str1_p++;
        } else {
            *str2_p++ = *str1_p++;
        }
        start++;
    }
    
    printf("拷贝完毕!\n");
    printf("现在,str2 中的内容是:%s\n",str2);


    return 0;
}

然后来给你解释一下
*target2++ = *target1++;

这句话到底是什么意思。

这句话的其实就是著名的代码:*p++
所谓的*p++,就是分成两个步骤:
第一,*p
第二,p++


因为p++,是先把p拿过来用,用完了以后再+1,所以整个*p++的意思就是:
p这个指针,先用*符号解引用,拿出里面的东西,然后指针p再向后面移动一位。
如果不太理解,可以点击这里:https://www.bilibili.com/video/BV1sJ411E7St?p=87
可以参考这个视频,从12分28秒开始看,相信你会有所领悟。

懂了之后
然后我们再来看
*target2++ = *target1++

这段代码的意思就是说:
先执行:
*target2 = *target1
也就是先把target1指针,指向的内容,赋值给target2指针指向的地方,
然后:
target2++;
target1++;
也就是两个指针,同时向后移动一位。

懂了吧?
放在这个题目里面就相当于:
str1[0] = str2[0]
然后
str1[1] = str2[1]
然后
str1[2] = str2[2]
然后
str1[3] = str2[3]
一直这样下去。

所以就是,str2和str1这个数组,两个同时向后,一个一个去遍历,遍历一个,str2把内容给str1,然后再遍历到下一个,str2再把内容给str1,然后从数组的最初,一直折腾到指定位置,这样就完成了复制。
所以,关键在于你要记住:
*p++
这个东西,一定要牢牢记住,这个非常重要。


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-15 21:36:57 | 显示全部楼层
#include <stdio.h>

#define MAX 1024

int main()
{
        char str1[MAX];
        char str2[MAX];

        char *target1 = str1;
        char *target2 = str2;

        char ch;
        int n;

        printf("请输入一个字符串到 str1 中:");
        fgets(str1, MAX, stdin);

        printf("请输入需要拷贝的字符个数:");
        scanf("%d", &n);

        printf("开始拷贝 str1 的内容到 str2 中...\n");
        while (n--)
        {
               //ch = *target2++ = *target1++;
               *target2 = *target1;
               ch = *target2;
               target1++;
               target2++;

               if (ch == '\0')
               {
                       break;
               }
               if ((int)ch < 0)
               {
                       //*target2++ = *target1++;
                       *target2 = *target1;
                       target1++;
                       target2++;

                       //*target2++ = *target1++;
                       *target2 = *target1;
                       target1++;
                       target2++;

               }
        }

        *target2 = '\0';

        printf("拷贝完毕!\n");
        printf("现在,str2 中的内容是:%s\n", str2);

        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-15 22:06:13 | 显示全部楼层    本楼为最佳答案   
本帖最后由 wutianlong220 于 2021-11-15 22:18 编辑

先贴上我自己写的答案,测试有效:
#include <stdio.h>
#define MAX 1024


int main(void) {
    
    char str1[MAX] = {'\0'};
    char str2[MAX] = {'\0'};
    int num;
    int start = 0;


    printf("请输入一个字符串到 str1 中:");


    fgets(str1, MAX, stdin);
    
    printf("请输入您需要拷贝的字符个数:");
    scanf("%d",&num);
    
    printf("您输入的字符是:%s\n",str1);
    
    printf("开始拷贝 str1 的内容到 str2 中...\n");

    char *str1_p = str1;
    char *str2_p = str2;


    while((start < num)  &&  *str1_p != '\0'     ) {
        int ch = (int)*str1_p;
        if (ch < 0) { //这里是专门对中文的处理,因为中文是4个字节,3个负数1个0,所以指针需要复制3次
            *str2_p++ = *str1_p++;
            *str2_p++ = *str1_p++;
            *str2_p++ = *str1_p++;
        } else {
            *str2_p++ = *str1_p++;
        }
        start++;
    }
    
    printf("拷贝完毕!\n");
    printf("现在,str2 中的内容是:%s\n",str2);


    return 0;
}

然后来给你解释一下
*target2++ = *target1++;

这句话到底是什么意思。

这句话的其实就是著名的代码:*p++
所谓的*p++,就是分成两个步骤:
第一,*p
第二,p++


因为p++,是先把p拿过来用,用完了以后再+1,所以整个*p++的意思就是:
p这个指针,先用*符号解引用,拿出里面的东西,然后指针p再向后面移动一位。
如果不太理解,可以点击这里:https://www.bilibili.com/video/BV1sJ411E7St?p=87
可以参考这个视频,从12分28秒开始看,相信你会有所领悟。

懂了之后
然后我们再来看
*target2++ = *target1++

这段代码的意思就是说:
先执行:
*target2 = *target1
也就是先把target1指针,指向的内容,赋值给target2指针指向的地方,
然后:
target2++;
target1++;
也就是两个指针,同时向后移动一位。

懂了吧?
放在这个题目里面就相当于:
str1[0] = str2[0]
然后
str1[1] = str2[1]
然后
str1[2] = str2[2]
然后
str1[3] = str2[3]
一直这样下去。

所以就是,str2和str1这个数组,两个同时向后,一个一个去遍历,遍历一个,str2把内容给str1,然后再遍历到下一个,str2再把内容给str1,然后从数组的最初,一直折腾到指定位置,这样就完成了复制。
所以,关键在于你要记住:
*p++
这个东西,一定要牢牢记住,这个非常重要。


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-17 08:33:48 From FishC Mobile | 显示全部楼层
wutianlong220 发表于 2021-11-15 22:06
先贴上我自己写的答案,测试有效:



自增运算符的优先级高于取值运算符
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-17 08:37:05 From FishC Mobile | 显示全部楼层
wutianlong220 发表于 2021-11-15 22:06
先贴上我自己写的答案,测试有效:



这个相当于*(target++)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-17 08:41:01 From FishC Mobile | 显示全部楼层
人造人 发表于 2021-11-15 21:36

为什么小于0的时候需要两次target1++=target2++
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 11:21:45 | 显示全部楼层
因为小于0的时候,代表这个字符是中文啊,正常的英文字母只占1个位置,所以
target1++=target2++
只需要这样复制且移动一下就行。
但是一个中文,比一个英文多占用2个字节,所以指针还得多向后面移动2位,才能把一个中文完整复制过来,懂了吧?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 11:23:32 | 显示全部楼层
林江楠 发表于 2021-11-17 08:37
这个相当于*(target++)

你这样括号括起来就错了,括号括起来代表括号必须先执行。
实际上是相当于:
*target++ //这个代码就等于下面的代码

*target;
target++;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 11:51:02 | 显示全部楼层
林江楠 发表于 2021-11-17 08:41
为什么小于0的时候需要两次target1++=target2++

因为这里假设一个中文字符是3个字节
你那边可能是2个字节也可能是3个字节
这个程序假设是3个字节
这个程序还假设中文字符的3个字节都是负数
所以,小于0就加2次
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 11:55:31 | 显示全部楼层
wutianlong220 发表于 2021-11-17 11:23
你这样括号括起来就错了,括号括起来代表括号必须先执行。
实际上是相当于:
    int num = *p++;

这个相当于下面这样
        int *temp = p;
        p++;
        num = *temp;

完整的代码
#include <stdio.h>

int main(void) {
    int array[5] = {1, 2, 3, 4, 5};
    int *p = array;
    int num = *p++;
    {
        int *temp = p;
        p++;
        num = *temp;
    }
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 14:49:14 | 显示全部楼层
学习 来了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-17 17:10:05 | 显示全部楼层
wutianlong220 发表于 2021-11-17 11:23
你这样括号括起来就错了,括号括起来代表括号必须先执行。
实际上是相当于:

不是吧

自增运算符的优先级高于取值运算符

先加在解引用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 20:47:58 | 显示全部楼层
林江楠 发表于 2021-11-17 17:10
不是吧

自增运算符的优先级高于取值运算符

自增运算符的优先级高于取值运算符,这个是对的。但是q++这个自增,是先用完q之后再自增,跟++q的先加了数字再用,是不一样的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-23 01:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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