簡體   English   中英

如何迭代生成字母和數字的所有可能組合,以與可變長度字符串匹配?

[英]How to iteratively generate all possible combinations of letters and numbers for matching with a variable length string?

我希望編寫一個迭代邏輯程序,其中有一個輸入字符串,該程序從長度1開始,並嘗試所有可能的字母和數字組合。 如果找不到匹配項,它將嘗試使用所有長度為2的字母和數字的組合,依此類推,直到找到與輸入字符串匹配的為止。

例如,

string input = "xG7a";
// loop all possible combinations for length 1, i.e., 0-9 then A-Z, then a - z
// check for all if matches the input string
// loop all possible combinations for length 2, i.e., 00-09, then 0A-0Z, then 0a - 0z. Then 
// for 10-19, then 1A-1Z, then 1a - 1z ... till z0-z9, then zA-zZ, then za - zz
// again check for all if matches the input string
// Keep doing this for lengths 3, 4, 5 and so on till it matches with the input string.
// exit with status success if match else keep going till infinity
// This example would exit at length 4 when it matches with "xG7a"

此處匹配的所有可能組合的數量為(10 + 26 + 26 = 62)= 62 ^ 1 + 62 ^ 2 + 62 ^ 3 + ...直到找到匹配項。

編輯更多詳細信息:

  • 這是編寫蠻力邏輯練習的一部分
  • 輸入字符串事先未知。 上面的例子只是為了說明。 我已經弄清楚了其余的邏輯。 生成的字符串將傳遞到哈希函數中,該哈希函數生成哈希以與數據庫中的密碼哈希匹配。 因此,要生成的字符串的動態性質。
  • 預先知道密碼字符串僅由數字以及大小寫字母組成。

預先感謝您提供的所有幫助。

用正確的順序創建一個包含所有可能字符的字符串:

 char charlist[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

然后針對您要檢查的每個字符,遍歷此字符串以構建測試字符串並進行比較:

int i, found;
char str_to_test[5];
for (i=0, found=0; !found && i<strlen(charlist); i++) {
    str_to_test[0] = charlist[i];
    str_to_test[1] = 0;
    if (!strcmp(str_to_test, target_string)) {
        found = 1;
    }
}
if (found) {
    printf("found it!\n");
} else {
    printf("not found\n");
}

對每個子字符串重復嵌套循環。

您說-我說的是一些偽代碼- 完整的工作程序

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

#define MARGIN 5

// if you're getting errors due to redeclaration of 'strdup', just remove that
const char *strdup(const char *string) {
    const size_t len = strlen(string);
    char *dst = calloc(len + 1, sizeof(char));

    memmove(dst, string, len);

    return dst;
}

struct NumeralSystem {
    char *alphabet;
    size_t base;
};

struct Word {
    struct NumeralSystem ns;
    char *data; // the current combination, null-terminated
    unsigned int *_internal; // indices of the characters of 'data' in 'ns.alphabet' 
    size_t length, maxLength;
};

struct NumeralSystem NewSystem(const char *alpha) {
    struct NumeralSystem ret = {strdup(alpha), strlen(alpha)};

    return ret;
}

struct Word NewWordEmpty(const struct NumeralSystem ns, const size_t maxLength) {
    struct Word ret;

    ret.ns = ns;
    ret.data = calloc(maxLength + 1, sizeof(char));
    ret._internal = calloc(maxLength + 1, sizeof(unsigned int));
    ret.maxLength = maxLength;

    *ret._internal = 0;
    *ret.data = *ret.ns.alphabet;

    ret.length = 1;

    return ret;
}

struct Word NewWordPreset(const struct NumeralSystem ns, const char *data) {
    struct Word ret;

    ret.length = strlen(data);

    const size_t maxLength = ret.length + MARGIN;

    ret.ns = ns;
    ret.data = calloc(maxLength + 1, sizeof(char));
    ret._internal = calloc(maxLength + 1, sizeof(unsigned int));
    ret.maxLength = maxLength;

    memmove(ret.data, data, ret.length);

    for (size_t i = 0; i < ret.length; ++i) {
        const char *found = strchr(ns.alphabet, ret.data[i]);
        if (found == NULL) return NULL;

        ret._internal[i] = found - ns.alphabet;
    }

    return ret;
}

void EnlargeWord(struct Word *wrd) { // here, wrd->length - wrd->maxLength == 1
    const size_t newSize = wrd->maxLength + MARGIN;

    wrd->data = realloc(wrd->data, newSize * sizeof(char));
    wrd->_internal = realloc(wrd->_internal, newSize * sizeof(int));

    memset(wrd->data + wrd->maxLength + 1, 0, MARGIN);
    memset(wrd->_internal + wrd->maxLength + 1, 0, MARGIN);

    wrd->maxLength = newSize;
}

void DestroyWord(struct Word *wrd) {
    free(wrd->data), free(wrd->_internal);
}

struct Word *next(struct Word *wrd) {
    int len = (int)(wrd->length - 1); // this can be negative, see below

    // handle the overflow if current digit is equal to the last_digit of the alphabet
    //   1. last_digit -> first_digit
    //   2. go to previous position
    while ((len >= 0) && (wrd->_internal[len] == wrd->ns.base - 1)) {
        wrd->_internal[len] = 0;
        wrd->data[len--] = *wrd->ns.alphabet;
    }

    // if all the digits in the word were equal to the last_digit of the alphabet,
    // 'len' will be exactly (-1), and the word's length must increase
    if (len == -1) {
        wrd->data[wrd->length++] = *wrd->ns.alphabet;

        // UH-OH, we're about to run out of bounds soon!
        if (wrd->length > wrd->maxLength)
            EnlargeWord(wrd);

        return wrd;
    }

    // if 'len' is still nonnegative, it's the position of the digit
    // that we haven't increased yet
    wrd->data[len] = wrd->ns.alphabet[++wrd->_internal[len]];

    return wrd;
}


int main(void) {
    const struct NumeralSystem ns = NewSystem("abcdef");
    struct Word wrd = NewWordPreset(ns, "deadbeef");

    printf("%s\n", wrd.data);

    for (unsigned int i = 0; i < 30; ++i)
        printf("%s\n", next(&wrd)->data);

    DestroyWord(&wrd);

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM