我是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");
}
}
除了找到这个问题的解决方案之外,如果有人指出任何不好的风格或糟糕的编码习惯,我会很高兴!
答案 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;
}