如何在不使用 strtok 的情况下根据特定字符拆分字符串
How to split String based on specific character without using strok
我能够在不使用 strok 函数的情况下基于 space 拆分字符串缓冲区。
因为我担心 = 符号后的值,所以我如何也可以根据 = 符号再次溢出 sring。
所以逻辑是:
根据 space 将字符串拆分为标记 --> 完成
然后根据 = 拆分每个标记并避免使用 strok--> issue here
登录到新缓冲区后最终只存储数字
int TokenizeString(char * s_String, char s_Token[][25], char c_Delimiter);
int main(void) {
char buf[] = "abc=3000 Xyz=27.3 rb2act=11.82 ";
//1.tokenizes each string without using strok
char s_Token[15][25];
memset(s_Token, 0, 200);
int count = TokenizeString(buf, s_Token, ' ');
int i;
printf("Step 1 : Split the string \n");
for (i = 0; i <= count; i++) {
printf("%s \n", s_Token[i]);
// here is the issue , i need to store the result and spilt it again based on the = sign , i am concern about value after = sign
}
return EXIT_SUCCESS;
}
// Function to tokize the string without using strtok
int TokenizeString(char * s_String, char s_Token[][25], char c_Delimiter) {
int j = 0;
unsigned int i_Offset = 0;
char b_Flag = 0;
int count = 0;
for (i_Offset = 0; i_Offset <= strlen(s_String); i_Offset++) {
if (s_String[i_Offset] != c_Delimiter && s_String[i_Offset] != '\t' && s_String[i_Offset] != '\n' && s_String[i_Offset] != '[=10=]') {
s_Token[count][j] = s_String[i_Offset];
j++;
b_Flag = 1;
continue;
}
if (b_Flag) {
s_Token[count][j] = '[=10=]';
count++;
j = 0;
b_Flag = 0;
}
}
return (count - 1);
}
我想你需要的是在每个 =
之后获取这些数字作为字符串并将它们存储在 s_Tokens
.
中
如果是这样,你可以做到
char buf[]="abc=3000 Xyz=27.3 rb2act=11.82 ";
char *ptr=buf;
char s_Token[15][25];
int i;
for(i=0; (ptr=strchr(ptr, '='))!=NULL; )
{
sscanf(++ptr, "%24s", s_Token[i++]);
}
虽然你应该准备错误检查。
输出为:
3000
27.3
11.82
strchr()
returns 指向字符串中某个字符第一次出现的指针。如果找不到该字符,则 returns NULL
.
可以使用 strspn
和 strcspn
将字符串拆分为空格,并将标记存储到动态分配的指针中。
不确定每个标记的两个部分要做什么,所以这显示了标记,等于之前的部分和等于之后的双精度。 strcspn
用于查找令牌中的相等,strtod
用于解析双精度。如果这两部分需要存储在内存中,结构数组可能比指针更值得研究。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **tokenize ( char *string, char delimiter);
char **freetokens ( char **tokens);
int main ( void) {
char buf[] = " abc=3000 Xyz=27.3 rb2act=11.82 ";
char **tokens = NULL;
char *last = NULL;
size_t each = 0;
size_t equal = 0;
double value = 0.0;
tokens = tokenize ( buf, ' ');
if ( tokens) {
each = 0;
while ( tokens[each]) {
if ( ( equal = strcspn ( tokens[each], "="))) {//look for the = ( except for = in index [0])
if ( equal < strlen ( tokens[each])) {//found an =
value = strtod ( tokens[each] + equal + 1, &last);//parse for a double
if ( last != tokens[each] + equal + 1 && *last == '[=10=]') {//able to parse a double
printf ( "token\t %s\n", tokens[each]);//show the string
printf ( "up to =\t %.*s\n", equal, tokens[each]);//show the token up to the =
printf ( "double\t %f\n\n", value);//show the double
}
else {
printf ( "%s bad token\n\n", tokens[each]);
}
}
else {
printf ( "%s bad token\n\n", tokens[each]);
}
}
else {
printf ( "%s bad token\n\n", tokens[each]);
}
each++;
}
tokens = freetokens ( tokens);
}
return 0;
}
char **freetokens ( char **tokens) {
size_t each = 0;
if ( tokens) {
while ( tokens[each]) {
free ( tokens[each]);
each++;
}
free ( tokens);
}
return NULL;
}
char **tokenize ( char *string, char delimiter) {
char **lines = NULL;
char **temp = NULL;
char limit[2] = "";
size_t skip = 0;
size_t span = 0;
size_t extent = 0;
size_t line = 0;
size_t len = strlen ( string);
limit[0] = delimiter;
if ( NULL == ( lines = malloc ( sizeof ( *lines) * 2))) {//allocate two pointers
fprintf ( stderr, "malloc problem\n");
return NULL;
}
lines[line + 1] = NULL;//sentinel
while ( extent < len) {
skip = strspn ( string + extent, limit);//get number of delimiters
extent += skip;//advance past spaces
if ( ( span = strcspn ( string + extent, limit))) {//find next delimiter or '[=10=]'
if ( NULL == ( lines[line] = malloc ( span + 1))) {
fprintf ( stderr, "malloc problem\n");
return lines;
}
strncpy ( lines[line], string + extent, span);
lines[line][span] = '[=10=]';
if ( NULL == ( temp = realloc ( lines, sizeof ( *lines) * ( line + 3)))) {
fprintf ( stderr, "realloc problem\n");
return lines;
}
lines = temp;
line++;
lines[line] = NULL;
lines[line + 1] = NULL;//sentinel
extent += span;//advance past the token
}
}//loop to end of string
return lines;
}
我能够在不使用 strok 函数的情况下基于 space 拆分字符串缓冲区。
因为我担心 = 符号后的值,所以我如何也可以根据 = 符号再次溢出 sring。
所以逻辑是: 根据 space 将字符串拆分为标记 --> 完成 然后根据 = 拆分每个标记并避免使用 strok--> issue here 登录到新缓冲区后最终只存储数字
int TokenizeString(char * s_String, char s_Token[][25], char c_Delimiter);
int main(void) {
char buf[] = "abc=3000 Xyz=27.3 rb2act=11.82 ";
//1.tokenizes each string without using strok
char s_Token[15][25];
memset(s_Token, 0, 200);
int count = TokenizeString(buf, s_Token, ' ');
int i;
printf("Step 1 : Split the string \n");
for (i = 0; i <= count; i++) {
printf("%s \n", s_Token[i]);
// here is the issue , i need to store the result and spilt it again based on the = sign , i am concern about value after = sign
}
return EXIT_SUCCESS;
}
// Function to tokize the string without using strtok
int TokenizeString(char * s_String, char s_Token[][25], char c_Delimiter) {
int j = 0;
unsigned int i_Offset = 0;
char b_Flag = 0;
int count = 0;
for (i_Offset = 0; i_Offset <= strlen(s_String); i_Offset++) {
if (s_String[i_Offset] != c_Delimiter && s_String[i_Offset] != '\t' && s_String[i_Offset] != '\n' && s_String[i_Offset] != '[=10=]') {
s_Token[count][j] = s_String[i_Offset];
j++;
b_Flag = 1;
continue;
}
if (b_Flag) {
s_Token[count][j] = '[=10=]';
count++;
j = 0;
b_Flag = 0;
}
}
return (count - 1);
}
我想你需要的是在每个 =
之后获取这些数字作为字符串并将它们存储在 s_Tokens
.
如果是这样,你可以做到
char buf[]="abc=3000 Xyz=27.3 rb2act=11.82 ";
char *ptr=buf;
char s_Token[15][25];
int i;
for(i=0; (ptr=strchr(ptr, '='))!=NULL; )
{
sscanf(++ptr, "%24s", s_Token[i++]);
}
虽然你应该准备错误检查。
输出为:
3000
27.3
11.82
strchr()
returns 指向字符串中某个字符第一次出现的指针。如果找不到该字符,则 returns NULL
.
可以使用 strspn
和 strcspn
将字符串拆分为空格,并将标记存储到动态分配的指针中。
不确定每个标记的两个部分要做什么,所以这显示了标记,等于之前的部分和等于之后的双精度。 strcspn
用于查找令牌中的相等,strtod
用于解析双精度。如果这两部分需要存储在内存中,结构数组可能比指针更值得研究。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **tokenize ( char *string, char delimiter);
char **freetokens ( char **tokens);
int main ( void) {
char buf[] = " abc=3000 Xyz=27.3 rb2act=11.82 ";
char **tokens = NULL;
char *last = NULL;
size_t each = 0;
size_t equal = 0;
double value = 0.0;
tokens = tokenize ( buf, ' ');
if ( tokens) {
each = 0;
while ( tokens[each]) {
if ( ( equal = strcspn ( tokens[each], "="))) {//look for the = ( except for = in index [0])
if ( equal < strlen ( tokens[each])) {//found an =
value = strtod ( tokens[each] + equal + 1, &last);//parse for a double
if ( last != tokens[each] + equal + 1 && *last == '[=10=]') {//able to parse a double
printf ( "token\t %s\n", tokens[each]);//show the string
printf ( "up to =\t %.*s\n", equal, tokens[each]);//show the token up to the =
printf ( "double\t %f\n\n", value);//show the double
}
else {
printf ( "%s bad token\n\n", tokens[each]);
}
}
else {
printf ( "%s bad token\n\n", tokens[each]);
}
}
else {
printf ( "%s bad token\n\n", tokens[each]);
}
each++;
}
tokens = freetokens ( tokens);
}
return 0;
}
char **freetokens ( char **tokens) {
size_t each = 0;
if ( tokens) {
while ( tokens[each]) {
free ( tokens[each]);
each++;
}
free ( tokens);
}
return NULL;
}
char **tokenize ( char *string, char delimiter) {
char **lines = NULL;
char **temp = NULL;
char limit[2] = "";
size_t skip = 0;
size_t span = 0;
size_t extent = 0;
size_t line = 0;
size_t len = strlen ( string);
limit[0] = delimiter;
if ( NULL == ( lines = malloc ( sizeof ( *lines) * 2))) {//allocate two pointers
fprintf ( stderr, "malloc problem\n");
return NULL;
}
lines[line + 1] = NULL;//sentinel
while ( extent < len) {
skip = strspn ( string + extent, limit);//get number of delimiters
extent += skip;//advance past spaces
if ( ( span = strcspn ( string + extent, limit))) {//find next delimiter or '[=10=]'
if ( NULL == ( lines[line] = malloc ( span + 1))) {
fprintf ( stderr, "malloc problem\n");
return lines;
}
strncpy ( lines[line], string + extent, span);
lines[line][span] = '[=10=]';
if ( NULL == ( temp = realloc ( lines, sizeof ( *lines) * ( line + 3)))) {
fprintf ( stderr, "realloc problem\n");
return lines;
}
lines = temp;
line++;
lines[line] = NULL;
lines[line + 1] = NULL;//sentinel
extent += span;//advance past the token
}
}//loop to end of string
return lines;
}