如何在C++中找到一个字符串数组中元素的数量?

5

我有一个字符串数组。

std::string str[10] = {"one","two"}

如何查找 str[] 数组中有多少个字符串?是否有标准函数可用?

(注:原文已经是英文,无需翻译。)

你的意思是非空、非空字符串吗?不是。 - Steve Wellens
你可以这么说...因为现在只有2个字符串。 - SPB
你可以在运行时找到它。请见下面我的回答。我想知道它是否可以在编译时发生。 - iammilind
8个回答

7

尽管您仅初始化了其中两个字符串,但是其中有十个字符串:

#include <iostream>
int main (void) {
    std::string str[10] = {"one","two"};
    std::cout << sizeof(str)/sizeof(*str) << std::endl;
    std::cout << str[0] << std::endl;
    std::cout << str[1] << std::endl;
    std::cout << str[2] << std::endl;
    std::cout << "===" << std::endl;
    return 0;
}

输出结果如下:
10
one
two

===

如果您想计算非空字符串:
#include <iostream>
int main (void) {
    std::string str[10] = {"one","two"};
    size_t count = 0;
    for (size_t i = 0; i < sizeof(str)/sizeof(*str); i++)
        if (str[i] != "")
            count++;
    std::cout << count << std::endl;
    return 0;
}

这将如预期地输出2


是的,没错。但当我运行一个循环时,如何知道我只需要循环两次? - SPB
你需要将元素与“null”字符串进行比较,这时你就可以停止循环了。 - OneDeveloper
不要只运行一次。运行10次并跳过底层字符串为空的情况。 - paxdiablo
抱歉,伙计。有三个问题。1. 为什么要不断地计算字符串中的元素数量? 第二个问题是,如果有一千万个元素,那么它的时间复杂度是O(N)。真的吗? 最后一个问题是,为什么不返回size_t类型?你的代码很容易超出范围。计数应该与for-iterator的类型相同。 - baash05
@baash05: (1) 如果你愿意,你可以手动缓存它,但是,除非你的编译器完全傻掉了,否则它已经在做这个了。(2) 没关系。除非你确定所有的空字符串都在末尾,否则你必须查看每个索引。如果你知道这个事实,你可以进行二分查找,但我可能会有一个不同的类来维护计数并在setter中进行调整(将非null更改为null -> count--,将null更改为非null -> count++)。(3) 是的,我错过了,会改变的。但是,如果你有那么多字符串,你比整数溢出还要麻烦 :-) - paxdiablo

6

如果你想计算所有元素,可以使用sizeof技术,就像其他人指出的那样。 如果你想计算所有非空字符串,这是一种可能的方法,可以使用标准的count_if函数。

bool IsNotEmpty( const std::string& str )
{
    return !str.empty();
}


int main ()
{
    std::string str[10] = {"one","two"};

    int result = std::count_if(str, &str[10], IsNotEmpty);
    cout << result << endl; // it will print "2"

    return 0;
 }

@baash05:如果您知道第一个空元素是用于分隔正在使用的值的,则可以使用find_if(..., IsEmpty) - Tony Delroy

2

我不确定我会使用std::string数组。如果您已经在使用STL,为什么不考虑使用vector或list呢?至少这样你可以直接使用std::vector::size()来计算大小而不必使用丑陋的sizeof技巧。而且,如果数组存储在堆上而不是栈上,那么这种sizeof技巧将无法工作。

只需要这样做:

std::vector<std::string> strings(10);
strings[0] = "one";
strings[1] = "two";

std::cout << "Length = " << strings.size() << std::endl;

但问题是要找到数组中的活动字符串。然而,使用vector<>来查找大小是一个很好的想法,非常直接。 - iammilind
啊,糟糕,得开始仔细阅读问题和评论了。他可以始终使用向量,将字符串推入向量中,然后只需使用 vector.size()。我不明白为什么他会有未激活的字符串,只要他 pop_back() 就好了。 - Andrew Rasmussen

0

对于一维字符串数组,只需使用此函数:

template<typename String, uint SIZE>  // String can be 'string' or 'const string'
unsigned int NoOfStrings (String (&arr)[SIZE])
{
  unsigned int count = 0;
  while(count < SIZE && arr[count] != "")
    count ++;
  return count;
}

使用方法:

std::string s1 = {"abc", "def" };
int i = NoOfStrings(s1);  // i = 2

我在想我们是否可以为此编写一个模板元程序!(因为所有内容都在编译时已知)


0

您可以始终使用countof宏来获取元素的数量,但是请注意,内存是为10个元素分配的,这也是您将获得的计数。


0

最理想的方法是这样做:

std::string str[] = {"one","two"}

int num_of_elements = sizeof( str ) / sizeof( str[ 0 ] );

他在构造函数中定义了数组的大小。因此,虽然您在这里的代码可以工作。 str [10](根据他的代码)将有10个字符串。 尽管有些是空的。 - baash05
这就是我的意思。你不需要一直提供数组长度。 - Priyank

0

因为你知道大小,你可以使用二分搜索找到非空的值。

str[9] 是空的
str[5] 是空的
str[3] 不为空
str[4] 是空的
你有4个项目。

我真的不想实现这段代码,但这应该会很快。


如果数组中间有空字符串,它将无法工作。如果我们有自己的插入函数,我们可以使用它来保持数组排序。在它成为真正的瓶颈之前,我不会这样做。 :) - young

0
一个简单的方法是使用std::string的empty()成员函数,例如:
    size_t stringArrSize(std::string *stringArray) {

       size_t num = 0;
       while (stringArray->empty() != true) {
           ++num;
           stringArray++;
       }
       return num;

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接