gpt4 book ai didi

c - strdup 和 strtok 导致的段错误

转载 作者:太空宇宙 更新时间:2023-11-04 02:33:40 25 4
gpt4 key购买 nike

我的大学教授给我布置了作业,我似乎发现了 strtok 的一些奇怪行为

基本上,我们必须为我的类解析一个 CSV 文件,其中 CSV 中的标记数量是已知的,最后一个元素可能有额外的 "," 字符。

一行的例子:

Hello,World,This,Is,A lot, of Text

token 应输出为

1. Hello
2. World
3. This
4. Is
5. A lot, of Text

对于这个作业,我们必须使用strtok。因此,我在其他一些 SOF 帖子中发现,使用带有空字符串的 strtok(或将 "\n" 作为第二个参数传递)导致读取直到结束线。这非常适合我的应用程序,因为额外的逗号总是出现在最后一个元素中。

我已经创建了这段有效的代码:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define NUM_TOKENS 5

const char *line = "Hello,World,This,Is,Text";

char **split_line(const char *line, int num_tokens)
{
char *copy = strdup(line);

// Make an array the correct size to hold num_tokens
char **tokens = (char**) malloc(sizeof(char*) * num_tokens);

int i = 0;
for (char *token = strtok(copy, ",\n"); i < NUM_TOKENS; token = strtok(NULL, i < NUM_TOKENS - 1 ? ",\n" : "\n"))
{
tokens[i++] = strdup(token);
}

free(copy);

return tokens;
}

int main()
{
char **tokens = split_line(line, NUM_TOKENS);

for (int i = 0; i < NUM_TOKENS; i++)
{
printf("%s\n", tokens[i]);
free(tokens[i]);
}
}

现在这行得通并且应该让我得到充分的信任,但我讨厌这个不应该需要的三元组:

token = strtok(NULL, i < NUM_TOKENS - 1 ? ",\n" : "\n");

我想用这个版本替换方法:

char **split_line(const char *line, int num_tokens)
{
char *copy = strdup(line);

// Make an array the correct size to hold num_tokens
char **tokens = (char**) malloc(sizeof(char*) * num_tokens);

int i = 0;
for (char *token = strtok(copy, ",\n"); i < NUM_TOKENS - 1; token = strtok(NULL, ",\n"))
{
tokens[i++] = strdup(token);
}

tokens[i] = strdup(strtok(NULL, "\n"));

free(copy);

return tokens;
}

这更能激发我的幻想,因为更容易看出存在最终情况。您还摆脱了奇怪的三元运算符。

遗憾的是,这是段错误!我这辈子都想不通为什么。

编辑:添加一些输出示例:

[11:56:06] gravypod:test git:(master*) $ ./test_no_fault 
Hello
World
This
Is
Text
[11:56:10] gravypod:test git:(master*) $ ./test_seg_fault
[1] 3718 segmentation fault (core dumped) ./test_seg_fault
[11:56:14] gravypod:test git:(master*) $

最佳答案

在将 NULL 传递给另一个函数之前,请检查 strtok 的返回值。您的循环调用 strtok 的次数比您想象的要多。

更常见的是使用这个返回值来控制你的循环,这样你就不会受数据的支配。至于分隔符,最好保持简单,不要尝试任何花哨的东西。

char **split_line(const char *line, int num_tokens)
{
char *copy = strdup(line);
char **tokens = (char**) malloc(sizeof(char*) * num_tokens);
int i = 0;
char *token;
char delim1[] = ",\r\n";
char delim2[] = "\r\n";
char *delim = delim1; // start with a comma in the delimiter set

token = strtok(copy, delim);
while(token != NULL) { // strtok result comtrols the loop
tokens[i++] = strdup(token);
if(i == NUM_TOKENS) {
delim = delim2; // change the delimiters
}
token = strtok(NULL, delim);
}
free(copy);
return tokens;
}

请注意,您还应该检查 mallocstrdup 的返回值并正确释放内存

关于c - strdup 和 strtok 导致的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40222582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com