2

我正在学习如何使用 k&r 书(C 编程语言)用 C 语言编写程序,但其中一个练习有问题。它要求我检测并删除字符串 s1 中的一个字符,该字符与字符串 s2 中的任何字符匹配。

所以,说 s1 = "A";

和 s2 = "AABAACAADAAE"

我希望它返回“BCDE”

我知道我走在正确的道路上,我只是不知道如何很好地设计程序,你能否给我任何额外的提示。我试图阅读二叉搜索树算法,但觉得它对于这个平凡的任务来说有点太高级了。

感谢大家!

/* An alternate version of squeeze(s1, s2) that deletes each character in
 * s1 that matches any character in the string s2
 *
 * Angie@odfx.org
 */

#include <stdio.h>
#include <string.h>

void squeeze(char s[], char t[]);

char string[] = "BAD";
char sstring[] = "ABC";

int
main(void)
{
    squeeze(string, sstring);
    return 0;
}

void
squeeze(char s[], char t[])
{
    int i, j, d;

    d = 0;
    if(strstr(s, t) == NULL)
        printf("%c", s[i]);
    s[j] = '\0';
}
4

6 回答 6

3

很棒的书。如果我是你,我会完全按照第 2.8 节中的squeeze() 进行操作,但不是直接比较 (s[i] != c) 我会编写并利用一个函数

 int contains(char s[], int c)

如果字符串 s 包含 c,则返回 1,否则返回 0。从简单的方法开始;当它起作用时,您可以使用更复杂的解决方案来提高性能(二进制搜索,但请注意,该问题不需要 s2 中的字符按特定顺序排列)。

于 2009-01-07T02:08:29.323 回答
2

二进制搜索对此太过分了。你需要三个索引。一个索引 ( i) 用于遍历s,一个索引 ( k) 用于遍历t,一个索引 ( j) 用于跟踪您所在的位置,以s查找您需要保留的字符,因为它们不在其中t。因此,对于 中的每个字符s,检查它是否在 中t。如果不是,请将其保留在s.

void squeeze(char *s, char *t) {
    int i, j, k;
    int found = 0;

    for(i = j = 0; s[i] != '\0'; i++) {
        found = 0;
        for(k = 0; t[k] != '\0' && (found == 0); k++) {
            if(t[k] == s[i]) {
                found = 1;
            }
        }

        if(found == 0) {
            s[j++] = s[i];
        }

    }

    s[j] = '\0';
}
于 2009-01-07T02:11:36.430 回答
0

您不需要花哨的二进制搜索来完成这项工作。您需要的是一个双 for 循环,它检查一个字符串中每个字符在另一个字符串中的出现,并将未出现的字符复制到第三个字符数组中(这是您的结果)。

代码可能类似于以下内容(未经测试!):

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
   for (j = 0; j < len2; j++) {
     if (s1[i] == s2[j]) {
       break;
     }
   }
   if (j == len2) {  /* s1[i] is not found in s2 */
     *result = s1[i]; 
     result++; /* assuming your result array is long enough */
   }
}
于 2009-01-07T02:00:05.500 回答
0
void squeeze(char s1[], char s2[])
{
    int i,j,k;
    char c;
    for(i=0;s2[i]!='\0';i++)
    {
        c=s2[i];
        for(j=k=0;s1[j]!='\0';j++)
            if(s1[j]!=c)
                s1[k++]=s1[j];
            s1[k]='\0';
    }
}
于 2013-11-27T20:25:56.080 回答
0

这是我非常清晰和简单的答案,并附有一些合乎逻辑的解释。

#include<stdio.h>
void squeeze();

在 main 我们输入我们测试过的字符串和wantbedelete字符串,其中包含我们要从yourstring中删除的字符。

int main() 
{

    char yourstring[] = "AABAACAADAAE";
    char wantbedelete[] = "A";

    squeeze(yourstring, wantbedelete);
    printf("%s", yourstring);

    return 0;
}

挤压函数内部的逻辑如下,

  • 循环在wantbedelete char by char
  • 然后,对于在wantbedelete中找到的任何字符,我们会遍历整个yourstring
  • 然后,我们比较两个创建的 char 是否不匹配,我们将 char 从yourstring更新(保存)到yourstring所以基本上在这里我们定义一个新的索引(k)来跟踪和更新唯一想要的字符
  • 现在这里的技巧是,每次我们再次返回到循环遍历我们打算删除的每个字符的外部循环时,我们都希望重置索引,以便我们最终得到唯一想要的字符串。

我强烈建议您使用调试器并遵循挤压函数中的每一行,以便您能够更清楚地理解逻辑。

void squeeze(char s1[], char s2[]) 
{
    int i, j, k;

    k = 0;
    for (i = 0 ; s2[i] != '\0' ; i++) /* loop for each char we want to delete with index i */
    {
        for (j = 0 ; s1[j] != '\0'; j++) /* loop for each char we want to keep with index j */
        {
            if (s2[i] != s1[j]) /* if the two chars do not match */
            {
                s1[k++] = s1[j]; /* update s1 with the char that we want to keep using index k */
            }
        }
        s1[k] = '\0'; /* since we update all char that we want to keep, the last char of index k must be empty */
        k = 0; /* reset index k so we will be ready for the next char that we want to delete from s1 */
    }
}
于 2022-02-14T00:13:29.350 回答
-1

这是我的功能:

void squeeze(char s1[],char s2[])
{
int i,j,p;
int found;

p=0;
for(i=0;s1[i]!='\0';i++)
{
    for(j=0;s2[j]!='\0';j++)
        if(s1[i]==s2[j])
            found=YES;
        else
            found=NO;
    if(found==NO)
        s1[p++]=s1[i];
     }
    s1[p]='\0';
}
于 2014-06-16T08:22:45.280 回答