sscanf - 在一个句子中得到第n个单词

时间:2010-11-29 03:12:49

标签: c string stdin scanf

我是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");
    }
}

除了找到这个问题的解决方案之外,如果有人指出任何不好的风格或糟糕的编码习惯,我会很高兴!

3 个答案:

答案 0 :(得分:9)

您可以使用%n支持的sscanf()转换说明符。它需要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,而不是声明为固定大小的数组,因为这些单词可能达到该长度。

答案 1 :(得分:2)

以下是一些建议:

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

  • 使用strtok代替sscanf;它会让你的生活更轻松

  • 尽量避免编辑限制一个单词的长度(20),特别是当你没有检查是否超出这些限制时

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

答案 2 :(得分:0)

作业?作为家庭作业,它有点有趣,因为它诱使人们实施原始且有限的解决方案,但却允许一个相当简单的真正解决方案。

无论如何,这是我拍摄的......

#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;
}