我不能为从字母S中删除N个字符的函数编写一个可行的代码,从位置P开始。你们会怎么写这样的函数?
void remove_substring(char *s, int p, int n) {
int i;
if(n == 0) {
printf("%s", s);
}
for (i = 0; i < p - 1; i++) {
printf("%c", s[i]);
}
for (i = strlen(s) - n; i < strlen(s); i++) {
printf("%c", s[i]);
}
}
示例:
s: "abcdefghi"
p: 4
n: 3
输出:
abcghi
但对于像n = 0和p = 1这样的情况,它不起作用! 非常感谢!
答案 0 :(得分:4)
有些人向您展示了如何做到这一点,但他们的大多数解决方案都是高度浓缩的,使用标准库函数或者根本不解释正在发生的事情。这是一个版本,不仅包括一些非常基本的错误检查,还包括对正在发生的事情的一些解释:
void remove_substr(char *s, size_t p, size_t n)
{
// p is 1-indexed for some reason... adjust it.
p--;
// ensure that we're not being asked to access
// memory past the current end of the string.
// Note that if p is already past the end of
// string then p + n will, necessarily, also be
// past the end of the string so this one check
// is sufficient.
if(p + n >= strlen(s))
return;
// Offset n to account for the data we will be
// skipping.
n += p;
// We copy one character at a time until we
// find the end-of-string character
while(s[n] != 0)
s[p++] = s[n++];
// And make sure our string is properly terminated.
s[p] = 0;
}
需要注意的一点需要注意:请不要将此功能称为:
remove_substr("abcdefghi", 4, 3);
或者像这样:
char *s = "abcdefghi";
remove_substr(s, 4, 3);
这样做会导致未定义的行为,因为字符串文字是只读的,标准不允许修改它们。
答案 1 :(得分:3)
严格来说,您没有实现删除子字符串:您的代码会打印原始字符串并删除一系列字符。
另外需要注意的是,根据您的示例,索引p
是基于1的,而不是基于零的,因为它在C中。否则"abcdefghi", 4, 3
的输出将是{{ 1}},而不是"abcdhi"
。
考虑到这一点,让我们做一些改变。首先,你的数学有点偏差:最后一个循环应如下所示:
"abcghi"
如果您想使用C的从零开始的索引方案,请按如下方式更改循环:
for (i = p+n-1; i < strlen(s); i++) {
printf("%c", s[i]);
}
此外,您应该从顶部的for (i = 0; i < p; i++) {
printf("%c", s[i]);
}
for (i = p+n; i < strlen(s); i++) {
printf("%c", s[i]);
}
返回,或添加if
:
else
或
if(n == 0) {
printf("%s", s);
return;
}
或完全删除if(n == 0) {
printf("%s", s);
} else {
// The rest of your code here
...
}
:它只是一种优化,没有它你的代码也能正常工作。
目前,当if
为n
时,您的代码会打印两次原始字符串。
如果您想让代码删除子字符串并返回结果,则需要分配结果,并将打印替换为复制,如下所示:
0
请注意,此新版本的代码会返回动态分配的内存,使用后需要char *remove_substring(char *s, int p, int n) {
// You need to do some checking before calling malloc
if (n == 0) return s;
size_t len = strlen(s);
if (n < 0 || p < 0 || p+n > len) return NULL;
size_t rlen = len-n+1;
char *res = malloc(rlen);
if (res == NULL) return NULL;
char *pt = res;
// Now let's use the two familiar loops,
// except printf("%c"...) will be replaced with *p++ = ...
for (int i = 0; i < p; i++) {
*pt++ = s[i];
}
for (int i = p+n; i < strlen(s); i++) {
*pt++ = s[i];
}
*pt='\0';
return res;
}
d。
答案 2 :(得分:2)
尝试复制字符串的第一部分,然后复制第二部分
char result[10];
const char input[] = "abcdefg";
int n = 3;
int p = 4;
strncpy(result, input, p);
strncpy(result+p, input+p+n, length(input)-p-n);
printf("%s", result);
答案 3 :(得分:2)
如果您希望在不使用strcpy
或strncpy
等功能的情况下执行此操作(我在评论中看到您这样做),请使用类似的方法strcpy
(或者至少有一种可能的变体)在引擎盖下工作:
void strnewcpy(char *dest, char *origin, int n, int p) {
while(p-- && *dest++ = *origin++)
;
origin += n;
while(*dest++ = *origin++)
;
}
答案 4 :(得分:1)
你尝试了什么? strcpy(s+p, s+p+n)
不起作用吗?
编辑:已修复以不依赖strcpy
中的未定义行为:
void remove_substring(char *s, int p, int n)
{
p--; // 1 indexed - why?
memmove(s+p, s+p+n, strlen(s) - n);
}
如果您的心脏确实设置了它,您还可以用循环替换memmove
来电:
char *dst = s + p;
char *src = s + p + n;
for (int i = 0; i < strlen(s) - n; i++)
*dst++ = *src++;
如果你这样做,你也可以删除strlen
电话:
while ((*dst++ = *src++) != '\0);
但我不确定我是否建议将其压缩得那么多。
答案 5 :(得分:1)
元代码: