我正在将一个数组传递给一个函数,我正在使用一些值全局初始化它。 我在数组的末尾使用空字符串来确定数组长度。
现在,有没有办法自动初始化数组以在其末尾有额外的空项目,所以我没有机会从那里忘记它?就像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);
}
答案 0 :(得分:6)
在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);
}
答案 1 :(得分:2)
不幸的是,你不正确。 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。我仍然不赞成这种方法,我只是为了完整性而添加它。
答案 2 :(得分:1)
传递长度或结尾而不是使用哨兵:
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中很常见(例如,从&lt; algorithm&gt;查看std :: sort)。
这是数组和容器(如std :: vector)之间的一个很好的中途度量,并允许您保留现在的简单初始化语法(C ++ 0x为您提供与std :: vector等容器相同的语法,但0x尚未准备好。)
答案 3 :(得分:0)
有更好的方法来查找数组长度。您可以使用:
1. sizeof(options) / sizeof(twostrings);
2. sizeof(options) / sizeof(options[0]);
3. std::vector<twostrings> options;
options.size();
4. ARRAYSIZE(options); (windows only)
答案 4 :(得分:0)
不要在C ++中使用C样式数组,与vector.size()相比,它们不值得付出努力。您应该使用boost::array<twostrings, length>
作为静态数组。
天啊,你可能不应该使用静态值。
答案 5 :(得分:0)
顺便说一句,if(opt[p].s1 == "")
检查2 const char *
指针是否相等,而不是2个字符串。虽然compiller通常优化相等的字符串常量指向一个地方,但它仍然是一个错误。
你应该使用先前由Svisstack提供建议的NULL
哨兵。
编辑:证明
#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