簡體   English   中英

為什么 strtok 采用 char* 而不是 const char*?

[英]Why strtok takes a char* and not a const char*?

據我所知, strtok()不會修改底層字符串,那么為什么不使用 const char*指針而不是const char*指針呢? 此外,在標記化時,您不希望字符串更改,對嗎?

更新: https ://godbolt.org/z/3SPvRB 很明顯 strtok() 確實修改了底層字符串。 非變異標記器的替代方案是什么?

但是strtok確實會更改字符串。

取以下代碼:

char sz[] = "The quick brown fox";
char* token = strtok(sz, " ");

它會將數組的內容更改為:

"The\0quick brown fox";

第一個發現的分隔符被替換為空字符。 在內部(通過線程本地存儲或全局變量),指向發現的分隔符之后的下一個字符的指針被存儲,以便隨后對strtok(NULL, " ")調用將從原始字符串中解析下一個標記。

它確實修改了底層字符串。 請參閱: http : //www.cplusplus.com/reference/cstring/strtok/

標記的這一結尾會自動替換為空字符,並且標記開頭由函數返回。

證明:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }

  /* note this line... */
  printf ("str = \"%s\"\n",str);
  return 0;
}

印刷:

Splitting string "- This, a sample string." into tokens:
This
a
sample
string
str = "- This"

更新: https : strtok()很明顯strtok()確實修改了底層字符串。 非變異標記器的替代方案是什么?

如評論中所述,您可以:

  1. 制作原始字符串的副本,然后使用strtok()標記副本; 或者
  2. 編寫自己的實現,將令牌括起來並將令牌復制到新存儲:
    • 使用 C strspn向前掃描到第一個非分隔符字符,這將是令牌的開頭,然后使用strcspn向前掃描到標記令牌結尾的下一個分隔符,
    • 用一對指針手動做同樣的事情; 或者
    • 對於 C++11 或更高版本,您可以使用.find_first_not_of()向前掃描到第一個非分隔符字符,然后使用.find_first_of()來定位標記.find_first_of()的分隔符。

在每種情況下,您都將把標記字符復制到一個新字符串(使用memcpy進行 C 類型實現——不要忘記nul-terminate )或 C++11 只需使用.substr()成員函數。

一個非常基本的 C++11 實現看起來類似於:

std::vector<std::string> stringtok (const std::string& s, const std::string& delim)
{
    std::vector<std::string> v {};  /* vector of strings for tokens */
    size_t beg = 0, end = 0;        /* begin and end positons in str */

    /* while non-delimiter char found */
    while ((beg = s.find_first_not_of (delim, end)) != std::string::npos) {
        end = s.find_first_of (delim, beg);       /* find delim after non-delim */
        v.push_back (s.substr (beg, end - beg));  /* add substr to vector */
        if (end == std::string::npos)             /* if last delim, break */
            break;
    }

    return v;   /* return vector of tokens */
}

如果您遵循邏輯,它會准確跟蹤函數定義上面描述的內容。 將其組合成一個簡短的示例,您將擁有:

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> stringtok (const std::string& s, const std::string& delim)
{
    std::vector<std::string> v {};  /* vector of strings for tokens */
    size_t beg = 0, end = 0;        /* begin and end positons in str */

    /* while non-delimiter char found */
    while ((beg = s.find_first_not_of (delim, end)) != std::string::npos) {
        end = s.find_first_of (delim, beg);       /* find delim after non-delim */
        v.push_back (s.substr (beg, end - beg));  /* add substr to vector */
        if (end == std::string::npos)             /* if last delim, break */
            break;
    }

    return v;   /* return vector of tokens */
}

int main (void) {

    std::string str = "    my           dog   has    fleas      ",
                delim = " ";
    std::vector<std::string> tokens;

    tokens = stringtok (str, delim);

    std::cout << "string: '" << str << "'\ntokens:\n";
    for (auto s : tokens)
        std::cout << "  " << s << '\n';
}

示例使用/輸出

$ ./bin/stringtok
string: '    my           dog   has    fleas      '
tokens:
  my
  dog
  has
  fleas

注意:這只是實現不修改原始字符串標記化的眾多方法之一。 仔細檢查一下,如果您還有其他問題,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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