我需要从没有任何库的字符串中删除指定数量的字符。
此函数应采用三个参数:字符串、起始索引号和要删除的字符数。
而且我还没有学会指针,所以我不能使用它们。
我已经编写了这段代码,它适用于我的单个测试用例。是否有任何我遗漏的错误、改进或解决问题的更好方法?
#include <stdio.h>
void removeString(char string[], int index, int number)
{
int i, j;
index--;
for (i = index, j = index + number; string[j] != '\0'; i++, j++)
{
string[i] = string[j];
}
string[i] = '\0';
}
int main(void)
{
char string[] = "this";
removeString(string, 2, 2);
printf("%s\n", string);
}
stdio
是标准输入/输出的缩写。如果您不进行输入或输出,则说明您没有使用此库。
我能看到使用 stdio 来做这件事的唯一方法是控制你输出的内容,也就是说,如果它们不应该被删除,一次打印一个字符。这根本不会改变字符串。
相反,如果你只需要实现你的 removeString
不使用任何其他库(不一定使用 stdio)的方法,让我们从查看现有代码开始:
void removeString(char string[], int index, int number)
{
int i, j;
index--;
for (i = index, ...)
如果 index==0
会发生什么?看起来这应该是一个有效的输入,但你从 i=-1
开始.嗯,可能没问题,只要我们不在索引中使用它
string[i] = ...
哦,亲爱的,我们只是在数组开始之前写的。我们需要对此更加小心。
怎么样j
?
for(..., j = index + number; string[j] != '\0'; i++, j++)
{
string[i] = string[j];
嗯,这很糟糕,如果 index+number
大于我们字符串的长度 - 我们开始读取数组末尾。
安全版本可能如下所示:
void removeString(char string[], int index, int number)
{
int i, j;
/* make sure inputs are sane */
if (index < 0) index = 0;
if (number < 1) number = 1;
/* make sure index < strlen(string) without using strlen */
for (i = 0; i<index; i++) {
if (string[i] == '\0') return;
}
/* advance j, stopping if we hit the end */
for (j = i+1; j < i+number && string[j]; j++) {}
/* now copy from i to j, stopping at the end */
do {
string[i++] = string[j];
} while (string[j++]);
}
具有以下不变量:
-
index
不允许小于零
-
number
不允许小于一(索引可以设为零吗?)
- 如果
index
大于字符串的总长度,没有改变
- 如果
index+number
大于字符串的总长度,我们在 index
处截断字符串
考虑结构的一种有用方法是,我们的函数将字符串分为三部分,并且我们为每一部分都有一个循环:
- 在删除部分(
0 <= i <= index
)之前是第一个循环
- 在删除的部分 (
index < j < index+number
) 中是第二个
- 在删除的部分 (
index <= i && index+number <= j <= end
) 之后是第三个
由于您是初学者,因此值得注意的是所有这三个循环都经过了仔细的编写。也就是说,要注意使它们正确,并且使用更规则的形式可能更容易(并且可能是更好的风格)。特别是 do/while
循环有两个后增量表达式,它们必须位于正确的位置,这有点脆弱。