C语言中调整数组指定单元大小的代码实现问题求助
问题分析与修复方案
咱们一步步拆解你代码里的问题,然后修复它,实现你想要的子串截取功能:
1. 核心问题梳理
你的代码目前存在几个关键缺陷,直接导致无法正常工作:
- 缺失
<string.h>头文件:strlen()、strcpy()等字符串操作函数需要这个头文件,缺失会引发编译器隐式声明,导致未定义行为 - 使用废弃的
gets()函数:完全不检查输入长度,极易造成缓冲区溢出,属于高危函数 - 变量
b未初始化就使用:main()里没有读取b的输入,程序会用随机值,逻辑完全混乱 - 没有子串复制逻辑:
realloc()只是调整内存大小,没有把原字符串中指定范围的字符复制到新内存里 - 忽略字符串结束符:C语言字符串必须以
'\0'结尾,你的代码没处理这个关键点 - 索引逻辑不明确:你的例子中
a=2、b=4对应输出ell,说明你是按1起始索引计数的,需要转换为C语言的0起始索引来处理
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 新增:字符串操作必须的头文件 char *readline() { char s[256]; char *ds; printf("Give string: "); // 用安全的fgets替代gets,同时处理换行符 fgets(s, sizeof(s), stdin); size_t len = strlen(s); // 去掉fgets读取到的换行符(如果存在) if (len > 0 && s[len-1] == '\n') { s[len-1] = '\0'; len--; } // 分配内存并检查是否成功 ds = (char *)calloc(len + 1, sizeof(char)); if (ds == NULL) { perror("Failed to allocate memory"); exit(EXIT_FAILURE); } strcpy(ds, s); return ds; } int main() { // 规范main函数的返回类型 char *s1, *s2; int a, b; s1 = readline(); printf("Start: "); scanf("%d", &a); printf("End: "); scanf("%d", &b); // 新增:读取b的输入值 // 校验输入合法性,避免越界访问 size_t str_len = strlen(s1); if (a < 1 || b > str_len || a > b) { printf("Invalid start/end values! Please enter 1<=start<=end<=string length.\n"); free(s1); exit(EXIT_FAILURE); } // 转换为0起始索引,计算子串长度(包含结束符) int start_idx = a - 1; int sub_len = b - a + 1; // 分配子串内存并检查 s2 = (char *)malloc(sub_len + 1); if (s2 == NULL) { perror("Failed to allocate memory"); free(s1); exit(EXIT_FAILURE); } // 复制指定范围的子串,并手动添加结束符 strncpy(s2, s1 + start_idx, sub_len); s2[sub_len] = '\0'; // strncpy不会自动添加结束符,必须手动处理 puts(s2); // 释放动态分配的内存,避免内存泄漏 free(s1); free(s2); return 0; }
关键修复说明
- 安全输入处理:用
fgets()替代gets(),同时处理了换行符问题,确保输入的字符串干净有效 - 内存安全检查:每次动态分配内存后都检查是否成功,避免空指针访问崩溃
- 输入合法性校验:防止用户输入的起始/结束位置超出字符串范围,避免越界访问
- 正确的子串逻辑:将1起始索引转换为C语言的0起始索引,用
strncpy()复制指定范围的字符,手动添加结束符保证字符串有效 - 内存泄漏防护:不再使用的动态内存及时释放,养成良好的内存管理习惯
测试你的例子:输入字符串Hello,a=2,b=4,程序会输出ell,完全符合你的需求。
内容的提问来源于stack exchange,提问作者codeboi
相关产品推荐
相关产品推荐

