开发者

sscanf - get nth word in a sentence

开发者 https://www.devze.com 2023-01-27 14:07 出处:网络
I\'m new to C, and I\'m trying to scan a line from stdin and extract the nth word from it. Right now I\'ve hard-coded it where you can store the first, second, or third entry in the sentence, and this

I'm new to C, and I'm trying to scan a line from stdin and extract the nth word from it. Right now I've hard-coded it where you can store the first, second, or third entry in the sentence, and this is what it looks like:

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

The code that calls this method is:

char *input = (char *) malloc (1);
if(getline(&input, (size_t)0, st开发者_高级运维din) != -1)
{
    char word[20];
    if(set_to_nth_word(word, input, 1))
    {
        printf("Success");
    }
}

Besides finding a solution to this problem, I'd be happy if anyone points out any bad style or bad coding practices!


You can make use of %n conversion specifier supported by sscanf(). It requires an int * parameter, and returns the number of characters consumed from the input into that 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;
}

As far as style goes, you should make the input parameter const char *, since the characters pointed to are not being modified in the function.

In terms of safety, word should be allocated with a length of strlen(input) + 1, rather than declared as a fixed-size array, since the words may be up to that length.


Here are a few pieces of advice:

  • instead of scanning a fixed number of words, loop n times scanning a single word

  • use strtok instead of sscanf for this; it will make your life much easier

  • try to avoid compiled-in limits on how long a word can be (20), especially when you're not checking to see if those limits are being exceeded

  • avoid copying string data unnecessarily when scanning it, especially (as stated above) when you're not enforcing length limits on your strcpy calls. Using strtok will locate words within the input with zero copies.


Homework? As homework assignments go, it's a bit interesting, as it tempts one to implement a crude and limited solution yet allows a fairly easy true solution.

Anyway, here is my shot at it...

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

精彩评论

暂无评论...
验证码 换一张
取 消