0

So, in javascript(coffeescript), I have some code that looks like this:

"BRIGHT":
  min: 1
  max: 4
  step: 1
  value: 3

bluetooth:
  options: [ 'off', 'on' ]  # SOMETIMES I NEED ARRAY
  callback: ->
    rangeFinder.bluetooth = rangeFinder.getSetting().value

mode:
  options: [ 'basic', 'advanced', 'config' ] # OF DIFFERENT LENGTHS
  callback: ->
    rangeFinder.lastMode = rangeFinder.getSetting().value

How do I do something like this in c++?

I've got an array of 3 objects similar to brightness

#include "setting.cpp"

class GlobalMenu {

  public:

    MenuSetting settings[3];
    int setting;
    GlobalMenu();

};

GlobalMenu::GlobalMenu(void){

  // What is the currently selected setting?
  this -> setting = 0;

  this -> settings[0].name = "BRIGHT";
  this -> settings[0].min = 1;
  this -> settings[0].max = 4;
  this -> settings[0].step = 1;
  this -> settings[0].value = 3;

  this -> settings[1].name = "BLUETOOTH";
  // HOW DO I GET VARIABLE LENGTH ARRAYS HERE?

}

and in setting.cpp

class MenuSetting {

  public:

    char *name;
    int min;
    char options[][5];
    int max;
    int step;
    int value;

};

somewhere else, this code changes the setting (and works)

void RangeFinder::changeSetting(int dir) {

  this -> data.global.settings[this -> data.global.setting].value +=
    (dir ? 1 : -1) *
    this -> data.global.settings[this -> data.global.setting].step;

  this -> enforceMinMax();

  this -> render();
}

also if you can find a way to clean it up that would help

So, I can probably figure out how to detect if options has a length, but I am having problems assigning any number of options into the options array

The solution cannot use the STD.

As far as i know the atmega32 micro-controller can't use std lib.

dansch
  • 6,059
  • 4
  • 43
  • 59

5 Answers5

3

In C++ the canonical way to handle an array of variable size is to use a vector

std::vector<std::string> options;

options.push_back("First option");
options.push_back("Second option");
options.push_back("Third option");

then you can use options.size() to know how many elements are there.

You would also do a favor yourself by reading a good C++ book from cover to cover before starting using the language. C++ is not the right language to learn by experimentation for a few reasons, the most important being:

  1. sometimes C++ is illogical (because of its history) and no matter how smart you are you cannot guess history. You need to study it.
  2. when you make a mistake you cannot count on the language to help you (there are no runtime error angels, just undefined behavior daemons).
Community
  • 1
  • 1
6502
  • 112,025
  • 15
  • 165
  • 265
0

The best options for you to avoid the several pitfalls you've fallen into:

  1. Use std::string instead of character pointers and buffers
  2. Use std::vector instead of compiler-sized arrays

This would make your class look like:

class MenuSetting 
{
public:
    std::string name;
    int min;
    std::vector<std::string> options;
    int max;
    int step;
    int value;
};

You can find the details on how the various operations for both std::string and std::vector.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • I've been avoiding using std because it is not found when I include it. – dansch Feb 13 '14 at 21:41
  • You must include `` and `` and **not** have `using namespace std;` declared if you are to use `std::string`. – Zac Howland Feb 13 '14 at 21:44
  • it doesn't find `` it can find string.h, but then std doesn't have string. I'm not sure if its something to do with my makefile, i attached it to the question – dansch Feb 13 '14 at 21:45
  • What compiler are you using? – Zac Howland Feb 13 '14 at 21:47
  • i've tried `using namespace std` and `string`, and without `using namespace std` and with `std::string`, and even combinations, but none work. – dansch Feb 13 '14 at 21:47
  • i do `make clean && make && avrdude -c usbtiny -P usb -p m32 -U flash:w:GccApplication2.hex` – dansch Feb 13 '14 at 21:48
  • My guess is that compiler does not use the standard. You do not have an include path (so that may be the issue), but if it finds the old "string.h", then it should have the rest of the standard library somewhere (unless this is just a C compiler - which it may be). – Zac Howland Feb 13 '14 at 21:52
  • `C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\avr\include\string.h` -- that's the string it's finding. its definietly a c++ compiler because I changed using `__cplusplus` or something. how/where is the std lib? – dansch Feb 13 '14 at 21:54
  • According to the [documentation](http://www.atmel.com/Images/avr32-gnu-toolchain-3.4.2.435-readme.pdf), this is a microcontroller compiler and only includes the standard C library (not C++). So the `std=c++11` directive in the makefile is meaningless. On that note, your best option would brush up on dealing with pointers and memory management in C. – Zac Howland Feb 13 '14 at 21:57
  • so.. hence my original question of how to add a variable length array in c++? – dansch Feb 13 '14 at 21:58
  • You are not going to be able to use C++ (my point). C and C++ are different languages. You are going to need to learn how to use `malloc`, `realloc`, and `free`. – Zac Howland Feb 13 '14 at 21:59
0

its not possible... the answer is to create case statements and hard code more.

dansch
  • 6,059
  • 4
  • 43
  • 59
0

The simplest way would be to use an array of pointers
and dont forget to delete the pointers ;)

class MenuSetting {

public:

char *name;
int min;
char* options[5];
int max;
int step;
int value;

};

then you may assign it this way

bool MenuSetting::setOption(char *str, unsigned int pos)
{
    if(c && p <5)
    {
        options[pos]=str;
        return true;
    }
    return false;
}

i think it would help you most if you used a smart pointer(a simple one is not that hard to implement) and i think you can refer this site Implementing a simple smart pointer in C++ for example.

Also i think this answer would work for you https://stackoverflow.com/a/279032/2689696

Community
  • 1
  • 1
tejas
  • 1,795
  • 1
  • 16
  • 34
  • `options[][5]` is to say, a list of options with unknown length, containing many strings of 5 length. so.. ['on', 'off'], or ['yes', 'no', 'maybe'] – dansch Feb 17 '14 at 15:13
  • you can make a class for options instead of char say `class options { private: char* strings[/*Some size*/]; int numberOfStrings; public: int getNoOfString(); char* getString(int index); bool setStringIndex // blah blah blah }` or something better ;) – tejas Feb 23 '14 at 09:04
0

You should really use the standard template library. It will make your life so much more meaningful, and you will have lots of extra free time to document your code! With the latest std libraries, and c++11, your code can be simplified to look clean like the javascript snippet:

#include <string>
#include <vector>

std::vector<std::string> bluetoothOptions = {"on", "off"};
std::vector<std::string> modeOptions      = {"basic", "advanced", "config"};

// Example usage:
assert (bluetoothOptions[1] == "off");   // exanple to access strings by index
assert (modeOptions.size() == 3);        // example to determine size of vector

If you want to enforce that these strings and vectors cannot change, then use the following (this would be my preference):

const std::vector<const std::string> bluetoothOptions = {"on", "off"};
const std::vector<const std::string> modeOptions      = {"basic", "advanced", "config"};
Steger
  • 887
  • 7
  • 16