[英]splitting string and counting tokens in c
我有一個文本文件,其中包含多個不同長度的字符串,我需要將這些字符串拆分為標記。 最好使用strtok
來拆分這些字符串以及如何計算令牌?
文件中的字符串示例
Emma Stone#1169876#COMP242#COMP333#COMP336#COMP133#COMP231
Emma Watson#1169875#COMP336#COMP2421#COMP231#COMP338#CCOMP3351
Kevin Hart#1146542#COMP142#COMP242#COMP231#COMP336#COMP331#COMP334
George Clooney#1164561#COMP336#COMP2421#COMP231#COMP338#CCOMP3351
Matt Damon#1118764#COMP439#COMP4232#COMP422#COMP311#COMP338
Johnny Depp#1019876#COMP311#COMP242#COMP233#COMP3431#COMP333#COMP432
一般來說,使用strtok
是一個很好的解決問題的方法:
#include <stdio.h>
#include <string.h>
int main( void )
{
char line[] =
"Emma Stone#1169876#COMP242#COMP333#COMP336#COMP133#COMP231";
char *p;
int num_tokens = 0;
p = strtok( line, "#" );
while ( p != NULL )
{
num_tokens++;
printf( "Token #%d: %s\n", num_tokens, p );
p = strtok( NULL, "#" );
}
}
該程序具有以下輸出:
Token #1: Emma Stone
Token #2: 1169876
Token #3: COMP242
Token #4: COMP333
Token #5: COMP336
Token #6: COMP133
Token #7: COMP231
但是,使用strtok
一個缺點是它具有破壞性,因為它通過用終止空字符替換#
分隔符來修改字符串。 如果你不想要這個,那么你可以使用strchr
代替:
#include <stdio.h>
#include <string.h>
int main( void )
{
const char *const line =
"Emma Stone#1169876#COMP242#COMP333#COMP336#COMP133#COMP231";
const char *p = line, *q;
int num_tokens = 1;
while ( ( q = strchr( p, '#' ) ) != NULL )
{
printf( "Token #%d: %.*s\n", num_tokens, q-p, p );
num_tokens++;
p = q + 1;
}
printf( "Token #%d: %s\n", num_tokens, p );
}
這個程序與第一個程序有相同的輸出:
Token #1: Emma Stone
Token #2: 1169876
Token #3: COMP242
Token #4: COMP333
Token #5: COMP336
Token #6: COMP133
Token #7: COMP231
strtok
另一個缺點是它不是可重入或線程安全的,而strchr
是。 然而,一些平台提供了一個函數strtok_r
,它沒有這些缺點。 但該功能仍然具有破壞性的缺點。
是的,您應該使用strtok
來拆分這些字符串。
在
我如何計算令牌
您可以簡單地在while
內添加一個計數器while
並在每次迭代中將其遞增 1 以獲得令牌總數。
#include <stdio.h>
#include <string.h>
int main(void) {
char string[] = "Hello world this is a simple string";
char *token = strtok(string, " ");
int count = 0;
while (token != NULL) {
count++;
token = strtok(NULL, " ");
}
printf("Total number of tokens = %d", count);
return 0;
}
您還可以編寫自己的函數來處理這個非常瑣碎的拆分:
char **split(char *str, char **argv, size_t *argc, const char delim)
{
*argc = 0;
if(*str && *str)
{
argv[0] = str;
*argc = 1;
while(*str)
{
if(*str == delim)
{
*str = 0;
str++;
if(*str)
{
argv[*argc] = str;
*argc += 1;
continue;
}
}
str++;
}
}
return argv;
}
int main(void)
{
char *argv[10];
size_t argc;
char str[] = "Emma Stone#1169876#COMP242#COMP333#COMP336#COMP133#COMP231";
split(str, argv, &argc, '#');
printf("Numner of substrings: %zu\n", argc);
for(size_t i = 0; i < argc; i++)
printf("token [%2zu] = `%s`\n", i, argv[i]);
}
https://godbolt.org/z/b1aarnfWs
備注:與 strtok 相同,它需要str
對我來說是可修改的。 str
將被修改。
strtok()
很少是適合任何事情的工具。 在這種情況下,目前還不清楚的序列是否##
相當於一個#
以及是否#
出現在開頭或線的一端可忽略不計...
strtok()
對這些可能不是預期行為的情況做出了強有力的假設。
此外, strtok()
修改其字符串參數並使用隱藏的靜態狀態,這使其在多線程程序中不安全,並且在嵌套用例中容易出現編程錯誤。 strtok_r()
在可用的情況下解決了這些問題,但語義仍然有些違反直覺。
為了您的目的,您必須精確定義什么是標記和分隔符。 如果允許空標記, strtok()
絕對不是解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.