Я нашел другой способ, не используя соседние метки или окружающие элементы.
Мой сценарий был в том, что у меня был анализатор уценки, который генерирует эти изящные списки TODO, и я хотел их стилизовать. Изменение сгенерированного HTML не было вариантом, поэтому я пришел к такому решению:
поставили флажок примерно так:
<input type="checkbox" id="cb">
Вы можете присвоить ему стиль visibility: hidden
для флажка и visibility: visible
на :: после, как это:
#cb {
visibility: hidden;
}
input#cb::after {
visibility: visible;
content: "F";
color: red;
background: green;
padding: 8px;
}
input#cb:checked::after {
content: " T ";
color: green;
background: red;
}
<!doctype html>
<html>
<body>
<input type="checkbox" id="cb">
</body>
</html>
РЕДАКТИРОВАТЬ:
@connexo в комментарии указал, что входные элементы не могут иметь контент. Это можно легко сделать с помощью элемента label, например, вот так (пожалуйста, кто-нибудь исправит меня, если это не так, у меня нет удобного браузера для тестирования).
#cb-span * {
visibility: hidden;
}
input#cb + label::after {
visibility: visible;
content: "F";
color: red;
background: green;
padding: 8px;
}
input#cb:checked + label::after {
content: " T ";
color: green;
background: red;
}
<!doctype html>
<html>
<body>
<span id="cb-span">
<input type="checkbox" id="cb">
<label for="cb"></label>
</span>
</body>
</html>
Флажок работает так же, как и обычный, и вы можете стилизовать его как угодно.
Может быть, это кому-нибудь поможет (и я могу добавить это в закладки, потому что я не нашел ничего подобного в Интернете)
С динамическим размещением, с использованием malloc:
int** x;
x = malloc(dimension1_max * sizeof(int*));
for (int i = 0; i < dimension1_max; i++) {
x[i] = malloc(dimension2_max * sizeof(int));
}
[...]
for (int i = 0; i < dimension1_max; i++) {
free(x[i]);
}
free(x);
Это выделяет 2D-массив размером Dimension1_max
* Dimension2_max
. Так, например, если вам нужен массив 640 * 480 (например, пиксели изображения), используйте Dimension1_max
= 640, Dimension2_max
= 480. Затем вы можете получить доступ к массиву, используя x [d1] [d2]
где d1
= 0..639, d2
= 0..479.
Но поиск в SO или Google также раскрывает другие возможности, например в этом вопросе SO
Обратите внимание, что ваш массив выиграл ' • выделить непрерывную область памяти (640 * 480 байт) в этом случае, что может вызвать проблемы с функциями, которые предполагают это. Итак, чтобы массив удовлетворял условию, замените блок malloc выше следующим:
int** x;
int* temp;
x = malloc(dimension1_max * sizeof(int*));
temp = malloc(dimension1_max * dimension2_max * sizeof(int));
for (int i = 0; i < dimension1_max; i++) {
x[i] = temp + (i * dimension2_max);
}
[...]
free(temp);
free(x);
Массивы в c объявляются и доступны с помощью оператора []
. Итак,
int ary1[5];
объявляет массив из 5 целых чисел. Элементы нумеруются с нуля, поэтому ary1 [0]
является первым элементом, а ary1 [4]
- последним элементом. Примечание 1: инициализации по умолчанию нет, поэтому память, занимаемая массивом, может изначально содержать что-нибудь . Примечание 2: ary1 [5]
обращается к памяти в неопределенном состоянии (которое может быть даже недоступно для вас), так что не делайте этого!
Многомерные массивы реализованы как массив массивов (массивов (из ...)). Итак,
float ary2[3][5];
объявляет массив из 3 одномерных массивов по 5 чисел с плавающей запятой в каждом. Теперь ary2 [0] [0]
- это первый элемент первого массива, ary2 [0] [4]
- последний элемент первого массива, а ary2 [2] [4]
- последний элемент последнего массива. Стандарт 89-го требует, чтобы эти данные были непрерывными (раздел A8.6.2 на странице 216 моего 2-го изд. K&R), но, похоже, не зависит от заполнения.
Если вы не знаете размер массива во время компиляции, вам нужно динамически выделить массив. Возникает соблазн попробовать
double *buf3;
buf3 = malloc(3*5*sizeof(double));
/* error checking goes here */
, который должен работать, если компилятор не заполняет выделение (вставляет дополнительное пространство между одномерными массивами). Может быть безопаснее использовать:
double *buf4;
buf4 = malloc(sizeof(double[3][5]));
/* error checking */
, но в любом случае хитрость заключается в разыменовании времени. Вы не можете написать buf [i] [j]
, потому что buf
имеет неправильный тип. Вы также не можете использовать
double **hdl4 = (double**)buf;
hdl4[2][3] = 0; /* Wrong! */
, потому что компилятор ожидает, что hdl4
будет адресом адреса типа double. Вы также не можете использовать double incomplete_ary4 [] [];
, потому что это ошибка;
Итак, что вы можете сделать?
Просто вычислите смещение памяти для каждого элемента следующим образом:
for (i=0; i<3; ++i){
for(j=0; j<3; ++j){
buf3[i * 5 + j] = someValue(i,j); /* Don't need to worry about
padding in this case */
}
}
Определите функцию, которая принимает требуемый размер в качестве аргумента, и продолжайте как обычно
void dary(int x, int y){
double ary4[x][y];
ary4[2][3] = 5;
}
Конечно, в этом случае ary4
является локальной переменной, и вы не можете ее вернуть: вся работа с array должен быть выполнен в функции, которую вы вызываете в функциях, которые он вызывает.
Рассмотрим это:
double **hdl5 = malloc(3*sizeof(double*));
/* Error checking */
for (i=0; i<3; ++i){
hdl5[i] = malloc(5*sizeof(double))
/* Error checking */
}
Теперь hdl5
указывает на массив указателей, каждый из которых указывает на массив значений типа double. Интересно то, что вы можете использовать нотацию двумерного массива для доступа к этой структуре --- hdl5 [0] [2]
получает средний элемент первой строки --- но это не - тем не менее, это объект другого типа, чем двумерный массив, объявленный double ary [3] [5];
.
Эта структура более гибкая, чем двумерный массив (поскольку для строк требуется не одинаковой длины), но доступ к нему, как правило, будет медленнее и для этого потребуется больше памяти (вам нужно место для хранения промежуточных указателей).
Обратите внимание, что, поскольку я не установил никаких охранников, вам придется оставить самостоятельно отслеживать размеры всех массивов.
c не поддерживает векторную, матричную или тензорную математику, вам придется реализовать ее самостоятельно или внести библиотеку.
Умножение на масштабатор, а также сложение и вычитание массивов одинаковых rank просты: просто перебирайте элементы и выполняйте операцию по ходу. Внутренние продукты также просты.
Внешние продукты означают больше петель.