我有一个字符串想分成两个不同的字符串,定界符是 $$$
.例如,在左边是产品名称,右边是其数量。milk $$$ 45
左边是产品名称,右边是数量。我曾用过 strtok
来拆分字符串,但很遗憾,我无法提取数字。
int num;
char *token = strtok(str, DELIMITER);
printf("%s\n", token);
strcpy(component->name, token);
char *number = strtok(NULL, " ");
num = atoi(number);
printf("%s\n", number);
该 printf
调用是为了调试。
我没有调试你的代码,但用 strtok_r()
其更好、更直观。C语言提供了两个函数 strtok()
和 strtok_r()
用于用定界符分割一个字符串。
strtok_r()
就像 strtok()
C中的函数。strtok_r()
做同样的工作,将一个字符串解析成一个标记序列。strtok_r()
是一个 reentrant
strtok()的版本
功能签名
char *strtok_r(char *str, const char *delim, char **saveptr);
第三个论点 saveptr
是一个指向 char *
变量,在内部被 strtok_r()
以便在解析同一字符串的连续调用之间保持上下文。
#include <stdio.h>
#include <string.h> /*for the strtok function*/
#include <ctype.h> /*for the isalpha function*/
int main()
{
/*assume your string is a raw string just like the one bellow. and if its not.
please modify the code.
*/
char str[80] = "milk $$$ 45 meat $$$ 89 water $$$ 12";
const char* delim = " $$$ ";
char* token = NULL;
char* rest = str;
int num;
while ((token = strtok_r(rest, " $$$ ", &rest)))
{
/*if its a number we will convert it to integer number*/
if (!isalpha(token[0]))
{
num = atoi(token);
printf("The price is: %d\n",num);
}
/*else it is a string*/
printf("The prodact name is: %s\n", token);
}
return 0;
}
问题是,你从这样的字符串开始(字符串中的空白对参数没有实质性影响)。
milk$$$45
假设 DELIMITER
是 "$"
(重复美元符号) "$$$"
不会让它看起来有多个 $
迹象),那么在这之后,你有。
milk\0$$45
在第二个搜索 strtok()
剩余的第一个人继续 $
. 它隔离了令牌 $$45
没有空格。 如果在数字前有一个空格,那么它就会将令牌隔离起来 $$
而不是。) 当你通过 $$45
到 atoi()
,它的评价是 0
. 你可以通过 printf("[[%s]]\n", number);
.
你也许应该用以下方法来解决这个问题。
char *number = strtok(NULL, " \t$");
这将跳过前导空格,标签。$
字符,然后停止在下一个字符(或字符串末尾的空字节)。 请注意,这段代码并没有确保有3个 $
符号来分隔名称和数字。
你想把输入的字符串拆分在一个定界符串上 $$$
: strtok()
不是一个精确的解决方案,因为它不搜索定界符字符串,而是将定界符字符串中的任何字符序列视为定界符。传递 "$$$"
相当于只通过 "$"
.由于第二次调用使用了不同的定界符集(空格),所以 strtok()
将返回 $$
作为第二个代币,所以你得到 0
改装后 atoi()
.
有不同的方法来解决这个问题。
使用 "$"
或 "$ \t"
作为第二次调用的定界符。strtok()
. 这是很草率的,但在你的情况下会有效,因为第二个字段不包含嵌入的空格和 atoi
忽略前导空格。
int num;
char *token = strtok(str, "$");
if (token) {
printf("%s\n", token);
strcpy(component->name, token);
char *number = strtok(NULL, "$");
if (number) {
num = atoi(number);
printf("%s\n", number);
}
}
使用 strstr
来定位定界符字符串,并跳过它来获取第二部分。
int num;
char *token = str;
char *p = strstr(str, "$$$");
if (p) {
p = '\0';
p += 3;
}
printf("%s\n", token);
strcpy(component->name, token);
char *number = p;
if (number) {
num = atoi(number);
printf("%s\n", number);
}
写一个自定义的函数来分割定界符上的字符串, 并且为了一致性而修剪白色空间:
#include <string.h>
#include <ctype.h>
char *trim_token(char *str) {
if (str) {
size_t len = strlen(str);
while (len > 0 && isspace((unsigned char)str[-1])
str[--len] = '\0';
while (isspace((unsigned char)str[0])
str++;
}
return str;
}
char *get_token(char *str, const char *delim, char **context) {
if (!str)
str = context;
if (!str)
return NULL; // no more tokens
char *p = strstr(str, delim);
if (p) {
*p = '\0';
p += strlen(delim);
}
*context = p;
// trimming starting and trailing white space from the token is
// a good idea, just return str to preserve these spaces.
return trim_token(str);
}
并这样使用。
int num;
char *context;
char *token = get_token(str, "$$$", &context);
if (token) {
printf("%s\n", token);
strcpy(component->name, token);
}
char *number = get_token(NULL, "$$$", &context);
if (number) {
num = atoi(number);
printf("%s\n", number);
}