如何在struct数组中自动初始化最后一项?

时间:2010-07-12 12:34:15

标签: c++ windows struct

我正在将一个数组传递给一个函数,我正在使用一些值全局初始化它。 我在数组的末尾使用空字符串来确定数组长度。

现在,有没有办法自动初始化数组以在其末尾有额外的空项目,所以我没有机会从那里忘记它?就像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);
}

6 个答案:

答案 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