【问题标题】:How do I find the size of a char array?如何找到 char 数组的大小?
【发布时间】:2020-08-06 17:49:57
【问题描述】:

我应该如何在 C++ 中查找 char 数组的长度?我已经尝试了两种方法,但它们都导致数组中的字符数错误。到目前为止,我已经使用了 strlensizeof 运算符,但无济于事。

void countOccurences(char *str, string word)
{
    char *p;
    string t = "true";
    string f = "false";

    vector<string> a;

    p = strtok(str, " ");
    while (p != NULL)
    {
        a.push_back(p);
        p = strtok(NULL, " ");
    }

    int c = 0;
    for (int i = 0; i < a.size(); i++)
    {
        if (word == a[i])
        {
            c++;
        }
    }

    int length = sizeof(str); //This is where I'm having the problem
    string result;
    cout << length << "\n";

    if (length % 2 != 0)
    {
        if (c % 2 == 0)
        {
            result = "False";
        }
        else
        {
            result = "True";
        }
    }
    else
    {
        if (c % 2 == 0)
        {
            result = "True";
        }
        else
        {
            result = "False";
        }
    }

    if (strlen(str) != 0)
    {
        cout << result;
    }
}

int boolean()
{
    char str[1000];
    cin.getline(str, sizeof(str));
    string word = "not";
    countOccurences(str, word);
    return 0;
}

【问题讨论】:

  • 字符数组还是 C 字符串?它们是有区别的。如果 C 字符串和 strlen() 不起作用,那么您已经搞砸了。如果您丢失了常规数组的大小,那么您已经搞砸了。
  • @sweenish 我说的是 char 数组。
  • strtok 修改字符串。您期望获得什么价值?不再存在的原始字符串的大小?
  • std::size() 可以告诉你数组的大小如果它没有衰减到只是一个指针。顺便提一句;为什么你首先使用 C 风格的数组而不是 std::vectorstd::array
  • 你想在“countOccurences”中做什么?

标签: c++ arrays char sizeof


【解决方案1】:

sizeof(str) 是错误的。它为您提供指针的大小(str 是一个指针),它是一个固定数字,通常是 48,具体取决于您的平台。

std::strlen(str) 是正确的, strtok 在您尝试获取大小之前 将一堆\0 插入到您的数组中。 strlen 将在第一个 \0 处停止,并为您提供它前面的字符数。

strtok 之前调用strlen 并将其返回值保存到变量中。

【讨论】:

  • 你是对的 - 但无论如何使用 c 风格的字符串/数组是不好的。你应该避免这种情况。仅使用这些函数:en.cppreference.com/w/cpp/string/basic_string/getline。此外,您不应使用 strtok。 std::string_view 更快更安全。
  • @Bernd 在 c++ 中使用 c 风格的字符串/数组是否不好是有原因的吗?我对这门语言比较陌生,到目前为止我还没有遇到很多问题。
  • 是的,因为 c 字符串只是指向某些数据的指针。您丢失了字符串结尾的信息。这是在最后一个“零”的 C 字符串中处理的。 strtok 只是为了 C 兼容性。这个函数的问题是它修改了数据。好的,你可以在标记之前复制它......但是有更聪明的解决方案(如果你喜欢我可以发布一些东西)
【解决方案2】:

Here你可以找到现代c++解决方案:

#include <iostream>
#include <string_view>
#include <string>
#include <type_traits>

template<typename String>
inline std::size_t StrLength(String&& str)
{
    using PureString = std::remove_reference_t<std::remove_const_t<String>>;
    if constexpr(std::is_same_v<char, PureString>){
        return 1;
    }
    else 
    if constexpr(std::is_same_v<char*, PureString>){
        return strlen(str);
    }
    else{
        return str.length();
    }
}

template<
    typename String,
    typename Lambda,
    typename Delim = char
>
void ForEachWord(String&& str, Lambda&& lambda, Delim&& delim = ' ')
{
    using PureStr = std::remove_reference_t<std::remove_reference_t<String>>;
    using View = std::basic_string_view<typename PureStr::value_type>;

    auto start = 0;
    auto view = View(str);

    while(true)
    {
        auto wordEndPos = view.find_first_of(delim, start);
        auto word =  view.substr(start, wordEndPos-start);

        if (word.length() > 0){
            lambda(word);
        }
        
        if (wordEndPos == PureStr::npos)
        {
            break;
        }
        start = wordEndPos + StrLength(delim);
    }
}

int main() {
   std::string text = "This is not a good sentence.";
   auto cnt = 0;
   ForEachWord(
       text, 
       [&](auto word)
       {
          //some code for every word... like counting or printing
          if (word == "not" ){
             ++cnt;
          }
       },
       ' '
   );
   std::cout << cnt << "\n";
}

【讨论】:

    【解决方案3】:

    “字符串结尾”是 char '\0' 检查该字符以停止搜索。

    【讨论】:

      猜你喜欢
      • 2021-06-07
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 2018-04-14
      • 2014-09-13
      • 1970-01-01
      • 1970-01-01
      • 2013-11-30
      相关资源
      最近更新 更多