【问题标题】:Setting Arduino String values in a class在类中设置 Arduino 字符串值
【发布时间】:2019-08-07 08:13:55
【问题描述】:

我有一个类声明,我将多次使用不同的 Titles 和 Values 值

class Generator
{
    public:
        String  Titles[9];     
        int16_t Values[9];
        byte    MainSel;
        void    SetTitles(String names[9])
                {
                    for (i = 0; i < 9; i++)
                        Titles[i] = names[i];
                }                   
        void    Update_Display()
                {
                    Display(__func__, Titles, Values, MainSel);
                }
};

我声明它的一个实例并尝试使用 SetTitles 设置标题

    Generator Organ_Levels;

    Organ_Levels.SetTitles("", "Rot", "Tone", "Sprd", "Bal", "Upper", "Lower", "Pedal", "Volume");

但编译器似乎认为我在传递 char 数组:

没有匹配函数调用'Generator::SetTitles(const char [1], const char [4], const char [5], const char [5], const char [4], const char [6] , 常量字符 [6], 常量字符 [6], 常量字符 [7])'

为什么不将它们作为 Arduino String 类型的实例?

【问题讨论】:

  • 什么是String?T 那不是c++标准实现。
  • “但编译器似乎认为我在传递 char 数组” 你是。这就是字符串文字。

标签: c++ arrays string parameter-passing


【解决方案1】:

不清楚String 是什么,但我假设它类似于std::string

将数组作为参数传递是一个糟糕的主意。改用向量:

    void    SetTitles(vector<string> names)

然后你可以很容易地调用它在流上创建一个向量,只需要两个大括号:

Organ_Levels.SetTitles({"", "Rot", "Tone", "Sprd", "Bal", "Upper", "Lower", "Pedal", "Volume"});    return 0;

Online demo

更进一步的方法是在您的班级中获取阵列的装备。然后,您可以替换您的 for 循环以将值一一复制到向量级别的简单赋值语句。

【讨论】:

    【解决方案2】:

    您的 SetTitles 函数需要一个字符串数组,但在这一行:

      Organ_Levels.SetTitles("", "Rot", "Tone", "Sprd", "Bal", "Upper", "Lower", "Pedal", "Volume");
    

    你正在调用一个有 9 个参数的函数。定义一个数组,用你的数据填充它,然后将它传递给 SetTitles :

    string names[9]={"", "Rot", "Tone", "Sprd", "Bal", "Upper", "Lower", "Pedal", "Volume"};
        Organ_Levels.SetTitles(names);
    

    我应该提到 String 不是 c++ 类型。

    【讨论】:

    • 是的,这行得通,但代码需要由不会成为专家程序员的音乐家(因此有一些名字)修改。因此,需要将名称直接放在函数调用中以保持简单。
    • 那么你需要使用向量,这样你就可以在函数调用中使用初始化列表。
    【解决方案3】:

    如果您使用的是 C++11 或更高版本,您可以通过使用 parameter packsSetTitles 作为可变参数函数(可以传递可变数量的参数)调用。

    template<class ...Ts>
    void SetTitles(Ts... args)    // accepts an arbitrary number of arguments
    {
        std::vector<String> names {args...};   // unpacks the arguments into an initialiser list          
                                               // and constructs a vector with it
    
        const int size = std::min(9, names.size());     // size should be no bigger than 9      
                                                        //  to prevent undefined behaviour      
        // loop through the vector as normal
        for (int i = 0; i < size; i++)
            Titles[i] = names[i];
    }
    

    这就允许:

    Organ_Levels.SetTitles("", "Rot", "Tone", "Sprd", "Bal", "Upper", "Lower", "Pedal", "Volume");
    

    甚至更多:

    Organ_Levels.SetTitles("p", "a", "r", "a", "m", "e", "t", "e", "r", " ", "p", "a", "c", "k", " ", "a", "b", "u", "s", "e");
    

    但是,由于Generator::Titles 的大小设置为 9,因此后一个示例最多只能设置 9 个标题。要使这个数字动态化,请考虑将String Titles[] 数组更改为std::vector(例如std::vector&lt;String&gt; Titles)。请注意,您可能还需要更改代码的其他部分(例如int16_t Values[] 数组)。还有一个额外的好处是您可以通过直接复制向量来消除循环:

    template<class ...Ts>
    void SetTitles(Ts... args)
    {
        std::vector<String> names {args...};
    
        //  works if Titles is an std::vector
        Titles = names;
        //  Titles = std::vector<String>{args...}; // should also work
    }
    

    感谢Christophe's prompt

    【讨论】:

    • 这是一个很好的答案。尽管如此,在其余代码不变的情况下,第二个示例将是 UB:names.size() 将超过数组 Titles 的大小。如果将Titles 更改为向量,则可以将赋值循环替换为单个向量赋值。
    • @Christophe 希望现在已经修补。感谢您的推动。
    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    相关资源
    最近更新 更多