在C中从字符串中删除子字符串
我已经有了在C中从字符串(单词)中删除子字符串的代码,但我不理解它。有人能给我解释一下吗?它不使用标准库中的函数。我试着自己分析,但某些部分我仍然不明白——我把它们放在了评论中。我只是想弄清楚这一切是怎么回事 谢谢在C中从字符串中删除子字符串,c,string,loops,C,String,Loops,我已经有了在C中从字符串(单词)中删除子字符串的代码,但我不理解它。有人能给我解释一下吗?它不使用标准库中的函数。我试着自己分析,但某些部分我仍然不明白——我把它们放在了评论中。我只是想弄清楚这一切是怎么回事 谢谢 #include <stdio.h> #include <stdlib.h> void remove(char *s1, char *s2); int main() { char s1[101], s2[101]; printf("First w
#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++; // ???
}
}
#包括
#包括
无效删除(字符*s1,字符*s2);
int main()
{
字符s1[101],s2[101];
printf(“第一个单词:”);
scanf(“%s”,s1);
printf(“第二个词:”);
scanf(“%s”,s2);
移除(s1,s2);
printf(“删除后的第一个单词是“%s.”,s1);
返回0;
}
无效删除(字符*s1,字符*s2)
{
int i=0,j,k;
while(s1[i])//遍历第一个字符串s1?
{
for(j=0;s2[j]&&s2[j]==s1[i+j];j++);//这行是做什么的?
if(!s2[j])//如果我们在字符串s2的末尾?
{
for(k=i;s1[k+j];k++)//整个块做什么?
s1[k]=s1[k+j];
s1[k]=0;
}
其他的
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]) // 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循环检查子串s2是否存在于从s1[i]开始的s1中。如果匹配,s2将完全迭代。如果不是,则在for循环的末尾,s2[j]将不是空字符。示例:如果s1=ITERATE,s2=RAT,则循环将仅在i=3时完全执行所以
如果(!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字符来完成的。for循环实现了这一点。如果for循环后s2[j]不为null,则i将递增,以检查是否从s1的下一个位置进行了替换。第一个,而(s1[i])
将迭代s1。是的,你说得对
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++);
上述for循环检查子串s2是否存在于从s1[i]开始的s1中。如果匹配,s2将完全迭代。如果不是,则在for循环的末尾,s2[j]将不是空字符。示例:如果s1=ITERATE,s2=RAT,则循环将仅在i=3时完全执行所以
如果(!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字符来完成的。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范围之外迭代。这里是一种在注释中浓缩的功能方法
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 (j = 0; s2[j] && s2[j] == s1[i + j]; j++);
这只会增加j
。应该注意的是,这个表达式没有大括号,并且以分号结尾,因此后面的代码不应该在循环体中执行。如果括号正确,它将在以下If/else
上循环,而s2
不为空且s2[j]==s1[i+j]
。除了s2
中的字符被s1
中的金额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
在空终止符中结束要正确结束的字符串
如果您想要更深入的理解,那么尝试编写自己的代码来做同样的事情,然后进行比较可能是值得的。我发现这通常比阅读一系列测试更有帮助。让我们把它分解一下。你有
while (s1[i])
{
// Code
}
这将迭代通过s1
。一旦到达字符串的末尾,就有了\0
,它是空终止符。在条件下进行计算时,它将计算为0
。在这里使用可能更好
那么你有
for (j = 0; s2[j] && s2[j] == s1[i + j]; j++);
这只会增加j
。应该注意的是,这个表达式没有大括号,并且以一个分号结尾