使用以下行给出文件:
word1 word2 word3 word4
我试图编写以下代码:
Exit status is 4
用于打印“单词”。
正在工作。但是,我什么都不懂。
最后一个单词FILE* f = fopen("my_file.txt", "r");
char line[MAX_BUFFER + 1];
if (fgets(line, MAX_LENGTH_LINE, f) == NULL) {
return NULL;
}
char* word = strtok(line, " ");
for (int i = 0; i < 4; i++) {
printf("%s ", word);
word = strtok(NULL, " ");
}
的效果如何? (我不明白,因为在“ word4”之后不存在空格。)。
答案 0 :(得分:2)
我不太确定您要问什么。您是在问程序即使没有空格也能从文件中正确读取word4
吗?或者您是在问为什么,当程序退回打印word4
时,似乎没有在其后打印空格?
第一个问题的答案是strtok
旨在为您提供以由分隔符分隔的标记,而不是由以分隔符终止的标记。不需要在最后一个标记后跟定界符。
要查看第二个问题的答案,如果稍稍调整程序及其打印输出,可能会更清楚:
char* word = strtok(line, " ");
for (int i = 0; word != NULL; i++) {
printf("%d: \"%s\"\n", i, word);
word = strtok(NULL, " ");
}
我在这里做了两项更改:
word
为NULL为止,也就是说,只要strtok
在行上找到另一个单词。 (这是为了确保我们看到 all 个单词,并确保我们不试图以任何方式特别对待第四个单词。如果您 以某种方式特别对待第四个单词,请这样说。)运行修改后的程序时,我看到:
0: "word1"
1: "word2"
2: "word3"
3: "word4
"
最后一行最初看起来很奇怪,但是解释很简单。您最初使用fgets
读取该行,该行确实将终止的\n
字符复制到line
缓冲区中。因此,它最终停留在word4
上;也就是说,第四个“单词”是"word4\n"
。
基于这个原因,通常建议将\n
包含在您要交给strtok
的空白定界符中,也就是说,可以调用strtok(line, " \n")
。如果我这样做(在两个strtok
调用中),输出将更改为
0: "word1"
1: "word2"
2: "word3"
3: "word4"
可能更接近您的预期。
答案 1 :(得分:0)
您的代码不检查strtok()
的返回值,在某些情况下可能不安全。
/* Split string
@content origin string content
@delim delimiter for splitting
@psize pointer pointing at the variable to store token size
@return tokens after splitting
*/
const char **split(char *content, const char *delim, int *psize)
{
char *token;
const char **tokens;
int capacity;
int size = 0;
token = strtok(content, delim);
if (!token)
{
return NULL;
}
// Initialize tokens
tokens = malloc(sizeof(char *) * 64);
if (!tokens)
{
exit(-1);
}
capacity = 64;
tokens[size++] = token;
while ((token = strtok(NULL, delim)))
{
if (size >= capacity)
{
tokens = realloc(tokens, sizeof(char *) * capacity * 2);
if (!tokens)
{
exit(-1);
}
capacity *= 2;
}
tokens[size++] = token;
}
// if (size < capacity)
// {
// tokens = realloc(tokens, sizeof(char *) * size);
// if (!tokens)
// {
// exit(-1);
// }
// }
*psize = size;
return tokens;
}