【问题标题】:Splitting string into strings using strtok() not working使用 strtok() 将字符串拆分为字符串不起作用
【发布时间】:2016-12-22 21:51:20
【问题描述】:

我在分隔传递给函数的字符串内容时遇到了问题。该函数使用如下字符串调用:

ADD:Nathaniel:50

其中 ADD 是协议名称,Nathaniel 是键,50 是值,都用 : 分隔。

我的代码如下所示:

bool add_to_list(char* buffer){

  char key[40];
  char value[40];
  int* token;

  char buffer_copy[1024];
  const char delim[2] = ":";

  strcpy(buffer_copy, buffer);

  token = strtok(NULL, delim);
  //strcpy(key, token);

  printf("%d",token);
  printf("%p",token);

  while(token != NULL){
    token = strtok (NULL, delim);
  }
  //strcpy(value, token);

  printf("%s", key);
  printf("%s", value);
  push(key, value);

  return true;
}

我要做的是使用strtok() 将每个键和值存储在一个单独的变量中。请注意,我试图存储第二个和第三个值(Nathaniel50)而不是第一位(ADD)。

当我运行代码时,它给了我一个分段错误,所以我猜我试图访问一个无效的内存地址而不是一个值。我只需要存储字符串的第二和第三位。有人可以帮忙吗?

编辑: 我已将代码更改为如下所示:

bool add_to_list(char* buffer){

char *key, *value, *token;

const char *delim = ":";

token = strtok(buffer, delim);

//printf("%d",token);
printf("%s",token);

key = strtok(NULL, delim);
value = strtok(NULL, delim);

printf("%s", key);
printf("%s", value);
//push(key, value);

return true;
}

但我仍然遇到相同的分段错误(核心转储)错误

【问题讨论】:

  • 您永远不会在keyvalue 中存储任何内容。
  • int* token; --> char *token;
  • const char[2] delim -> const char* delim
  • 看在上帝的份上,使用strsep 而不是糟糕的strtok

标签: c delimiter strtok


【解决方案1】:

第一次调用strtok() 需要提供要扫描的字符串。您只在重复调用中使用NULL,因此它将继续处理字符串的其余部分。所以第一个电话应该是:

token = strtok(buffer_copy, delim);

那么当你想要获取key和value的时候,你需要将它们复制到数组中:

token = strtok(NULL, delim);
key = strcpy(token);
token = strtok(NULL, delim);
value = strcpy(token);

您不需要循环,因为您只想提取这两个值。

其实keyvalue不需要声明为数组,可以使用指针:

char *key, *value;

那么你可以这样做:

token = strtok(buffer_copy, delim);
key = strtok(NULL, delim);
value = strtok(NULL, delim);

【讨论】:

  • 我收到一些关于以下方面的警告:警告:分配来自不兼容的指针类型 [-Wincompatible-pointer-types] token = strtok(buffer_copy, delim);这里发生了什么,有没有办法可以消除错误?
  • token 应该是 char*,而不是 int*
【解决方案2】:

你的主要问题是,当你第一次调用strtok时,第一个参数应该是你要解析的字符串,所以不是:

strcpy(buffer_copy, buffer);
token = strtok(NULL, delim);

但是

strcpy(buffer_copy, buffer);
token = strtok(buffer_copy, delim);

此外,当您在 while 循环中检测到令牌时,您会将它们扔掉。你想在那个时候做点什么(或者只是展开循环并调用strtok 三次)。

还有:

const char* delim = ":";

将是一种更传统的方式来确保NUL 终止的字符串比:

const char delim[2] = ":";

还可以考虑使用strtok_r 而不是strtok,因为strtok 不是线程安全且可怕的。虽然您在这里没有使用线程(似乎),但您不妨进入良好的实践。

【讨论】:

  • 你能解释一下如何使用strtok_r函数吗?我正在尝试查找有关它的信息,但我发现它很难理解。另外,我的系统就像一个小型服务器,所以我会有多个线程,因此我对使用安全版本很感兴趣,加上它的良好道德
  • Re strtok_r,手册页是一个有用的资源,但这是你应该做的。对于您想要执行的每个字符串标记化(即此处示例中的一次),在第一次使用之前添加char *save=NULL;(从技术上讲,初始化是可选的),然后将&save 作为附加参数添加到每次使用strtok该标记化,并将strtok 更改为strtok_r。这意味着strtok_r 将在调用之间将其状态存储在save 而不是内部静态缓冲区中,因此您具有线程安全性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
相关资源
最近更新 更多