0

我正在尝试扫描包含 C 中多个单词的行。有没有办法逐字扫描它并将每个单词存储为不同的变量?

例如,我有以下类型的行:

A is the 1 letter;
B is the 2 letter;
C is the 3 letter;

如果我正在解析第一行:“A 是 1 个字母”并且我有以下代码,我在每种情况下都放什么,以便我可以获取各个标记并将它们存储为变量。为了澄清,在这段代码的末尾,我想要不同变量中的“is”、“the”、“1”、“letter”。

我有以下代码:

while (feof(theFile) != 1) {
    string = "A is the 1 letter"
    first_word = sscanf(string);
    switch(first_word):
      case "A":
        what to put here?
      case "B":
        what to put here?
      ...     
4

4 回答 4

2

你不应该那样使用feof()。您应该使用fgets()或等效。您可能需要使用鲜为人知(但存在于标准 C89 中)的转换说明符%n

#include <stdio.h>

int main(void)
{
    char buffer[1024];

    while (fgets(buffer, sizeof(buffer), stdin) != 0)
    {
        char *str = buffer;
        char word[256];
        int  posn;
        while (sscanf(str, "%255s%n", word, &posn) == 1)
        {
            printf("Word: <<%s>>\n", word);
            str += posn;
        }
    }
    return(0);
}

这会读取一行,然后sscanf()迭代地使用从该行中获取单词。%n格式说明符不计入成功的转换,因此与 1 进行比较。注意使用以%255s防止word. 还要注意,在转换规范中指定的 255 计数之后可能会写入 null,因此声明 of和转换说明符sscanf()之间的差异为 1 。char word[256];%255s

显然,您可以决定如何处理提取的每个单词。这里的代码只是打印它。

与基于任何解决方案的任何解决方案相比,此技术的一个优点strtok()sscanf()不会修改输入字符串,因此如果您需要报告错误,您可以在错误报告中使用原始输入行。


编辑问题后,似乎一个单词中都不需要分号之类的标点符号;上面的代码将包含标点符号作为单词的一部分。在这种情况下,您必须更加努力地考虑要做什么。起点很可能是使用字母数字扫描集作为转换规范来代替%255s

"%255[a-zA-Z_0-9]%n"

然后,您可能必须查看下一个组件开头的字符中的内容,如果它不是字母数字则跳过它:

if (!isalnum((unsigned char)*str))
{
    if (sscanf(str, "%*[^a-zA-Z_0-9]%n", &posn) == 0)
        str += posn;
}

导致:

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char buffer[1024];

    while (fgets(buffer, sizeof(buffer), stdin) != 0)
    {
        char *str = buffer;
        char word[256];
        int  posn;
        while (sscanf(str, "%255[a-zA-Z_0-9]%n", word, &posn) == 1)
        {
            printf("Word: <<%s>>\n", word);
            str += posn;
            if (!isalnum((unsigned char)*str))
            {
                if (sscanf(str, "%*[^a-zA-Z_0-9]%n", &posn) == 0)
                    str += posn;
            }
        }
    }
    return(0);
}

您需要考虑所选字母数字范围的 I18N 和 L10N 方面;可用的内容可能取决于您的实现(不幸的是,POSIX 没有在scanf()扫描集中指定对符号的支持,例如[[:alnum:]])。

于 2012-12-07T01:10:00.937 回答
1

您可以strtok()用来标记或拆分字符串。示例请参考以下链接:http ://www.cplusplus.com/reference/cstring/strtok/

您可以获取字符指针数组并将标记分配给它们。

例子:

char *tokens[100];
int i = 0;
char *token = strtok(string, " ");
while (token != NULL) {
    tokens[i] = token;
    token = strtok(NULL, " ");
    i++;
}

printf("Total Tokens: %d", i);
于 2012-12-07T01:02:39.620 回答
0

请注意说明%s符去除空格。所以你可以写:

    std::string s = "A is the 1 letter";
    typedef char Word[128];
    Word words[6];
    int wordsRead = sscanf(s.c_str(), "%128s%128s%128s%128s%128s%128s", words[0], words[1], words[2], words[3], words[4], words[5] );
    std::cout << wordsRead << " words read" << std::endl;
    for(int i = 0;
        i != wordsRead;
        ++i)
        std::cout << "'" << words[i] << "'" << std::endl;

请注意这种方法(与 不同strtok)如何有效地要求关于要阅读的最大单词数及其长度的假设。

于 2012-12-07T01:04:36.887 回答
0

我建议使用strtok(). 这是来自http://www.cplusplus.com/reference/cstring/strtok/的示例

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

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

输出将是:

Splitting string "- This, a sample string." into tokens:

This

a

sample

string

于 2012-12-07T01:07:06.157 回答