从C中的字符串中删除子字符串

时间:2016-01-11 12:50:37

标签: c string loops

我已经有了从C中的字符串(word)中删除子字符串的代码,但我不明白。有人可以向我解释一下吗?它不使用标准库中的函数。我自己试图分析它,但某些部分我仍然不明白 - 我把它们放在评论中。我只需要弄清楚这一切是如何运作的。

谢谢!

#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++;    // ???
    }
}

4 个答案:

答案 0 :(得分:2)

这里函数的主要工作如下:

-Skip两个字符串之间的公共部分,并为第一个字符串分配新字符串。

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.
}

答案 1 :(得分:1)

第一个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]不为空,则i递增以检查来自s1的下一个位置的子分配。

答案 2 :(得分:1)

以下是评论中隐含的功能方法

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范围。

答案 3 :(得分:1)

让我们分解吧。

while (s1[i])
{
    // Code
}

这遍历s1。一旦到达字符串的末尾,就有\0,这是空终止符。在条件中进行评估时,它将评估为0。在这里使用for可能更好。

然后你有

for (j = 0; s2[j] && s2[j] == s1[i + j]; j++);

这只会增加j。应该注意的是,这个表达式没有大括号,并以分号结束,因此后面的代码不应该在循环体内执行。如果它确实有正确的大括号,它将循环遍历以下if/else,而s2不为空且s2[j] == s1[i+j]。除s2中的字符偏移i中的s1字符外,我对第二部分没有真正的解释。可能会改进此部分以删除不必要的迭代。

然后就是

if (!s2[j])
{
}
else
{
}

检查以确保s2中的位置有效并执行删除字符串(如果是),否则增加i。当else s2不再适合s1的其余部分时,可以通过返回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来压缩字符串。在循环结束时import java.io.*; public class Strbuff { public static void main(String arg[])throws IOException { BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); String str; try { System.out.println("Enter your name"); str=in.readLine(); str+="\nThis is example for string Buffer class and its function"; StringBuffer strbuf=new StringBuffer(); strbuf.append(str); System.out.println(strbuf); strbuf.delete(0,str.length()); strbuf.append("hello"); strbuf.insert(5,"-java"); System.out.println(strbuf); strbuf.reverse(); System.out.println("Reversed string"); System.out.println(strbuf); strbuf.reverse(); System.out.println(strbuf); strbuf.setCharAt(5,' '); System.out.println(strbuf); System.out.println("Character at 6th position"); System.out.println(strbuf.substring(3,7)); strbuf.deleteCharAt(3); System.out.println(strbuf); System.out.println("Capacity of the string Buffer object"); System.out.println(strbuf.capacity()); strbuf.delete(6,strbuf.length()); System.out.println("The string with first 6 letters"); System.out.println(strbuf); } catch(StringIndexOutOfBoundsException e) { System.out.println(e.getMessage()); } } } 结束空终止符中的字符串以正确结束。

如果你想要更深入的理解,可能值得尝试编写自己的代码来做同样的事情然后进行比较。我发现这通常比阅读大量测试更有帮助。