我有一段代码循环遍历char数组字符串以尝试检测单词。它会循环通过,如果检测到A - Z或a - z或_(下划线),它会将它添加到char数组中。我需要的,因为它们是单词,是能够将它们放入一个字符串,然后我可以使用另一个函数进行检查,然后可以将其丢弃。 这是我的功能:
char wholeProgramStr2[20000];
char wordToCheck[100] ="";
IdentiferFinder(char *tmp){
//find the identifiers
int count = 0;
int i;
for (i = 0; i < strlen(tmp); ++i){
Ascii = toascii(tmp[i]);
if ((Ascii >= 65 && Ascii <= 90) || (Ascii >= 97 && Ascii <= 122) || (Ascii == 95))
{
wordToCheck[i] = tmp[i];
count++;
printf("%c",wordToCheck[i]);
}
else {
if (count != 0){
printf("\n");
}
count = 0;
}
}
printf("\n");
}
目前我可以看到所有的单词,因为它会在不同的行上打印出来。
WholeProgram2的内容是文件的所有行。它是* tmp参数。
谢谢。
答案 0 :(得分:3)
你描述了将一个大字符串分成小字符串(单词) 假设您正在使用普通分隔符进行解析,例如空格或制表符或换行符:
这是一个三步法 :
首先 ,获取有关源字符串的信息
第二 ,动态创建目标数组以满足您的尺寸需求
第三次 ,循环strtok()
以填充目标字符串数组(char **)
(第四个是释放创造的内存,你需要做的事)
提示:原型可能如下所示:
// void Free2DCharArray(char ** a,int numWords);
代码示例:
void FindWords(char **words, char *source);
void GetStringParams(char *source, int *longest, int *wordCount);
char ** Create2DCharArray(char **a, int numWords, int maxWordLen);
#define DELIM " \n\t"
int main(void)
{
int longestWord = 0, WordCount = 0;
char **words={0};
char string[]="this is a bunch of test words";
//Get number of words, and longest word, use in allocating memory
GetStringParams(string, &longestWord, &WordCount);
//create array of strings with information from source string
words = Create2DCharArray(words, WordCount, longestWord);
//populate array of strings with words
FindWords(words, string);
//Do not forget to free words (left for you to do)
return 0;
}
void GetStringParams(char *source, int *longest, int *wordCount)
{
char *tok;
int i=-1, Len = 0, KeepLen = 0;
char *cpyString = 0;
cpyString = calloc(strlen(source)+1, 1);
strcpy(cpyString, source);
tok=strtok(source, DELIM);
while(tok)
{
(*wordCount)++;
Len = strlen(tok);
if(Len > KeepLen) KeepLen = Len;
tok = strtok(NULL, DELIM);
}
*longest = KeepLen;
strcpy(source, cpyString);//restore contents of source
}
void FindWords(char **words, char *source)
{
char *tok;
int i=-1;
tok = strtok(source, DELIM);
while(tok)
{
strcpy(words[++i], tok);
tok = strtok(NULL, DELIM);
}
}
char ** Create2DCharArray(char **a, int numWords, int maxWordLen)
{
int i;
a = calloc(numWords, sizeof(char *));
if(!a) return a;
for(i=0;i<numWords;i++)
{
a[i] = calloc(maxWordLen + 1, 1);
}
return a;
}
答案 1 :(得分:2)
如果您的目标是查找字符数组中的单词,您可能希望首先找到一个有效的字符序列(并且您似乎正在尝试这样做),并且一旦找到一个,进行二次检查以确定它是否是真正的单词。如果它确实是一个单词,那么您可以决定保留它以供进一步使用。
这种方法的优点是你不需要保留一个大的潜在单词缓冲区,你只需要一个固定的缓冲区,其大小与字典中最大的单词相匹配。事实上,你可能甚至不需要一个缓冲区,只是一个指向char数组的指针,指向一个可能的单词的开头,一个int(虽然一个字节可能就足够了)来跟踪那个单词的长度。
// structure to store a word match in array
typedef struct token_s {
int length;
const char *data;
} token_t;
void nextToken(const char *tmp, int len, token_t *to){
char *start = NULL;
while (len){
if (start) {
// search for end of current word
if (!isalpha(*tmp)) {
to->data = start;
to->length = tmp - start;
return;
}
} else {
// search for beginning of next word
if (isalpha(*tmp))
start = tmp;
}
tmp++;
len--;
} // while
if (start) {
to->data = start;
to->length = tmp - start;
}
}
简单地通过:
to->data + to->length + 1
token_t
每次调用nextToken
,并检查令牌的内容,以确定它是否找到了候选人;如果没有,你知道阵列已被完全扫描。
void scanArray(const char *tmp, int len){
while (len > 0){
token_t to;
to.data = NULL;
to.length =0;
nextToken(tmp, len, &to);
if (to.data) {
tmp += to.length +1;
len -= to.length +1;
// process token here...
} else break;
} // while
}
我使用isalpha
来测试有效字符,但您需要通过自己的函数替换它。而且您必须在scanArray
的正文中插入自己的代码进行二次检查。