我想找到非常简单的类似于BNF的样式字符串的所有排列。
唯一的运算符是()[]|
因此,()
表示“必须具有”,[]
表示“可选”,而|
表示“或”
给定一个字符串(foo | bar) [zop] [flip | flop]
它将给我以下结果:
我可以使用任何算法来做到这一点吗?我可以编写一个简单的解析器+标记器,但是我的直觉可能是一个更简单的解决方案。我正在用ISO C编写代码。
答案 0 :(得分:0)
您可以做的是在字符串解析中使用递归。因此,对于每个字符:
处理强制和可选集将获取其令牌并对其进行迭代,然后重新执行上述3个步骤。同样,处理可选集有一个空迭代,不包含任何东西作为其可选项。所以:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1024
void printPermutation(char* result[], int size) {
for (int i = 0; i < size; ++i) {
printf("%s ", result[i]);
}
printf("\n");
}
void parseDeep(char* s, char* result[], int currIdx) {
char* mandatory[1024];
char* optional[1024];
char *start = 0, *end = 0;
char* delim = "|";
int mandatorySize = 0;
int optionalSize = 0;
while (*s != 0) {
//Mandatory
if ('(' == *s) {
++s;
end = start = s;
while (*end != ')') {
++end;
}
char* mandatorySet = malloc(end - start + 1);
strncpy(mandatorySet, start, end - start);
mandatorySet[end - start] = 0;
char* token = strtok(mandatorySet, delim);
while (token != 0) {
mandatory[mandatorySize] = malloc(strlen(token) + 1);
strcpy(mandatory[mandatorySize++], token);
token = strtok(0, delim);
}
for (int m = 0; m < mandatorySize; ++m) {
result[currIdx] = mandatory[m];
parseDeep(end, result, currIdx + 1);
}
for (int i=0; i < mandatorySize; ++i) {
free(mandatory[i]);
}
free(mandatorySet);
s = end;
return;
//Optional
} else if ('[' == *s) {
++s;
end = start = s;
while (*end != ']') {
++end;
}
char* optionalSet = malloc(end - start + 1);
strncpy(optionalSet, start, end - start);
optionalSet[end - start] = 0;
char* token = strtok(optionalSet, delim);
while (token != 0) {
optional[optionalSize] = malloc(strlen(token) + 1);
strcpy(optional[optionalSize++], token);
token = strtok(0, delim);
}
for (int m = -1; m < optionalSize; ++m) {
//Optional when it is not added
if (m == -1) {
continue;
} else {
result[currIdx] = optional[m];
parseDeep(end, result, currIdx + 1);
}
}
for (int i=0; i < optionalSize; ++i) {
free(optional[i]);
}
free(optionalSet);
s = end;
}
mandatorySize = optionalSize = 0;
++s;
}
printPermutation(result, currIdx);
}
void parse(char* s) {
char* result[MAX_SIZE];
parseDeep(s, result, 0);
}
int main() {
char *s = "(foo | bar) [zop] [flip | flop]";
parse(s);
}
这不检查字符串的有效性。