如何读取一个字符串中的两个单词

How to read two words in one string

我有这样的示例输入文件

1344 穆罕默德·阿尤比 1
第1344章 穆罕默德·阿里·阿尤比1

首先,姓氏与制表符分隔。但是,一个人可能有两个名字。在这种情况下,名称以 空格 .

分隔

我正在尝试从输入文件中读取并将它们存储在相关变量中。

这是我的代码,当一个人只有一个名字时成功读取。

fscanf(fp, "%d\t%s\t%s\t%d", &id, firstname, surname, &roomno)

问题是有没有办法读取可能包含两个名字的输入文件。

提前致谢。

您可以使用 %[ 说明符读取字符串中的空格:

fscanf(fp, "%d\t%[^\t]\t%[^\t]\t%d", &id, firstname, surname, &roomno)

使用 fgets() 读取 ,然后将其保存为 字符串

然后解析字符串。保存到足够大小的缓冲区中。

使用 "\t" 扫描,扫描任意数量的 white-space - 零个或多个。使用下面的 TABFMT 扫描 1 个制表符。

沿途测试结果。

此代码使用 " %n" 来查看解析是否达到该点,仅此而已。

#define LINE_N 100
char line[LINE_N];
int id, 
char firstname[LINE_N];
char surname[LINE_N];
int roomno;

if (fgets(line, sizeof line, fp)) {
  int n = 0;
  #define TABFMT "%*1[\t]"
  #define NAMEFMT "%[^\t]"
  sscanf(line, "%d" TABFMT NAMEFMT TABFMT NAMEFMT TABFMT "%d %n", 
      &id, firstname, surname, &roomno, &n);
  if (n == 0 || line[n]) {
    fprintf(stderr, "Failed to parse <%s>\n", line);
  } else {
    printf("Success: %d <%s> <%s> %d\n", id, firstname, surname, roomno);
  }
}

如果姓氏或名字为空,此代码会将其视为错误。

另一种方法是将该行读入字符串,然后使用 strcspn()、strchr()strtok() 寻找制表符以解析为 4 sub-strings`。


OP 遗漏的更大问题是如何处理 ill-formatted 输入?错误处理经常被“输入将是良好格式”而忽略,但在现实生活中,错误的输入确实会发生,这也是黑客寻找的破解方法。防御性编码采取步骤来验证输入。迂腐的代码根本不会使用 *scanf(),而是使用 fgets(), strcspn(), strspn(), strchr(), strtol() 和测试、测试、测试。此答案是一项 middle-of-the-road 测试工作。

题中的答案是合理的,但题目是错误的

这里的end-goal读作human-names。人名千差万别——并不总是first, [middle,] last。在此假设下烘焙是设计错误。

这是一个多次重复多次次的错误。最好不要重复。

最简单的解决方案是 re-order 数据字段,并且不对名称结构做任何假设。所以输入数据变为:

1344 1 Muhammad Ayyubi
1344 1 Muhammad Ali Ayyubi

然后扫描代码可以提取前两个数字字段,并将该行的其余部分用于名称(不对结构进行假设)。

更一般地说,如果您确实需要扫描带有嵌入空格的字段,请记住 ASCII 字符 table 中的 32 个“控制”字符,其中约 24 个没有分配语义(当前使用)。您可以向文本文件添加结构,例如使用 (from man ascii:

034   28    1C    FS  (file separator)        
035   29    1D    GS  (group separator)       
036   30    1E    RS  (record separator)      
037   31    1F    US  (unit separator)        

几乎没有允许文本字段使用这些字符的情况。