【问题标题】:C Unix - Parse a single line of characters [duplicate]C Unix - 解析单行字符[重复]
【发布时间】:2014-09-27 18:26:54
【问题描述】:

我基本上想从标准输入中获取单行输入,获取“字符串”(由空格分隔的字符数组),然后将每个“字符串”放入 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);
}

编辑:感谢 Paul,对于任何与我有同样问题的人,我通过更改以下行来让它工作:

arguments[i] = token;

到:

strcpy(arguments[i], token);

【问题讨论】:

  • 显示您尝试过的内容以及失败的原因。 fgets()strtok() 或手动解析的组合是执行此操作的正常方式,因此,如果这对您不起作用,那么您应该这样做,而不是寻找其他方式。跨度>
  • arguments[i] = token; - 你不能分配给这样的数组,你需要使用strcpy()strtok() 也会修改你传递给它的字符串,所以你不应该让它成为const。这都是非常基础的,我认为你需要多花一点时间学习 C,然后再在 Stack Overflow 上提问。
  • 我认为argvint main(int argc, char * * argv);)可能正是您所需要的。请注意,设计程序以获取其参数作为命令行参数通常比交互式查询用户更好。不幸的是,后者是大多数书籍和课程教给你的。

标签: c parsing unix


【解决方案1】:

把它分成几个步骤:

    1234563
  • 接下来,执行换行规范化。一些应用程序总是需要尾随换行符;其他人永远不会想要它; getline有时将它给你,所以你需要以一种或另一种方式强制它(我建议删除,因为它只是一个 NUL 字节的条件分配,而不是条件重新分配)。请注意,如果您想使用回车进行 DTRT(以处理 windows 和经典 mac 文件 - 是的,仍然存在于野外 - 您需要编写自己的函数而不是 getline

  • 此时,您拥有包含整行的malloced 字符串的所有权。我将假设您希望一次访问所有参数(在一个数组中)而不是一次访问一个,因此您需要分配一个足够大的数组;通过对输入执行早期传递来计算分隔符的数量通常很方便(如果您在将数组作为类提供的高级语言中执行此操作,则通常以增量方式推送)。 不要像大多数示例一样使用固定大小的数组。学习会导致现实世界中的安全漏洞的坏习惯是绝对不能接受的。或者,如果您根据代码确切地知道 预期 有多少令牌,则可以准确分配那么多令牌,如果太多或太少,就会出错。

  • 现在遍历字符串。我倾向于避免使用strtok,因为它有很多问题,其中一些问题没有用strtok_r 解决,所以使用直接迭代滚动我自己的搜索(如果我需要进行额外的预处理,例如反斜杠或引号处理,这很有用 - 这可以就地完成,无需分配,记住)或使用strchr(用于单个字符;另请参见strchrnul以获得更方便的GNU扩展)或strpbrk/strspn/strcspn(用于搜索对于任何一组字符,例如空格或制表符(请注意,bashslash/quote 处理 也可以 用这个来完成,并且可能比手动循环更有效。但是对于你通常花时间解析,可读性远比效率重要,所以重要的是你能把什么变得可读))

  • 对于每个单词,在分隔符顶部存储一个 NUL 并将指向单词开头的指针存储到数组中,然后跳过分隔符以开始下一个单词。如果您点击输入字符串的末尾而不是分隔符,请中断。

  • 最后,编写一组测试用例。想到的一些重要情况是:空行,只有空格的行,开头/结尾有空格的行,有相邻空格的行,只有一个单词的行,有很多单词的行;使用每个分隔符重复上述所有操作,并使用/不使用每种形式的尾随换行符。您可能会在代码中发现一些错误,因此返回并修复它。 (有些人主张首先编写测试用例,并且只在必要时编写代码以使测试通过,但我想你不了解哪种测试有助于发现错误,但你'当你写bug的时候会得到它。如果你想要一个有趣的实验,试着在你写完测试后删除你的主源文件,然后看看你的测试套件是否足以迫使你正确地重写它。如果没有,你需要更多测试。)

【讨论】:

    猜你喜欢
    • 2014-05-22
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 2023-03-15
    • 2013-03-30
    • 2011-07-03
    相关资源
    最近更新 更多