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 worduse
strtok
instead ofsscanf
for this; it will make your life much easiertry 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;
}
精彩评论