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) );
}
}
}