[英]Removing a substring from a string in C
我已经有从C中的字符串(单词)中删除子字符串的代码,但我不理解。 有人可以向我解释吗? 它不使用标准库中的函数。 我试图自己分析它,但是某些部分我还是不明白-我将它们放在注释中。 我只需要弄清楚这一切是如何工作的。
谢谢!
#include <stdio.h>
#include <stdlib.h>
void remove(char *s1, char *s2);
int main()
{
char s1[101], s2[101];
printf("First word: ");
scanf("%s", s1);
printf("Second word: ");
scanf("%s", s2);
remove(s1, s2);
printf("The first word after removing is '%s'.", s1);
return 0;
}
void remove(char *s1, char *s2)
{
int i = 0, j, k;
while (s1[i]) // ITERATES THROUGH THE FIRST STRING s1?
{
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++); // WHAT DOES THIS LINE DO?
if (!s2[j]) // IF WE'RE AT THE END OF STRING s2?
{
for (k = i; s1[k + j]; k++) //WHAT DOES THIS ENTIRE BLOCK DO?
s1[k] = s1[k + j];
s1[k] = 0;
}
else
i++; // ???
}
}
这里的功能主要工作是这样的:
-跳过两个字符串之间的公共部分,并为第一个字符串分配新的字符串。
while (s1[i]) // Yes It ITERATES THROUGH THE FIRST STRING s1
{
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++); // Here it skips the part which is
//similar in both
由于此循环仅增加公共部分的索引,因此将跳过s1中的数据存储。
if (!s2[j]) // IF WE'RE AT THE END OF STRING s2
{
for (k = i; s1[k + j]; k++) //Here it is re assigning the non common part.
s1[k] = s1[k + j];
s1[k] = 0;
}
else
i++; // it is req. if both have more values.
}
第一个while (s1[i])
遍历s1。 是的,你是对的。
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++);
上面的for循环从s1 [i]开始检查s1中是否存在子字符串s2。 如果匹配,则完全迭代s2。 如果不是,则在for循环的末尾,s2 [j]将不是空字符。 示例:如果s1 = ITERATE且s2 = RAT,则仅当i = 3时循环才会完全执行。
因此, if (!s2[j])
成立,则意味着我们找到了一个子字符串,而i是s1中子字符串的起点。
for (k = i; s1[k + j]; k++) //WHAT DOES THIS ENTIRE BLOCK DO?
s1[k] = s1[k + j];
s1[k] = 0;
abov块删除子字符串。 因此,对于ITERATE和RAT示例,这是通过在存在R和A的位置复制E和null char来完成的。 for循环可实现此目的。 如果for循环后s2 [j]不为null,则i递增以检查是否从s1的下一个位置开始。
这是注释中浓缩的功能的一种方法
void remove(char *s1, char *s2)
{
int i = 0, j, k;
while (s1[i]) // Iterates through s1 (until it finds a zero)
{
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++); // Iterates through s2 while both it is NOT the end of the string s2 and each character of s2 coincides with s1 (if s2 == s1, j points to the end of s2 => zero)
if (!s2[j]) // If j point to the end of s2 => We've found the coincidence
{
for (k = i; s1[k + j]; k++) //Remove the coincident substring
s1[k] = s1[k + j];
s1[k] = 0;
}
else
i++; // There is no coincidence so we continue to the next character of s1
}
}
注意:我还注意到,由于它迭代到s1范围之外,因此很容易解释。
让我们分解一下。 你有
while (s1[i])
{
// Code
}
这遍历s1
。 到达字符串的末尾后,您就有\\0
,这是空终止符。 在条件中求值时,它将求值为0
。 这可能是更好的使用for
这里。
然后你有
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++);
这除了增加j
什么都没有。 应当注意,该表达式没有花括号,并且以分号结尾,因此不应在循环体内执行之后的代码。 如果确实具有正确的括号,则它将在以下if/else
循环,而s2
不为null且s2[j] == s1[i+j]
。 除了s2
的字符被s1
i
偏移之外, i
对第二部分实际上没有任何解释。 该部分可能会得到改进,以消除不必要的迭代。
然后有
if (!s2[j])
{
}
else
{
}
这将检查以确保s2
的位置有效,并执行删除字符串的操作,否则将i
递增。 当s2
不再适合s1
的其余部分时,可以通过返回else
来改善它。
for (k = i; s1[k + j]; k++)
s1[k] = s1[k + j];
s1[k] = 0;
这是另一个有点奇怪的循环,因为由于没有花括号,因此将在循环外部设置s1[k] = 0
。 这里发生的是,通过删除s2
并将k+j
处的字符向下移动到k
来压缩字符串。 在循环的末尾, s1[k] = 0
结束以正确结束的空终止符中的字符串。
如果您想更深入地了解,可能值得尝试编写自己的代码来做相同的事情,然后再进行比较。 我发现,这通常比阅读大量测试更有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.