如何将文本文件中的一行的子字符串保存到字符串数组中?
Posted
技术标签:
【中文标题】如何将文本文件中的一行的子字符串保存到字符串数组中?【英文标题】:How can I save a substring of a line from a text file into an array of strings? 【发布时间】:2017-11-05 03:25:51 【问题描述】:我有读取.txt
文件的代码:
Pancho: Juanka,Cony
这个想法是找到字符':'
并将其分开保存在一个字符串数组中。与 Juanka
和 Cony
相同,但它会在找到 ','
和 '\0'
时出现。
【问题讨论】:
查看strtok
。
使用sscanf
... 或strchr
查找角色
另一种选择是strcspn
。就我个人而言,这是我最喜欢这类任务的,因为您没有指定应该如何处理空格,这使得上述所有三个都可能无效,或者至少在技术上是困难的。
把潘乔分开...*
char sub[3][16]; sscanf("Pancho: Juanka,Cony", "%15[^:]: %15[^,],%15[^\n]", sub[0], sub[1], sub[2]);
【参考方案1】:
虽然strtok
会解决这个问题,但我相信它不会是一个非常可维护的解决方案。我打算指出使用strtok
的一些问题,以及这些问题的解决方案。
问题 #1:由于隐藏状态,strtok
不可重入且非线程安全;如果您尝试同时标记两个字符串(例如交织函数调用序列或使用多个线程),您会遇到问题。
解决方案 #1: 可以改用 strchr
和 strcspn
来解决此问题。我已经展示了使用strcspn
阅读其他答案中的行的能力1,2;这些可以很容易地改用strchr
,或使用'\n'
以外的字符。
问题 #2: strtok
、strchr
和 strcspn
都对需要中间数组存在的字符串进行操作。您正在从文件中读取;如果您不需要该中间数组,因为您可以将字段直接读入它们对应的数组中,那么消除它们可能会带来更高级的优化和更简洁、更易于维护的代码。
解决方案#2:以下代码demonstrates使用fscanf
直接从文件中执行拆分。
#include <stdio.h>
#define WIDTH_STR(width) #width
#define FIXED_FIELD(width) "%" WIDTH_STR(width)
#define TERMINAL(set) "[^" set "]%*1[" set "] "
#define W 1024
int parse(FILE *f)
char x[W+1], y[W+1], z[W+1];
if (fscanf(f, FIXED_FIELD(W) TERMINAL(":"), x) <= 0) return EOF;
if (fscanf(f, FIXED_FIELD(W) TERMINAL(","), y) <= 0) return EOF;
if (fscanf(f, FIXED_FIELD(W) TERMINAL("\n"), z) <= 0) return EOF;
printf("<%s>\n", x);
printf("<%s>\n", y);
printf("<%s>\n", z);
return 0;
int main(void)
printf("parse returned: %d\n", parse(stdin));
问题 #3: 当您假设字段为固定宽度时,上述所有解决方案都会达到最佳最优性(在可维护性/复杂性和计算效率方面)。一旦该假设失效,更有意义使用fgetc
一次读取和解析一个字节,并根据需要重新分配以适应可变字段。
解决方案#3: 我在another answer 中展示了读取可变长度单词的能力,这很容易适应读取单个标记并将其解析为单独的动态分配。这可能会遭受代价高昂的重新分配的缺点,即允许您的用户输入 巨大的(多兆字节)字段值,这些字段值通常不支持作为具有自动存储持续时间的固定宽度数组。
【讨论】:
以上是关于如何将文本文件中的一行的子字符串保存到字符串数组中?的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 将 JSON 数组保存到 SharedPreferences
如何使用“保存到..”对话框将字符串从 EditControl 写入 Visual Studio 2008 中的文本文件?