鱼C论坛

 找回密码
 立即注册
查看: 44|回复: 5

两个insert函数实现功能区别

[复制链接]
发表于 昨天 23:10 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 赵珂夷 于 2025-11-20 23:57 编辑

代码1(我写的)程序思路:从先将s1的n位以后部分向后挪动,再将s2的字符串加入到字符串s1中
  1. #include <stdio.h>
  2. #include <string.h>
  3. void insert(char *s1,char *s2,int n)
  4. {
  5.     int i;
  6.     int l1=0,l2=0;
  7.     while (s1[l1]!=' '&&s1[l1]!='\0') l1++;
  8.     while (s2[l2]!=' '&&s2[l2]!='\0') l2++;
  9.     int k=0;

  10.     if(n>l1||n<0||s1==NULL||s2==NULL) printf("error");

  11.     else{
  12.         for(i=l1;i>=n;i--)
  13.         {
  14.             s1[i+l2]=s1[i];
  15.         }
  16.         
  17.         for(i=n;i<n+l2;i++)
  18.         {
  19.             s1[i]=s2[k];
  20.             k++;
  21.         }
  22.         s1[l1+l2]=' ';
  23.         s1[l1+l2+1]='\0';
  24.     }
  25. }
复制代码

代码2:学长/姐祖传代码 程序思路:将s1从第n项以及之后的项在s3中进行保存,将s2复制到s1的n位及以后位置,再将s3接入s1.
  1. #include <stdio.h>
  2. #include <string.h>
  3. void insert(char * s1,char * s2,int n)
  4. {
  5.     int i,len1,len2,j;
  6.     char s3[100]={0};
  7.     if(n<0||s1==NULL||s2==NULL)
  8.     {
  9.             printf("error");
  10.             return;
  11.     }
  12.     for(len1=0;s1[len1]!=' '&&s1[len1]!='\0';len1++);
  13.     for(len2=0;s2[len2]!=' '&&s2[len2]!='\0';len2++);
  14.     if(n>len1)
  15.     {
  16.             printf("error");
  17.             return;
  18.     }
  19.     for(i=n,j=0;i<len1;*(s3+j++)=*(s1+i++));
  20.     for(i=n,j=0;j<len2;*(s1+i++)=*(s2+j++));
  21.     for(i=n+len2,j=0;i<len1+len2;*(s1+i++)=*(s3+j++));
  22.     *(s1+len1+len2)=' ';
  23.     return;
  24. }
复制代码

我认为自己的函数编译输出结果正常
但是在学校C语言作业系统中评分为85分,以下是题目:
实现在字符串的内部增加字符串。

void insert(char * s1,char * s2, int n);
将s2指向的字符串的拷贝,添加到s1第n个字符的位置,原位置的字符后移。n=0时,s2增加到s1的首部;
n=s1的字符串长度时,s2增加到s1的末尾。

注意:使用空格字符来表示字符串的结束。
例如source指向位置,依次保存了字符'a',字符'b',字符空格' ',字符'c',则source指向的字符串为"ab"。

保存为functions.cpp。
遇到异常情况,输出"error";否则不要随意输出,会视为错误。

请问可能是哪些测试点我没有考虑到呢?或者说我的程序1和程序2有哪些实现功能上的区别?求问求问TAT

   

程序1运行结果

程序1运行结果
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 昨天 23:57 | 显示全部楼层
解决方法:将第二个for循环里面的内容更改成
  1. for(i=0;i<l2;i++)
  2.         {
  3.             s1[i+n]=s2[i];
  4.         }
复制代码

得分就是100了
原理不太懂
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 23:11 | 显示全部楼层
两个 insert 函数都旨在将字符串 s2 插入到字符串 s1 的第 n 位,但实现方式和正确性有显著区别。以下是详细分析:

代码1(你写的)存在多个错误,无法正常工作:
- 长度计算错误:在 while 循环中,s1 和 s2 是指针,但代码未解引用(例如应使用 *s1 检查字符),导致无限循环或错误计数。
- 字符移动逻辑错误:for 循环中的 s1=s1 和 s1=s2 未实际移动或复制字符,只是重复赋值指针。
- 未处理字符串终止符:最后设置 s1=' ' 和 s1='\0' 可能覆盖数据,且未正确分配空间。

代码2(学长/姐的祖传代码)采用更安全的思路:
- 使用临时数组 s3 保存 s1 中第 n 位后的部分,避免直接覆盖。
- 先复制 s2 到 s1 的指定位置,再追加 s3,确保数据完整性。

主要功能区别:
  • 代码1因逻辑错误无法实现插入,可能导致程序崩溃或错误输出。
  • 代码2通过临时存储正确实现插入,适用于大多数情况。


建议修改代码1:使用标准字符串函数(如 strcpy 和 memmove)或参考代码2的思路。例如,正确实现应计算长度、检查边界,并移动字符:


  1. #include <stdio.h>
  2. #include <string.h>
  3. void insert(char *s1, char *s2, int n) {
  4.     int len1 = strlen(s1);
  5.     int len2 = strlen(s2);
  6.     if (n < 0 || n > len1 || s1 == NULL || s2 == NULL) {
  7.         printf("error");
  8.         return;
  9.     }
  10.     // 移动原字符串部分
  11.     memmove(s1 + n + len2, s1 + n, len1 - n + 1);
  12.     // 插入新字符串
  13.     memcpy(s1 + n, s2, len2);
  14. }
复制代码


总之,代码2更可靠,而代码1需修正基础错误。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 23:17 | 显示全部楼层
本帖最后由 赵珂夷 于 2025-11-20 23:22 编辑
FishC 发表于 2025-11-20 23:11
两个 insert 函数都旨在将字符串 s2 插入到字符串 s1 的第 n 位,但实现方式和正确性有显著区别。以下是详 ...


你可以再看一看题目的要求,题目要求“ ”表示字符串的结束,但strlen是不是会计算空格后的字符数呢?这里可能有问题。请根据题目要求再帮我修改一下代码@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 23:20 | 显示全部楼层
赵珂夷 发表于 2025-11-20 23:17
FishC 发表于 2025-11-20 23:11
两个 insert 函数都 ...


两个 insert 函数都旨在将字符串 s2 插入到字符串 s1 的第 n 位(从0开始索引),但实现方式和正确性有显著区别。代码1(你写的)存在多个错误,无法正常工作;代码2(学长/姐的祖传代码)采用临时数组保存部分字符串的思路更可靠,但未提供完整代码。以下是详细分析:

代码1的主要错误:
- 长度计算错误:while 循环中未解引用指针(应使用 *s1 和 *s2 检查字符),且指针未移动,导致无限循环或错误计数。
- 字符移动逻辑错误:for 循环中的 s1=s1s1=s2 未实际移动或复制字符,只是重复赋值指针。
- 终止符处理错误:s1=' 's1='\0' 可能覆盖数据,且未正确设置字符串结束。

代码2的思路优势:
- 使用临时数组 s3 保存 s1 中第 n 位后的部分,避免直接覆盖。
- 先复制 s2 到 s1 的指定位置,再追加 s3,确保数据完整性。

功能区别:
代码1因逻辑错误无法实现插入,可能导致程序崩溃或错误输出;代码2通过临时存储正确实现插入,但需注意缓冲区大小。

根据题目要求,字符串以空格 ' ' 或空字符 '\0' 作为结束标志。以下是修正后的代码1,使用自定义长度计算和字符移动:


  1. #include <stdio.h>

  2. void insert(char *s1, char *s2, int n) {
  3.     int len1 = 0, len2 = 0;
  4.     char *p;

  5.     // 计算 s1 长度直到遇到 ' ' 或 '\0'
  6.     p = s1;
  7.     while (*p != ' ' && *p != '\0') {
  8.         len1++;
  9.         p++;
  10.     }

  11.     // 计算 s2 长度直到遇到 ' ' 或 '\0'
  12.     p = s2;
  13.     while (*p != ' ' && *p != '\0') {
  14.         len2++;
  15.         p++;
  16.     }

  17.     // 检查参数有效性
  18.     if (n < 0 || n > len1 || s1 == NULL || s2 == NULL) {
  19.         printf("error");
  20.         return;
  21.     }

  22.     // 移动 s1 中从位置 n 开始的字符(包括终止符)向后移动 len2 位
  23.     for (int i = len1; i >= n; i--) {
  24.         s1[i + len2] = s1[i];
  25.     }

  26.     // 复制 s2 的有效字符到 s1 的位置 n
  27.     for (int i = 0; i < len2; i++) {
  28.         s1[n + i] = s2[i];
  29.     }

  30.     // 设置字符串以 '\0' 结束
  31.     s1[len1 + len2] = '\0';
  32. }
复制代码


修正说明:
- 使用循环计算字符串长度,以 ' ' 或 '\0' 为结束标志。
- 移动字符时,从后向前遍历,避免覆盖。
- 插入后强制以 '\0' 终止,符合C语言标准。
- 假设 s1 有足够空间容纳插入后的字符串。

代码2的思路类似,但使用临时数组可能更易读,但需额外内存。建议优先使用修正后的代码1。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 23:58 | 显示全部楼层
赵珂夷 发表于 2025-11-20 23:57
解决方法:将第二个for循环里面的内容更改成
for(i=0 ...


根据你的反馈,我重新分析了代码1的问题,并采纳了你的修改建议。关键点在于:字符串以空格 ' ' 或空字符 '\0' 作为结束标志,因此不能直接使用 `strlen`(它会计算到 '\0' 为止,可能包含空格后的字符)。以下是修正后的代码1,主要更改包括:
- 使用循环计算字符串长度,以 ' ' 或 '\0' 为结束标志。
- 修正字符移动逻辑:从后向前移动 s1 的字符,避免覆盖。
- 将第二个 for 循环改为 `for(i=0; i < len2; i++)` 来正确复制 s2 的字符。

修正后的代码:


  1. #include <stdio.h>

  2. void insert(char *s1, char *s2, int n) {
  3.     int len1 = 0, len2 = 0;
  4.     int i;

  5.     // 计算 s1 长度,直到遇到 ' ' 或 '\0'
  6.     for (i = 0; s1[i] != ' ' && s1[i] != '\0'; i++) {
  7.         len1++;
  8.     }

  9.     // 计算 s2 长度,直到遇到 ' ' 或 '\0'
  10.     for (i = 0; s2[i] != ' ' && s2[i] != '\0'; i++) {
  11.         len2++;
  12.     }

  13.     // 检查参数有效性
  14.     if (n < 0 || n > len1 || s1 == NULL || s2 == NULL) {
  15.         printf("error");
  16.         return;
  17.     }

  18.     // 移动 s1 中从位置 n 开始的字符(包括终止符)向后移动 len2 位
  19.     for (i = len1; i >= n; i--) {
  20.         s1[i + len2] = s1[i];
  21.     }

  22.     // 复制 s2 的字符到 s1 的位置 n(使用 for(i=0; i < len2; i++))
  23.     for (i = 0; i < len2; i++) {
  24.         s1[n + i] = s2[i];
  25.     }

  26.     // 字符串以移动后的终止符(' ' 或 '\0')自然结束,无需额外设置
  27. }
复制代码


修改说明:
- 长度计算:通过循环遍历字符,直到遇到 ' ''\0',确保只计算有效部分。
- 字符移动:从后向前移动,避免覆盖未处理字符。
- 字符复制:使用 for(i=0; i < len2; i++) 正确索引 s2 的每个字符。
- 终止符处理:移动循环已包含原字符串的终止符,因此插入后字符串能正确结束。

这个版本解决了原代码1的错误,并符合题目要求。如果 s1 的缓冲区不足,可能导致溢出,使用时需确保空间足够。代码2的思路(使用临时数组)也更安全,但修正后的代码1更简洁。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-21 10:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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