我将一个数组传递给一个函数,并且我正在用全局值初始化它。 我在数组的末尾使用空string来确定数组的长度。
现在,有没有办法自动初始化数组中有多余的空项目,所以我没有机会忘记从那里? 就像char []的工作,它增加了结束IIRC额外的空。
这是我现在使用的代码:
struct twostrings { string s1, s2; }; twostrings options[] = { {"text1", "more text1"}, {"text2", "more text2"}, {"text3", "more text3"}, {""}, // tells that the array ends here } int get_len(twostrings opt[]){ int p = 0; while(1){ if(opt[p].s1 == ""){ return p; } p++; // now here is a possibility to go in infinite loop if i forgot the empty string. // currently i have a code here that checks if p > 10000 and gives error message to me if i manage to forget that empty string in accident. } return p; } void dosomething(twostrings options[]){ int len = get_len(options); for(int p = 0; p < len; p++){ // do stuff } } int main(){ // yes its not valid written main function. dont bother about it. dosomething(options); }
在C ++中传递C数组并不是很习惯。 尝试使用std::vector
来代替:
#include <vector> #include <string> struct twostrings { std::string s1, s2; }; typedef std::vector<twostrings> option_type; twostrings options[] = { {"text1", "more text1"}, {"text2", "more text2"}, {"text3", "more text3"} }; int get_len(const option_type& options){ return options.size(); } void dosomething(const option_type& options){ int len = get_len(options); for(int p = 0; p < len; p++){ // do stuff } } int main() { // This main function is perfectly fine! option_type opt_vector(options, options + (sizeof options / sizeof options[0])); dosomething(opt_vector); }
不幸的是,你是不正确的。 char数组不会自动在null中结束,这只是一个用字符串文字(在末尾具有自动空值)赋值的副作用。
char x[] = "ABC"; // size 4, contains A, B, C, \0. char x[] = {'A','B','C'}; // size 3, contains no terminating null.
所以简短的答案是否定的,没有办法自动结束数组自动条目。 还有其他一些选项,比如STL向量,它们有其他的方法来确定你到底是什么时候。 在C ++ 0x中,可能(IIRC)就像你想要的那样初始化矢量。
HTH。
编辑 :
就个人而言,我更喜欢在数组的末尾添加额外的0,但我想有办法使用宏来解决这个问题。
#define ARRAY(...) {__VA_ARGS__, {0}}
并像这样使用它
struct foo { char* x; char* y; } struct foo x[] = ARRAY({"abc", "xyz"}, {"def","uvw"});
我不知道这是否行得通(我没有预处理器),正如我所说,我个人并不喜欢它。 它还要求结构中的第一个元素是可以分配0来标记数组的结尾的东西。
当然,这迫使你记住在宏调用中包装它,这跟强迫你记住终止数组差不多。
编辑:
我只是有机会测试它,它的工作原理。 原来可变宏是,到目前为止,只有C。 然而,一些(大多数?)C ++编译器无论如何都支持它们,快速搜索出现了g ++和visual studio。 不过我不会赞成这种方法,我只是为了完整而添加它。
通过长度或结束,而不是使用哨兵:
template<class T, int N> int len(T (&)[N]) { // exists in a more general form as boost::size return N; } typedef std::pair<std::string, std::string> twostrings; // std::pairs have first and second members of the given types void dosomething(twostrings options[], int size); // call as: dosomething(array, len(array)); # or: template<class T, int N> T* end(T (&a)[N]) { // exists in a more general form as boost::end return a + N; } void dosomething(twostrings* options_begin, twooptions* options_end); // call as: dosomething(array, end(array)); // usage example: void dosomething(twostrings* options_begin, twooptions* options_end) { // you might name the parameters just 'begin' and 'end' for (; options_begin != options_end; ++options_begin) { // the 'begin' var advances through the entire sequence // use for (twostrings* current = options_begin; current != options_end; ++current) // if a separate copy is required cout << options_begin->first << ": " << options_begin->second << '\n'; } }
注意[begin,end]迭代器模式(包括begin,exclusive end)在stdlib中很常见(例如,从<algorithm>查看std :: sort)。
这是数组和容器(如std :: vector)之间的一个很好的中途测量,并允许您保持现在简单的初始化语法(C ++ 0x为您提供了与std :: vector等容器相同的语法,但是0x还没有准备好)。
不要在C ++中使用C风格的数组,与vector.size()相比,它们不值得。 您应该使用boost::array<twostrings, length>
作为静态数组。
地狱,你可能应该不使用静态值。
有更好的方法来查找数组长度。 您可以使用:
1. sizeof(options) / sizeof(twostrings); 2. sizeof(options) / sizeof(options[0]); 3. std::vector<twostrings> options; options.size(); 4. ARRAYSIZE(options); (windows only)
顺便说一句, if(opt[p].s1 == "")
检查2个const char *
指针是否相等,而不是2个字符串。 虽然compiller通常优化相等的字符串常量指向一个地方,它仍然是一个错误。
你应该使用一个NULL
sentinell,因为它之前提到过Svisstack。
编辑:证明
#include <stdio.h> const char *one = "the string"; void main(){ const char *other = "the string"; printf("adress of 'one' = %x, it contains \"%s\"\n", one, one); printf("adress of 'other' = %x, it contains \"%s\"\n", other, other); if(one == other){ printf("one == other\n", one); } else { printf("one != other\n", one); } }
输出:
k:\temp>cl test.cpp Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86 /out:test.exe test.obj k:\temp>test.exe adress of 'one' = 3d8140, it contains "the string" adress of 'other' = 3d814c, it contains "the string" one != other