Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 置换字符串未按预期工作_C - Fatal编程技术网

C 置换字符串未按预期工作

C 置换字符串未按预期工作,c,C,我正在尝试创建一个函数,它可以排列一个单词的所有可能组合,程序会创建重复的排列字符串,我不知道为什么 这是我的工作代码: #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> char arr[5000] = {0}; void swap (char *x, char *y); void permute(char *ptr, size_t i, size_

我正在尝试创建一个函数,它可以排列一个单词的所有可能组合,程序会创建重复的排列字符串,我不知道为什么

这是我的工作代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char arr[5000] = {0};
void swap (char *x, char *y);
void permute(char *ptr, size_t i, size_t n);

int main(void){
    char str[80] = "MICHI";
    size_t len = strlen(str);

    permute(str, 0, len );
    printf("%s\n", arr);
    printf("END\n");
}

void swap (char *x, char *y){
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

void permute(char *ptr, size_t i, size_t n){
    size_t j;
    if (i == n){
        strcat (arr, ptr);
        strcat (arr, "\n");
    }else{
        for (j = i; j <= n; j++)
        {

            swap( (ptr + i), (ptr + j) );
            permute(ptr, i+1, n);
            swap( (ptr + i), (ptr + j) );
        }
    }
}
预期产出应为:

ABC
AB
ACB
AC
A
BAC
BA
BCA
BC
B
CBA
CB
CAB
CA
c
该程序创建了大量的重复项,同时也创建了大量的新行

注意,如果输入是例如
MICHI
,我会得到如下重复:

IMCHI
IMCH
IMCIH
IMCI

函数permute中的循环包括字符串的NUL字节。您只需更改
j您在排列中包含字符串终止符
\0

行的内部状态为:

ABC\0
AB\0C
ACB\0
AC\0B
A\0CB
A\0BC
BAC\0
BA\0C
BCA\0
BC\0A
B\0AC
B\0CA
CBA\0
CB\0A
CAB\0
CA\0B
C\0AB
C\0BA
\0ABC
\0ACB
\0BAC
\0BCA
\0CAB
\0CBA
printf
仅打印到结尾
0

解决此问题的一种方法是将循环限制减少1,并从排列中排除
\0
。然后必须添加第二个循环,该循环创建一个子字符串,该子字符串不包含
i
th字符,并为该子字符串调用
permute

另一种方法是在分支超出
\0
后停止置换

编辑:

这里是第二个建议的一个实现,即如果一个排列与前一个相同,则通过抑制输出来“停止排列”。它甚至似乎产生了您在示例中指定的顺序:

void permute(char *ptr, size_t i, size_t n){
    size_t j;
    static char prev[80] = "";
    if (i == n){
        if (strcmp(prev, ptr)) {
            strcat (arr, ptr);
            strcat (arr, "\n");
            strcpy(prev, ptr);
        }
    }else{
        for (j = i; j <= n; j++)
        {

            swap( (ptr + i), (ptr + j) );
            permute(ptr, i+1, n);
            swap( (ptr + i), (ptr + j) );
        }
    }
}
void排列(字符*ptr,大小i,大小n){
尺寸j;
静态字符prev[80]=“”;
如果(i==n){
if(strcmp(上一个ptr)){
strcat(arr、ptr);
strcat(arr,“\n”);
strcpy(prev,ptr);
}
}否则{

对于(j=i;j)您可能想阅读以下内容:顺序重要吗?如果您的输入包含重复的字符,如MICHI中的两个
i
,则应该有重复的排列。当您排列时,两个
i
s被视为不同的实体。或者您只是想要组合(即唯一排列)?@Klaslind bäck抱歉,我的回答太晚了,不,我不需要唯一的排列,因为就像你说的,它可能是不同的实体,你是对的。好的开始。这将打印所有长度
n
的排列。那么较短的子字符串的排列呢?你的代码更改了我想要的输出。请检查我的预期输出问题。请在发布前运行您的代码。这不起作用。@klutt我确实运行过,并且它在我的电脑中起作用(但不是为了期望的输出)我运行了它,只得到了长度为3的字符串。是的,但我需要我的问题的预期输出。@Michi这一个似乎有效。请注意,如果任何字符出现多次,它将打印重复的字符。这就是我需要的。现在我知道问题出在哪里了。+1.您的代码不会打印
M
(如果输入是
Michi
)但是我修复了它。@Michi好极了!你想共享修复/工作代码吗?将其作为你自己的答案发布或编辑我的答案(你的选择!)。对不起,我的错。你的代码很好。我在错误的文件中测试了你的函数。谢谢。
ABC\0
AB\0C
ACB\0
AC\0B
A\0CB
A\0BC
BAC\0
BA\0C
BCA\0
BC\0A
B\0AC
B\0CA
CBA\0
CB\0A
CAB\0
CA\0B
C\0AB
C\0BA
\0ABC
\0ACB
\0BAC
\0BCA
\0CAB
\0CBA
void permute(char *ptr, size_t i, size_t n){
    size_t j;
    static char prev[80] = "";
    if (i == n){
        if (strcmp(prev, ptr)) {
            strcat (arr, ptr);
            strcat (arr, "\n");
            strcpy(prev, ptr);
        }
    }else{
        for (j = i; j <= n; j++)
        {

            swap( (ptr + i), (ptr + j) );
            permute(ptr, i+1, n);
            swap( (ptr + i), (ptr + j) );
        }
    }
}