【问题标题】:Rerefence to a const char* array引用 const char* 数组
【发布时间】:2016-10-08 14:01:33
【问题描述】:

我试图避免为 5 个不同的数组重复我的代码。我有 3 个数组(将来可能会更多):

const char *FirstlistOfOptionText[2]   = {OPT_1, 
                                         OPT_2};
const char *SecondlistOfOptionText[2]   = {OPT_1, 
                                         OPT_2};
const char *ThirdlistOfOptionText[2]  = {OPT_1, 
                                         OPT_2};    

每个元素中的元素都不相同。现在它们是因为我只是复制和粘贴它们。元素的数量也不会。

我有一个函数,我想根据我作为参数给出的值打印列表的每个元素。另外,我需要用其他颜色打印其中一个元素(除了一个绿色之外,所有元素都是白色的)。

我只想拥有一个代码来打印和选择我现在拥有的颜色。但我想在这样做之前选择正确的数组。我想了想:

const char *listOfOptions[];
if(menu_t.first_level_option == 0) {
    listOfOptions = FirstlistOfOptionText;
}
if(menu_t.first_level_option == 1) {
    listOfOptions = SecondlistOfOptionText;
}
if(menu_t.first_level_option == 2) {
    listOfOptions = ThirdlistOfOptionText;
}

但我收到一些关于“listOfOptions”存储大小未知的错误。或者我不能将 const char** 用于 char* 或类似的东西。

这样做的正确方法是什么?

【问题讨论】:

  • "... 5 个不同数组的代码。我有 3 个数组..." 5? 3?这有点令人困惑
  • 请提供minimal reproducible example 和确切的错误消息。 “一些错误”和“或类似的事情”有点太不具体,无法猜测出了什么问题
  • 您使用的是 C 还是 C++?
  • 顺便说一句。如果您的代码只需要使用 C++(它是标签之一),那么您可以使用 std::array
  • @Marqin:怎么会这样?数组有不同的维度。他需要std::vector

标签: c++ c arrays


【解决方案1】:

基本上你需要将 listOfOptions 设为 char **;

可以通过指向指针的指针来引用指针数组(这就是 char ** 的含义)。

使用 listOfOptions 的任何人都不会知道大小,因此您需要一种方法来确定大小。要么使用 NULL 指针终止列表,要么您将不得不使用跟踪大小的第二个变量 (listOfOptionsSize)。

所以下面的代码应该可以编译(我选择了 NULL 终止的列表)。

const char *FirstlistOfOptionText[]   = {"a",  "b", NULL};
const char *SecondlistOfOptionText[]   = {"c", "d", "e", "f", NULL};
const char *ThirdlistOfOptionText[]  = {"e",  "f", "g", NULL};    

const char **listOfOptions= NULL;  // pointer to pointer(s)
int first_level_option= 2;         // some value for testing


if(first_level_option == 0) {
    listOfOptions = FirstlistOfOptionText;
}
if(first_level_option == 1) {
    listOfOptions = SecondlistOfOptionText;
}
if (first_level_option == 2) {
    listOfOptions = ThirdlistOfOptionText;
}

printem(listOfOptions);

现在对于您的打印函数,它将获取指向指针列表的指针作为参数,并且看起来像这样:

void printem(const char **listOfOptions)
{
     const char *word;

     while (*listOfOptions!=NULL) {  // while the pointer in the list not NULL
        word= *listOfOptions;        // get the char * to which listOfOptions is pointing
        printf("entry: %s\n", word);
        listOfOptions++;
     }
}

哦,欢迎来到 C-Pointer Hell :-)

【讨论】:

  • 我尝试了你的初始化,我得到了这个错误:错误:'const char* [0] 的初始化程序太多
  • 我忘记更新了。我让它工作了。我只是删除最新的 NULL 元素并设置每个数组的大小。我对此没有任何问题,因为我有一个包含每个数组大小的变量。谢谢!
  • 很高兴听到这个消息
【解决方案2】:

const char *FirstlistOfOptionText[2] 是一个由两个指向 char 的指针组成的数组。

const char *listOfOptions[] 是一个大小未知的数组,带有指向 char 的指针。

const char **listOfOptions; 是指向 char 的指针,您可以将其分配给选项数组列表的地址:

listOfOptions = FirstlistOfOptionText;

【讨论】:

    【解决方案3】:
    const char *listOfOptions[];
    

    但我收到一些关于“listOfOptions”存储大小未知的错误。

    数组的大小是其类型的一部分。 T[1]T[2] 是不同的类型。

    没有指定大小的数组是不完整类型,您不能创建不完整类型的对象。

    或者我不能将 const char** 用于 char* 或类似的东西。

    是的,因为它们是完全不同的类型。第一个是指向常量char 对象的指针。第二个是指向非常量char 对象的指针。

    您的代码尝试将数组视为一等公民,您可以将其分配为“普通”对象,例如int。它还试图平等地对待不同维度的数组。这些都行不通。 C++ 数组比你想象的要有限。


    因此,解决方案是使用std::vector。当您使用它时,std::string 而不是 char*

    #include <string>
    #include <vector>
    
    #define OPT_1 "a"
    #define OPT_2 "b"
    
    int main()
    {
        std::vector<std::string> FirstlistOfOptionText = { OPT_1, OPT_2 };
        std::vector<std::string> SecondlistOfOptionText = { OPT_1, OPT_2 };
        std::vector<std::string> ThirdlistOfOptionText = { OPT_1, OPT_2 };    
    
        int first_level_option = 0;
    
        std::vector<std::string> listOfOptions;
    
        if (first_level_option == 0) {
            listOfOptions = FirstlistOfOptionText;
        }
        if (first_level_option == 1) {
            listOfOptions = SecondlistOfOptionText;
        }
        if (first_level_option == 2) {
            listOfOptions = ThirdlistOfOptionText;
        }
    }
    

    当然,这可以(并且应该)进一步改进。例如,摆脱预处理器宏并将列表选择放入像std::vector&lt;std::string&gt; GetListOfOptions(int) 这样的函数中。

    【讨论】:

      【解决方案4】:

      要打印选项列表,您可以使用模板函数,该函数将静态数组的引用作为参数:

      template <int n>
      void PrintOptions(const char* (&listOfOptions)[N])
      {
          for (int i = 0; i < N; i++)
          {
              //actual printing
          }   
      }
      
      void PrintMenu(/* ... */)
      {
          //...
      
          switch (menu_t.first_level_option)
          {
              case 0:
                  PrintOptions(FirstlistOfOptionText);
                  break;
              case 1:
                  PrintOptions(SecondlistOfOptionText);
                  break;
              case 2:
                  PrintOptions(ThirdlistOfOptionText);
                  break;
          }
      
          //...
      }
      

      数组的大小将由编译器推导出来。

      【讨论】:

        猜你喜欢
        • 2014-07-17
        • 1970-01-01
        • 1970-01-01
        • 2017-03-29
        • 2018-07-30
        • 1970-01-01
        • 2013-07-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多