我基本上想从stdin中获取一行输入,抓住'字符串' (由空格分隔的一系列字符串),然后放置每个字符串'到char []数组。我已经尝试过使用fgets,getline和strtok;我不想使用外部库或Unix不可用的任何东西。我在这里看到了很多类似的问题所以我很抱歉,如果已经回答了这个问题,但是我无法找到一种简单明了的方法来做到这一点。
谢谢,如果我说错了,我很抱歉,我很不习惯C。
编辑:好的,所以这是我最近尝试过的事情:#include <string.h>
#include <stdio.h>
int main() {
const char str[80] = "This is a | test";
const char s[2] = " ";
char *token;
char arguments[10][50];
int i = 0;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
arguments[i] = token;
i++;
token = strtok(NULL, s);
}
return(0);
}
编辑:感谢保罗,对于任何有同样问题的人,我通过更改以下内容来完成工作:
arguments[i] = token;
为:
strcpy(arguments[i], token);
答案 0 :(得分:1)
将其拆分为以下步骤:
首先,使用getline
获取整行输入(GNU扩展;如果不存在,则实现自己作为fgets
周围的循环)
接下来,执行换行规范化。一些应用程序总是希望尾随换行符;其他人永远不会想要它; getline
会给你有时,所以你需要以某种方式强制它(我建议删除,因为它只是一个NUL字节的条件赋值,而不是而不是有条件的realloc)。请注意,如果你想用回车DTRT(处理窗口和经典的mac文件 - 是的,仍然存在于野外 - 你需要编写自己的函数而不是getline
)
此时,您拥有包含整行的malloc
ed字符串。我假设您希望一次访问所有参数(在数组中)而不是一次访问所有参数,因此您需要分配足够大的数组;通过对输入执行早期传递来计算分隔符的数量通常很方便(如果您在提供数组作为类的更高级语言中执行此操作,则通常会逐步推送)。 不要像大多数示例那样使用固定大小的阵列。从来没有人能够学会在现实世界中引起安全漏洞的不良习惯。或者,如果根据代码确切地知道期望的令牌数量,那么如果有太多或太少,您可以准确分配那么多并且错误。
现在迭代字符串。我倾向于避免strtok
,因为它有很多问题,其中一些问题没有用strtok_r
解决,所以使用直接迭代滚动我自己的搜索(如果我需要进行额外的预处理,如反斜杠或引用处理 - 可以就地完成,无需分配,记住)或使用strchr
(对于单个字符;另请参阅strchrnul
以获得更方便的GNU扩展)或strpbrk
/ strspn
/ strcspn
(搜索任何一组字符,例如空格或制表符(请注意,baskslash / quote handling 也可以完成此操作,并且可能是比手动循环更有效。但是对于你通常花时间解析的东西,可读性远比效率重要,所以重要的是你可以使它变得可读))
对于每个单词,将NUL存储在分隔符的顶部,并将指向单词开头的指针存储到数组中,然后跳过分隔符以开始下一个单词。如果您点击输入字符串的末尾而不是分隔符,请中断。
最后,编写一组测试用例。我想到的一些重要案例是:空行,仅包含空格的行,在开头/结尾处有空格的行,包含相邻空格的行,仅包含一个单词的行,包含许多单词的行;使用每个分隔符并使用/不使用每种形式的尾随换行符重复上述所有内容。您可能会在代码中发现一些错误,因此返回并修复。 (有些人主张编写测试用例首先并仅在必要时编写代码以使测试通过,但我想你不会掌握哪种测试有助于发现bug,但是当你编写bug时,你会获得它。如果你想要一个有趣的实验,尝试在编写测试后删除你的主源文件,然后看看你的测试套件是否足以迫使你正确地重写它。如果没有,你需要更多的测试。)