DELETE FROM story_category
WHERE category_id NOT IN (
SELECT cid FROM (
SELECT DISTINCT category.id AS cid FROM category INNER JOIN story_category ON category_id=category.id
) AS c
)
Один из вариантов будет:
struct widget_t {
char const *name;
uint8_t numberOfNicknames;
char const * const *nicknames;
};
static char const *mower_nicknames[] = { "Choppie", "Bob" };
widget_t SomeWidget = { "Lawn Mower", 2, mower_nicknames };
static char const *bus_nicknames[] = { "Wheels", "Go", "Round" };
widget_t OtherWidget = { "Bus", 3, bus_nicknames };
// no setup function needed
Здесь есть разные проблемы.
Сначала ваш последний член имеет неполный тип, потому что это массив необъявленного измерения. Это не разрешено в C ++, но большинство компиляторов допускает его как расширение с той же семантикой, что и в C. В любом случае, это довольно сложно использовать, поскольку его можно использовать только с выделенными структурами, где вы выделяете память для самой структуры и неполный массив.
Далее вы пытаетесь присвоить массиву. Ты не можешь. Массивы не являются объектами первого класса в C ++ (и в C). Вы можете инициализировать массив целиком, но можете назначить его только элементу массива.
И наконец, вы назначаете C литеральную строку для char *
. Это плохо, потому что стандарт объявляет, что литеральные строки имеют значение const
, поэтому использование более позднего указателя для изменения символа будет неопределенным поведением. Это сработает, если вы этого не сделаете, но указатели должны быть по крайней мере объявлены как const
.
Вот как вы можете использовать все это:
widget_t* setUpFunction () {
// allocates a widget_t with 2 slots in nicknames
widget_t *someWidget = (widget_t *) malloc(sizeof(widget_t) + 2 * sizeof(char *));
someWidget.name = (char *)"Lawn Mower"; // VERY DANGEROUS: pointer should be const
someWidget.numberOfNicknames = 2;
someWidget.nicknames[0] = (char *) "Choppie McGrasschopper"; // SAME DANGER
someWidget.nicknames[1] = (char *) "Really Noisy" // Still same danger
return widget_t;
}
Но все это скорее C-ish и его следует избегать в C ++. Кроме того, он все еще требует выделенной памяти, что может не соответствовать тому, что вы хотите для Arduino
Что вы пытаетесь сделать, это назначить строковый литерал указателю char *
- это плохо (подробнее см. Как избавиться от deprecated conversion from string constant to ‘char*’
предупреждений в GCC? ). Вот возможный подход:
#define MAX_NAME_LEN 128
#define MAX_NICK_NAMES 10
struct widget_t {
char name[MAX_NAME_LEN];
uint8_t numberOfNicknames;
char nicknames[MAX_NICK_NAMES][MAX_NAME_LEN];
};
widget_t SomeWidget;
void setUpFunction () {
strcpy(SomeWidget.name, "Lawn Mower");
SomeWidget.numberOfNicknames = 2;
strcpy(SomeWidget.nicknames[0], "Choppie McGrasschopper");
strcpy(SomeWidget.nicknames[1], "Really Noisy");
}
В любом случае, поскольку вы пометите свой вопрос с помощью C++
, я бы предложил вам использовать вместо этого std::string
и std::vector
.
Ваша проблема в том, что c ++ не поддерживает переменные массивы. Вместо этого вам придется динамически распределять память, используя new или в вашем случае new [] .
Сначала вам нужно изменить тип данных на char**
, почти равный предыдущему. Затем вы можете выделить столько строк, сколько захотите nicknames = new char*[number_of_nicknames]
.
Важно то, что с помощью этого метода вам придется вручную добавлять свои псевдонимы следующим образом: delete[] nicknames;
. Лучший способ сделать это - использовать RAII (удалить ваши псевдонимы в деконструкторе)
Если у вас есть динамические строки, вы бы использовали следующую структуру
struct widget_t {
// optional constructor to allocate nicknames
~widget_t()
{
for (int i = 0; i < numberOfNicknames; ++i)
{
char* nickname = nicknames[i];
if (nickname)
delete[] nickname;
}
delete[] nicknames;
}
char *name;
uint8_t numberOfNicknames;
char **nicknames = NULL;
};
и с постоянной строкой следующий
struct widget_t {
// optional constructor to allocate nicknames
// allocate nicknames like
// -> nicknames = new const char*[numberOfNicknames];
~widget_t()
{
if (nicknames) delete[] nicknames;
}
char *name;
uint8_t numberOfNicknames;
const char **nicknames = NULL;
};