【问题标题】:Reading user input and checking the string读取用户输入并检查字符串
【发布时间】:2011-06-26 07:11:16
【问题描述】:

如何在 C 中检查读取的字符串中的子字符串?

如果我有以下情况

char name[21];
fgets(name, 21, stdin);

如何检查字符串中的一系列子字符串?

如何在字符之前检查子字符串?例如,如何检查= 符号之前的子字符串?

【问题讨论】:

  • 发布示例输入字符串。如果 strtok 无法对其进行标记,那么您可能只需要逐个字符地扫描并挑选出子字符串。

标签: c string substring fgets


【解决方案1】:

警惕strtok();它不是可重入的。除此之外,这意味着如果您需要在一个函数中调用它,然后再调用另一个函数,并且如果另一个函数也使用strtok(),那么您的第一个函数就搞砸了。它还在分隔符上写入 NUL ('\0') 字节,因此它会随时修改输入字符串。如果您要查找多个终止符,则无法确定找到了哪一个。此外,如果您编写了一个库函数供他人使用,但您的函数使用strtok(),您必须记录这一事实,以便您的函数的调用者不会被他们自己的代码的失败所困扰调用你的函数后使用strtok()。换句话说,它是有毒的;如果你的函数调用strtok(),一般来说,它会使你的函数不可重用;同样,您使用strtok() 的代码也无法调用也使用它的其他人的函数。

如果你仍然喜欢这个功能的想法——有些人喜欢(但我几乎总是避免它)——那么在你的系统上寻找strtok_r()。它是可重入的;它需要一个额外的参数,这意味着其他函数可以使用strtok_r()(或strtok())而不影响您的函数。

有多种选择可能是合适的。显而易见的是strchr()strrchr()strpbrk()strspn()strcspn():这些都不会修改他们分析的字符串。它们都是标准 C 的一部分(strtok() 也是如此),因此它们基本上随处可用。在单个字符之前寻找材料建议您应该使用strchr()

【讨论】:

  • 我想要一个等效于 Objective C componentsSeparatedByString: 的组件,它返回一个元素数组,这样你就可以访问你想要的。
  • +1 击败我并同时使用更多单词。第三个strtok 问题是我以前从未想过的。
  • @alJaree - 你必须自己动手。它是否应该返回一个 C 数组(带有 size_t * 输出参数)?还是应该将缓冲区和长度作为参数并尝试填充它们?还是应该返回一个用于数组目的的用户定义结构?同样,它应该如何分配字符串?
  • 我想要的是拥有一个结构集合。在这些结构中,我有变量,其中一个变量是字符串数组。所以我需要获取用户输入,通过将其分配给 tempStruct 字段来处理它。我想检查用户输入并匹配第一个“令牌”(在“:”之前),然后将其余部分存储在字符串数组中。重复直到输入的第一个标记与我想要的不匹配,然后将此结构添加到集合结构中。
  • @alJaree:内存将如何分配?你怎么知道输入行的长度?如果输入行比您想象的要长,会发生什么?当第一个 toekn 与您想要的不匹配时,您如何判断?当您说“字符串数组”时,您是在拆分冒号后面的内容吗?你需要处理冒号前的空格吗?在第一个词之前?结肠之后?您是否将具有相同前缀的多行匹配到相同的临时结构,或者您是否单独处理每一行?如果输入行中没有冒号会怎样?
【解决方案2】:

使用strtok() 将字符串拆分为标记。

char *pch;
pch = strtok (name,"=");
if (pch != NULL)
{
  printf ("Substring: %s\n",pch);
}

您可以继续调用strtok() 以查找= 之后的更多字符串。

【讨论】:

  • 谢谢。这将返回或打印出什么? = 之前的子字符串?如何将它与 C 中的另一个字符串进行比较?
  • =之前的字符串。所有字符串比较都在 C 中使用 strcmp()(或类似 strncmp() 的变体)完成,因此只需使用 pch 作为参数之一。
【解决方案3】:

您可以使用strtok,但它不可重入并且会破坏原始字符串。其他(也许更安全的)函数是strchrstrstrstrspn,也许还有mem* 的变体。一般来说,我避免使用strn* 变体,因为虽然它们进行“绑定检查”,但它们仍然依赖于 nul 终止符。它们可能会在恰好比您预期处理的长的有效字符串上失败,并且除非您知道缓冲区大小,否则它们实际上不会防止缓冲区溢出。最好(恕我直言)忽略终止符,并确切知道每次 mem* 函数的工作方式时您正在使用多少数据。

【讨论】:

  • C 看起来很原始。我只是想为大学课程学习它。这种动态做事的斗争。我希望 obj c 更常见。 :/ 那么,如果我不知道每次我会收到多少数据怎么办。我正在拆分用户输入。例如语言:英语我想检查语言,然后抓取英语并存储它。
  • @alJaree - 非常刻意。它使您可以更快,更准确地做事。如果你想要简单的动态控制(这也是一件好事,并且有它自己的优点),你不应该使用 C。但是学习如何用“C 方式”来做也很重要。
  • 当然。我知道了解事物的运作方式非常有用。当计算机拥有几乎无限的内存和处理能力时,未来会发生什么?无论如何,这是另一个讨论;)所以我应该手动扫描char数组(用户输入)并检查分隔符,自己将每个部分存储到一个数组中,或者是否有一个库函数可用于拆分字符串并存储零件成一个数组?
  • @alJaree:这取决于您可以使用哪些库。标准 C 库中没有这样的函数,但在标准 C 库之上构建的其他库中可能有这样的函数。
  • @alJaree - 好吧,当您可以使用strchrstrspn 时,它并不是真正的手动扫描,但阵列存储是您必须自己做的事情。 C 不像大多数其他语言那样具有内置的动态数组类型。
猜你喜欢
  • 2014-02-16
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-26
  • 2015-10-03
相关资源
最近更新 更多