如何在c中的字符数组中用strtok划分单词

how to divide words with strtok in an array of chars in c

我有一个名为 excuses 的结构,它包含字符,我需要存储至少 20 个借口。然后,我需要把每一个借口的每一个字都划分到一个数组中。

¿我该怎么做?

#define excuseLength 256

typedef struct{
    char sentence[excuseLength];
}excuse;

excuse listExcuses[20];

for (int listExcuses_i = 0; listExcuses_i < 20; listExcuses_i++)
{
    char *input;
    scanf("%s", input);
    strcpy(listExcuses[listExcuses_i].sentence, input);

    char* token = strtok(input, " ");
    while(token != NULL){
        printf("token: %s\n", token);
        token = strtok(NULL, " ");
    }
}

我更改了 fgets 的 scanf 并初始化了 char 输入[256],现在它可以工作了!

#define excuseLength 256
#define numberExcuses 20

typedef struct{
    char sentence[excuseLength];
}excuse;

excuse listExcuses[20];

for (int listExcuses_i = 0; listExcuses_i < numberExcuses; listExcuses_i++)
{
    char input[256];
    scanf("%s", input);
    fgets(input, 256, stdin);
    strcpy(listExcuses[listExcuses_i].sentence, input);

    char* token = strtok(input, " ");
    while(token != NULL){
        printf("token: %s\n", token);
        token = strtok(NULL, " ");
    }
}

以下是您可以添加到解决方案中的一些内容:

  • 检查 fgets() 的 return 值,因为它 returns NULL 出错。
  • 如果您决定仍然使用 scanf(),请务必使用 scanf("%255s", input) 代替 char input[256]。使用格式说明符 %255s 而不是简单的 %s 检查输入过多。总的来说,使用 fgets() 读取输入更好。
  • 删除 fgets() 附加的 '\n' 个字符。这也有助于检查您在 input 中输入的字符数没有超过 256 的限制,并且您的句子在每个句子后没有尾随换行符。如果您不删除此换行符,那么您的 strtok() 定界符将必须改为 " \n"
  • #define 常量,并使用 const char* 作为字符串文字,例如 strtok() 的分隔符。
  • 您还可以添加一些代码来检查来自 fgets() 的空输入。您可以简单地使用一个单独的计数器,并且只为找到的有效字符串增加该计数器。
  • struct只有一个成员也很奇怪,通常结构包含多个成员。您可以简单地绕过使用结构并使用声明为 char listexcuses[NUMEXCUSES][EXCUSELENGTH] 的二维字符数组。该数组最多可以容纳 20 个字符串,每个字符串的最大长度为 256

这是您的方法的一些修改代码:

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

#define EXCUSELENGTH 256
#define NUMEXCUSES 20

typedef struct {
    char sentence[EXCUSELENGTH];
} excuse;

int main(void) {
    excuse listexcuses[NUMEXCUSES];
    char input[EXCUSELENGTH] = {'[=10=]'};
    char *word = NULL;
    const char *delim = " ";
    size_t slen, count = 0;

    for (size_t i = 0; i < NUMEXCUSES; i++) {

        printf("\nEnter excuse number %zu:\n", count+1);
        if (fgets(input, EXCUSELENGTH, stdin) == NULL) {
            fprintf(stderr, "Error from fgets(), cannot read line\n");
            exit(EXIT_FAILURE);
        }

        slen = strlen(input);
        if (slen > 0 && input[slen-1] == '\n') {
            input[slen-1] = '[=10=]';
        } else {
            fprintf(stderr, "Too many characters entered in excuse %zu\n", count+1);
            exit(EXIT_FAILURE);
        }

        if (*input) {
            strcpy(listexcuses[count].sentence, input);
            count++;

            printf("\nTokens found:\n");
            word = strtok(input, delim);
            while (word != NULL) {
                printf("%s\n", word);
                word = strtok(NULL, delim);
            }  
        }
    }

    return 0;
} 

由于您最终需要将这些令牌存储在某个地方,因此您将需要另一种存储此数据的形式。由于您不知道可以获得多少个令牌,或者每个令牌有多长,您可能需要使用诸如 char **tokens 之类的东西。这不是数组,而是指向指针的指针。使用这个将允许存储任意数量的单词和每个单词的任意长度。为此,您将需要动态内存分配。 post 中的答案会有所帮助。