C Unix - 解析一行字符

时间:2014-09-27 18:26:54

标签: c parsing unix

我基本上想从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);

1 个答案:

答案 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时,你会获得它。如果你想要一个有趣的实验,尝试在编写测试后删除你的主源文件,然后看看你的测试套件是否足以迫使你正确地重写它。如果没有,你需要更多的测试。)