C 字符串字符处理:如何将后处理循环组合到主循环中?

C 字符串字符处理:如何将后处理循环组合到主循环中?,c,string,loops,C,String,Loops,以下是我试图解决的问题,但无法找到更简单的方法:- 编写一个函数squez,删除s1中与字符串s2中任何字符匹配的每个字符 到目前为止,我所做的是以下代码:- #include<stdio.h> #include<string.h> char *mysqueeze(char *a, char *b); int main(void) { int j = 0; char s1[100] = "krishna"; char s2[100] = "kare

以下是我试图解决的问题,但无法找到更简单的方法:-

编写一个函数squez,删除s1中与字符串s2中任何字符匹配的每个字符

到目前为止,我所做的是以下代码:-

#include<stdio.h>
#include<string.h>
char *mysqueeze(char *a, char *b);
int main(void)
{
    int j = 0;
    char s1[100] = "krishna";
    char s2[100] = "kareem";
    char real[100];
    char *t = mysqueeze(s1,s2);
    for (int i = 0; i <= strlen(t); i++)  //1
        if (t[i] != '*')
    real[j++] = t[i];
    real[j] = '\0';        //4

    printf("%s\n", real);
}

char *mysqueeze(char *a, char *b)
{
    int i = 0, k;
    do
    {
        k = 0;
        while (b[k] != '\0')
        {
            if (a[i] == b[k]) {
                a[i] = '*';
                break;
            }
            k++;
        }
        i++;
    }
    while (a[i]);
    return a;
}
#包括
#包括
char*mysqueze(char*a,char*b);
内部主(空)
{
int j=0;
char s1[100]=“奎师那”;
字符s2[100]=“kareem”;
char real[100];
char*t=mysqueze(s1,s2);

对于(int i=0;i要真正回答您的问题,将1到4移动到函数中最明显的方法是将
real
作为第三个参数传递。但是,将
a
中的字符替换为
“*”
然后复制其他字符是不必要的步骤。类似这样的方法更好:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

void mysqueeze(const char * first, const char * second, char * result);

int main(void) {
    char first[] = "krishna";
    char second[] = "kareem";
    char result[100];

    mysqueeze(first, second, result);

    printf("Result: %s\n", result);

    return EXIT_SUCCESS;
}

void mysqueeze(const char * first, const char * second, char * result) {
    while ( *first ) {
        const char * t_second = second;
        bool found = false;
        while ( *t_second ) {
            if ( *first == *t_second++ ) {
                found = true;
                break;
            }
        }
        if ( !found ) {
            *result++ = *first;
        }
        ++first;
    }

    *result = '\0';
}
#包括
#包括
#包括
void mysqueze(常量字符*第一,常量字符*第二,字符*结果);
内部主(空){
char first[]=“克里希纳”;
字符秒[]=“kareem”;
字符结果[100];
迷惑(第一,第二,结果);
printf(“结果:%s\n”,结果);
返回退出成功;
}
void mysqueze(常量字符*第一,常量字符*第二,字符*结果){
while(*第一){
常量字符*t_秒=秒;
bool-found=false;
而(*t_秒){
如果(*first==*t_second++){
发现=真;
打破
}
}
如果(!找到){
*结果+=*第一;
}
++第一,;
}
*结果='\0';
}
有更省时的方法来实现此算法,例如,对第二个字符串进行一次遍历,并在数组中为存在的每个字符设置一个标志,因此可以在单个恒定时间查找中完成与第一个字符串的每次比较


编辑:添加变量
t\u second
以回应phonetagger的评论。

要真正回答您的问题,将1到4移动到函数中最明显的方法是将
real
作为第三个参数。但是,将
a
中的字符替换为
'*'
然后复制其他字符是不必要的第一步。像这样更好:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

void mysqueeze(const char * first, const char * second, char * result);

int main(void) {
    char first[] = "krishna";
    char second[] = "kareem";
    char result[100];

    mysqueeze(first, second, result);

    printf("Result: %s\n", result);

    return EXIT_SUCCESS;
}

void mysqueeze(const char * first, const char * second, char * result) {
    while ( *first ) {
        const char * t_second = second;
        bool found = false;
        while ( *t_second ) {
            if ( *first == *t_second++ ) {
                found = true;
                break;
            }
        }
        if ( !found ) {
            *result++ = *first;
        }
        ++first;
    }

    *result = '\0';
}
#包括
#包括
#包括
void mysqueze(常量字符*第一,常量字符*第二,字符*结果);
内部主(空){
char first[]=“克里希纳”;
字符秒[]=“kareem”;
字符结果[100];
迷惑(第一,第二,结果);
printf(“结果:%s\n”,结果);
返回退出成功;
}
void mysqueze(常量字符*第一,常量字符*第二,字符*结果){
while(*第一){
常量字符*t_秒=秒;
bool-found=false;
而(*t_秒){
如果(*first==*t_second++){
发现=真;
打破
}
}
如果(!找到){
*结果+=*第一;
}
++第一,;
}
*结果='\0';
}
有更省时的方法来实现此算法,例如,对第二个字符串进行一次遍历,并在数组中为存在的每个字符设置一个标志,因此可以在单个恒定时间查找中完成与第一个字符串的每次比较


编辑:添加变量
t\u second
以回应phonetagger的评论。

我希望这不是在回答家庭作业问题,但即使是这样,我想既然你已经有了一个可行的解决方案,我也不会在技术上为他们做任何家庭作业

我下面的两个解决方案都实现了就地折叠算法,如果适用于问题,这肯定是最有效的方法。如果问题需要折叠到另一个缓冲区解决方案中,所需的修改将是最小的。正如Paul Griffiths在其解决方案中提到的,最有效的解决方案(对于大型干草堆)涉及到预计算针形布尔的查找表
如下。请注意,如果重复使用同一组指针,最好将函数拆分为两个单独的函数,一个用于初始化指针数组,然后
mysqueze
实现将使用指向指针数组查找表的指针,而不是指向字符串的指针

在实现任何解决方案时,都需要验证它是否正确处理重复的针形字符。为了测试这一点,我将haystack字符串扩展为四个相同字母的序列。原始帖子的解决方案正确处理了这种情况。我的两个解决方案也正确处理了这种情况

可能需要注意的是,虽然
mysqueze3()
mysqueze2()
更有效,但前者不是通用解决方案,而后者是。查找表解决方案取决于
char
大小为8位(或更小);即,最多有256个指针值。如果系统上的
char
为9位或更大,则需要相应地修改该解决方案。如果系统上的
char
为16位或更大(可能是unicode!),则查找表解决方案将变得不切实际

#include<stdio.h>
#include<string.h>
typedef enum {false=0, true=1} bool;
char *mysqueeze(char *a, char *b);
char *mysqueeze2(char *haystack, const char *needles);
char *mysqueeze3(char *haystack, const char *needles);
void mysqueeze_griffiths(const char * first, const char * second, char * result);

int main(void)
{
    int j = 0;
    char s1[100] = "kkkkrrrriiiisssshhhhnnnnaaaa";
    char s2[100] = "kareem";
    char real[100];
    char *t = mysqueeze(s1,s2);
    for (int i = 0; i <= strlen(t); i++)  //1
        if (t[i] != '*')
           real[j++] = t[i];
    real[j] = '\0';        //4

    printf("mysqueeze:           %s\n", real);

    char s3[100] = "kkkkrrrriiiisssshhhhnnnnaaaa";
    char s4[100] = "kareem";
    printf("mysqueeze2:          %s\n", mysqueeze2(s3,s4));

    char s5[100] = "kkkkrrrriiiisssshhhhnnnnaaaa";
    char s6[100] = "kareem";
    printf("mysqueeze3:          %s\n", mysqueeze3(s5,s6));

    char s7[100] = "kkkkrrrriiiisssshhhhnnnnaaaa";
    char s8[100] = "kareem";
    char result[100];
    mysqueeze_griffiths(s7,s8, result);
    printf("mysqueeze_griffiths: %s\n", result);

}

char *mysqueeze(char *a, char *b)
{
    int i = 0, k;
    do
    {
        k = 0;
        while (b[k] != '\0')
        {
            if (a[i] == b[k]) {
                a[i] = '*';
                break;
            }
            k++;
        }
        i++;
    }
    while (a[i]);
    return a;
}

void mysqueeze_griffiths(const char * first, const char * second, char * result) {
    while ( *first ) {
        bool found = false;
        while ( *second ) {
            if ( *first == *second++ ) {
                found = true;
                break;
            }
        }
        if ( !found ) {
            *result++ = *first;
        }
        ++first;
    }

    *result = '\0';
}

char *mysqueeze2(char *haystack, const char *needles)
{
    char *dest=haystack, *src=haystack;
    while (*src)
    {
        const char* n;
        for (n=needles; *n; ++n)
        {
            if (*n==*src)
            {
                ++src;
                break;
            }
        }
        if (!*n)
           *dest++ = *src++;
    }
    *dest = '\0';
    return haystack;
}

char *mysqueeze3(char *haystack, const char *needles)
{
    char *dest=haystack, *src=haystack;
    bool needleArray[256];
    memset(needleArray,0,sizeof(needleArray));
    for (const char* n=needles; *n; ++n)
        needleArray[(unsigned char)*n] = true;
    while (*src)
    {
        if (needleArray[(unsigned char)*src])
            ++src;
        else
           *dest++ = *src++;
    }
    *dest = '\0';
    return haystack;
}
#包括
#包括
typedef枚举{false=0,true=1}bool;
char*mysqueze(char*a,char*b);
char*mysqueze2(char*haystack,const char*needers);
char*mysqueze3(char*haystack,const char*needers);
void mysqueze_griffiths(常量字符*第一,常量字符*第二,字符*结果);
内部主(空)
{
int j=0;
字符s1[100]=“KKKKRRRIIIISSSHHHNNNAAA”;
字符s2[100]=“kareem”;
char real[100];
char*t=mysqueze(s1,s2);

对于(int i=0;i我希望这不是在回答家庭作业问题,但即使是这样,我想既然你已经有了一个有效的解决方案,我也不会严格地为他们做任何家庭作业

我下面的两个解决方案都实现了就地折叠算法,即