如何在C ++中声明字符串数组?


89

我正在尝试以最佳方式遍历静态字符串数组的所有元素。我希望能够在一行上声明它,并轻松地从中添加/删除元素,而不必跟踪数字。听起来真的很简单,不是吗?

可能的非解决方案:

vector<string> v;
v.push_back("abc");
b.push_back("xyz");

for(int i = 0; i < v.size(); i++)
    cout << v[i] << endl;

问题-无法在带有字符串列表的一行上创建矢量

可能的非解决方案2:

string list[] = {"abc", "xyz"};

问题-无法自动获取字符串数量(据我所知)。

必须有一个简单的方法来执行此操作。


升压分配库似乎是你在寻找什么。它使向容器分配常量比以往更加容易。
Craig H

Answers:



37

您可以vector<string>从静态创建的char*数组中简洁地初始化a :

char* strarray[] = {"hey", "sup", "dogg"};
vector<string> strvector(strarray, strarray + 3);

顺便说一下,这将复制所有字符串,因此您使用了两倍的内存。您可以使用威尔·迪恩(Will Dean)的建议将此处的魔术数字3替换为arraysize(str_array)-尽管我记得在某些特殊情况下,特定版本的arraysize可能会造成不良后果(对不起,我无法立即记住详细信息) 。但是它经常可以正常工作。

另外,如果您真的对单行很感兴趣,则可以定义一个可变参数宏,这样一行就DEFINE_STR_VEC(strvector, "hi", "there", "everyone");可以工作。


由于strarray在标题中,它不会违反一个定义规则吗?
jww

22

问题-无法自动获取字符串数(我知道)。

有一种沼泽标准的方式来执行此操作,许多人(包括MS)arraysize为以下内容定义宏:

#define arraysize(ar)  (sizeof(ar) / sizeof(ar[0]))

1
另外,可以使用这样的事情:template<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; } (inline关键字不是必需的,但用来记录功能的意图现代编译理论上应该能够返回整个功能,我相信。
贾斯汀时间-恢复莫妮卡

1
对于指针,这将失败。在C ++中,对数组元素的计数应以不同的方式进行。
jww

8

像这样在C ++中声明一个字符串数组: char array_of_strings[][]

例如 : char array_of_strings[200][8192];

将容纳200个字符串,每个字符串的大小为8kb或8192字节。

用于strcpy(line[i],tempBuffer); 将数据放入字符串数组中。


仅供参考,char array_of_strings [] []无法接受C ++字符串,请务必先转换为char *。cplusplus.com/reference/string/string/c_str
Luqmaan 2012年

由于array_of_strings在标题中,它不会违反一个定义规则吗?
jww

7

一种可能性是使用NULL指针作为标志值:

const char *list[] = {"dog", "cat", NULL};
for (char **iList = list; *iList != NULL; ++iList)
{
    cout << *iList;
}

char **实际上是什么意思?在Java中,它将是字符串列表吗?
IAmGroot 2012年

1
@Doomsknight:在这种情况下,是的。在第一行中,我定义的数组char*。在内存中,这被布置为3个指针-一个指向“ dog”,一个指向“ cat”,另一个保持为NULL。我可以将指针指向第一个指针,并获得char**-指向char指针的指针。当我增加它时,我将char **指向列表中的下一项-指向“ cat”的指针,然后再次增加,并获得一个指向NULL指针的指针,并且我知道我做完了 (
Eclipse

4

您可以使用Boost范围库中的beginend函数轻松找到基本数组的末端,并且与宏解决方案不同,如果不小心将其应用于指针,则会产生编译错误而不是破坏行为。

const char* array[] = { "cat", "dog", "horse" };
vector<string> vec(begin(array), end(array));

3

您可以使用Will Dean的建议[ #define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))]将此处的魔术数字3替换为arraysize(str_array)-尽管我记得在某些特殊情况下,特定版本的arraysize可能会带来不好的后果(对不起,我不记得详细信息了立即)。但是它通常可以正常工作。

它不起作用的情况是“数组”实际上只是一个指针,而不是一个实际的数组。另外,由于将数组传递给函数的方式(转换为指向第一个元素的指针),即使签名看起来像数组,它也不能跨函数调用起作用- some_function(string parameter[])是true some_function(string *parameter)


3

这是一个例子:

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

int main() {
    const char* const list[] = {"zip", "zam", "bam"};
    const size_t len = sizeof(list) / sizeof(list[0]);

    for (size_t i = 0; i < len; ++i)
        std::cout << list[i] << "\n";

    const std::vector<string> v(list, list + len);
    std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));
}

2

除了这个宏,我可以建议这个:

template<typename T, int N>
inline size_t array_size(T(&)[N])
{
    return N;
}

#define ARRAY_SIZE(X)   (sizeof(array_size(X)) ? (sizeof(X) / sizeof((X)[0])) : -1)

1)我们想使用宏使其成为编译时常量;函数调用的结果不是编译时常量。

2)但是,我们不希望使用宏,因为该宏可能会意外地用于指针。该函数只能在编译时数组上使用。

因此,我们使用函数的定义性来使宏“安全”。如果函数存在(即大小为非零),则使用上面的宏。如果该函数不存在,则返回错误值。


2
#include <boost/foreach.hpp>

const char* list[] = {"abc", "xyz"};
BOOST_FOREACH(const char* str, list)
{
    cout << str << endl;
}

1
#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>

int main()
{
    const std::vector< std::string > v = boost::assign::list_of( "abc" )( "xyz" );
    std::copy(
        v.begin(),
        v.end(),
        std::ostream_iterator< std::string >( std::cout, "\n" ) );
}

1

您可以直接声明一个字符串数组,例如string s[100];。然后,如果您想访问特定的元素,则可以像一样直接获取它s[2][90]。为了进行迭代,请使用s[i].size()函数获取字符串的大小 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.