簡體   English   中英

在 c 中拆分字符串和計數標記

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM