为字符串生成不同的整体(要使用的点)

Generate distinct entires for a string (dots to be used)

本文关键字:字符串      更新时间:2023-10-16

我有以下字符串:

char *str = "test";

我需要使用点从中生成不同的条目,例如将生成以下内容:

test
t.est
te.st
tes.t
t.e.s.t
t.e.st
te.s.t
...

注意:开头和结尾不能有点。

目前拥有的能够生成其中一些,但不是全部,我尝试了多种方法,例如:
1.在位级别(每次迭代的点打开和关闭),这听起来像是迄今为止最合理的,但我遇到了障碍。
2. 只是一个基于相等生成的嵌套循环,例如(x、y,并将 x、y 与 i 进行比较(其中 i 将用作生成新字符串的循环)。

我当前拥有的代码:

#include <stdio.h>
#include <string.h>
int main() {
    char str[] = "test";
    for (int k = 0; k < sizeof(str) - 1; ++k) {
        for (int x = k; x < sizeof(str) - 1; ++x) {
            for (int y = x + 1; y < sizeof(str) - 1; ++y) {
                char tmp[512], *p = tmp;
                for (int i = 0; i < sizeof(str); ++i) {
                    *p++ = str[i];
                    if (i == x || i == y)
                        *p++ = '.';
                }
                *p++ = '';
                printf("%sn", tmp);
            }
        }
    }
    return 0;
}

这给出了:

t.e.st
t.es.t
t.est.
te.s.t
te.st.
tes.t.
te.s.t
te.st.
tes.t.
tes.t.

是否最好使用位级的东西,如果是这样,有什么建议吗? 或者如果我继续使用当前并修复它以正常工作会更好(请提供解决方案)?

请注意,这里并不真正需要性能,这只是一次性的事情(在启动时),所以,只要它有效,任何事情都可以。

这个词有四个字母,所以有三个分隔符,你可以在其中插入一个点'.'。将有 2 种插入/不插入点的n-1 组合。您可以将它们编码为二进制数:

dec bin word
--- --- -------
  0 000 test
  1 001 t.est
  2 010 te.st
  3 011 t.e.st
  4 100 tes.t
  5 101 t.es.t
  6 110 te.s.t
  7 111 t.e.s.t

你现在需要做的是制作一个从 0 更改为 2n-1-1(包括 0)的"掩码",并将此掩码解释为嵌套循环中的一系列点,如下所示:

string s = "test";
for (int mask = 0 ; mask != 1 << (s.size()-1) ; mask++) {
    cout << s[0];
    for (int i = 0 ; i != s.size()-1 ; i++) {
        if (mask & (1<<i)) {
            cout << ".";
        }
        cout << s[i+1];
    }
    cout << endl;
}

演示。

使用整数作为位掩码:对于每个位,如果已设置,请打印一个.。 如果迭代从 02 ** (len-1) 的所有值,则将枚举点的所有可能位置以及所有可能的组合:

#include <stdio.h>
#include <string.h>
int main(void) {
    char str[] = "test";
    int len = strlen(str);
    for (int bits = 0; bits < (1 << (len - 1)); bits++) {
         putchar(str[0]);
         for (int j = 1; j < len; j++) {
             if (bits & (1 << (j - 1)))
                 putchar('.');
             putchar(str[j]);
         }
         putchar('n');
    }
    return 0;
}

此函数应执行您的预期操作:

void dotify(char *str) {
    int nr = 1 << (strlen(str)-1);
    char buf[strlen(str)*2];
    while (nr--) {
        int i;
        char *ptr = buf;
        for (i = 0; i < strlen(str); i++) {
            *ptr++ = str[i];
            if (nr & (1 << i))
                *ptr++ = '.';
        }
        *ptr = '';
        puts(buf);
    }
}

该解决方案背后的基本思想是将每个点位映射到具有 strlen(str)-1 位的二进制数的数字。从 0-n 开始计算此数字。数字 0 表示"不设置点",而 1 表示"设置点"