【问题标题】:sscanf - get nth word in a sentencesscanf - 获取句子中的第 n 个单词
【发布时间】:2010-11-29 03:12:49
【问题描述】:

我是 C 新手,我正在尝试从标准输入扫描一行并从中提取第 n 个单词。 现在我已经对其进行了硬编码,您可以在其中存储句子中的第一个、第二个或第三个条目,这就是它的样子:

int set_to_nth_word(char* word, char* input, int n)
{
    char word1[20];
    char word2[20];
    char word3[20];
    if(sscanf(input, "%s %s %s", word1, word2, word3) < n)
    {
        printf("You didn't enter enough values\n");
        return 0;
    }
    else
    {
        if(n == 1) strcpy(word, word1);
        else if(n == 2) strcpy(word, word2);
        else if(n == 3) strcpy(word, word3);
        return 1;
    }
}

调用这个方法的代码是:

char *input = (char *) malloc (1);
if(getline(&input, (size_t)0, stdin) != -1)
{
    char word[20];
    if(set_to_nth_word(word, input, 1))
    {
        printf("Success");
    }
}

除了找到解决此问题的方法外,如果有人指出任何不良风格或不良编码实践,我会很高兴!

【问题讨论】:

  • 请注意,这里的 getline() 是一个 GNU 函数,并不适用于所有 POSIX 平台。 (例如,Mac OS X 没有它。)

标签: c string stdin scanf


【解决方案1】:

您可以使用sscanf() 支持的%n 转换说明符。它需要一个int * 参数,并将输入消耗的字符数返回到int

int set_to_nth_word(char *word, const char *input, int n)
{
    int chars_used;

    word[0] = '\0';    /* In case n < 1 */

    while (n > 0 && sscanf(input, "%s%n", word, &chars_used) > 0)
    {
        input += chars_used;
        n--;
    }

    if (n > 0)
    {
        printf("You didn't enter enough values\n");
        return 0;
    }

    return 1;
}

就样式而言,您应该将input 参数设为const char *,因为指向的字符在函数中没有被修改。

为了安全起见,word 的分配长度应为 strlen(input) + 1,而不是声明为固定大小的数组,因为单词可能达到该长度。

【讨论】:

    【解决方案2】:

    以下是一些建议:

    • 不是扫描固定数量的单词,而是循环n 次扫描单个单词

    • 为此使用strtok 而不是sscanf;它会让你的生活更轻松

    • 尽量避免对单词的长度 (20) 进行编译限制,尤其是当您不检查是否超出这些限制时

    • 避免在扫描字符串数据时不必要地复制它,尤其是(如上所述)当您没有对 strcpy 调用执行长度限制时。使用strtok 将在输入中找到零副本的单词。

    【讨论】:

      【解决方案3】:

      家庭作业?随着家庭作业的进行,这有点有趣,因为它会诱使人们实施一个粗略且有限的解决方案,但却允许一个相当简单的真正解决方案。

      无论如何,这是我的尝试......

      #include <stdio.h>
      #include <stdlib.h>
      
      int set_to_nth_word(char *word, const char *input, int n) {
        int i;
        size_t used = 0;
        char convert[1000];
        static const char convertPattern[] = " %*s";
        static const char convertReal[] = " %s";
      
        if((unsigned)n > sizeof convert / sizeof convertPattern - 1) 
          return 0;
        for(i = 1; i < n; ++i)
          used += sprintf(convert + used, "%s", convertPattern);
        sprintf(convert + used, "%s", convertReal);
        return sscanf(input, convert, word) == 1;
      }
      
      int main(int ac, char **av) {
        static char space[1000];
        static char wordn[1000];
      
        if (ac > 1) {
          fgets(space, sizeof space, stdin);
          if(set_to_nth_word(wordn, space, atoi(av[1])))
            printf("%s\n", wordn);
        }
        return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-30
        • 2022-01-21
        • 2020-06-28
        • 2011-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多