Путем я сделал должно было потребоваться несколько минут первоначально для осмотра через самый основной материал - перемещение курсора, поиск вперед и назад, переход к следующим и предыдущим словам/предложениям/абзацам, и т.д. Вставка, добавление. Независимо от того, что можно поместиться голову. Затем когда у Вас есть что-то, чтобы сделать, который не должен быть сделан за следующие 15 секунд, заставить себя использовать его.
, Когда Вы довольно довольны основами, медленно изучайте более усовершенствованные команды - особенно те, которые усиливают Ваше предыдущее приобретение знаний (как замена следующих 3 слов или удаление к следующей поисковой цели)
, я люблю использовать VI, как только я учился как. Усовершенствованные команды намного более мощны, чем, что большинство редакторов GUI, кажется, предлагает, и то, что это повсеместно и основано на тексте, и так доступно по ssh, тем лучше.
Он отслеживает значение, увеличивая хвост структуры экземпляры mapgen, смешанные с экземплярами times2
Каждый вызов pow2next добавляет еще одну пару к хвосту.
Единственная ценность этого примера - иллюстрация того, как много языков высокого уровня делают для нас и насколько наивная реализация высокоуровневых языков концепции уровней могут убить вашу производительность.
Код показывает, как можно сгенерировать произвольную последовательность чисел
с помощью 'генераторов' .
генераторы являются популярным инструментом в динамических языках, таких как Python, и позволяют
перебирать произвольную длинную последовательность, не выделяя сразу всю последовательность.
Отслеживание происходит в строках
p->next = pow2next;
p->continue_from = 0;
, которые говорят p , что он должен вызвать pow2next , чтобы получить следующий элемент в последовательности
и continue_from = 0 , чтобы указать, что where в начале последовательности.
Когда вы вызываете p-> next (p) , он фактически просто вызывает pow2next с p в качестве параметра. Для первого вызова это просто вернет 1 и увеличит continue_from до 2 .
switch(p->continue_from) {
case 0:
p->continue_from = 1;
return 1;
/* ... */
При втором вызове ( continue_from = 2 ) он создаст новую рабочую структуру map_gen на новой структуре struct pow2s и с помощью функции times2 :
case 1:
p->g = map(times2,pow2()) ;
p->continue_from = 2;
return p->g->next(p->g) ;
/* ... */
Все дальнейшие вызовы проходят через p-> g-> next (p-> g) , который использует times2 и map_gen для получения следующего значение / создайте новые структуры map_gen по мере необходимости. Все отслеживание значений выполняется с помощью элемента структуры continue_from или с использованием кодов возврата.
Показывая интересный подход к генераторам в C, я должен указать, что этот код приводит к утечке памяти! Как видите, новые структуры выделяются с помощью malloc , но они никогда не освобождают .
Я надеюсь, что это объяснение не сбивает с толку, даже если вы только начинаете учиться C.
Если вы действительно хотите разбираться в генераторах, возможно, вам захочется пройти небольшой курс по питону;)
ОБНОВЛЕНИЕ
Как вы сказали в своем комментарии , ни один из генераторов, кажется, никогда не возвращает значение> 2 .
Ключ к увеличению числа кроется в функции map_next :
int map_next(struct mapgen *p) {
return p->f(p->g->next(p->g));
}
. Вместо того, чтобы возвращать исправление, он применяет номер p-> f ()
(в нашем преобразуйте функцию times2 () в результат p-> g-> next (p-> g) .
Это рекурсивный вызов.
Он будет продолжайте вызывать map_next () для каждого map_gen в списке, пока не дойдете до последнего.
Этот последний элемент вернет фиксированное значение (либо 1 , либо 2 ).
Которая затем передается обратно в предыдущий вызов, который применит к нему times2 () и вернет результат вызывающей стороне, которая, в свою очередь, применит к нему times2 () и вернет результат для его вызывающей стороны .... (вы поняли).
Все эти рекурсивные вызовы суммируются и формируют окончательное значение.
Если вы распечатаете результат каждого вызова pow2next () , вы получите следующее:
/* first call */
1
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
2
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
pow2next: returning 4 /* times2(2) */
4
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
pow2next: returning 4 /* times2(2) */
pow2next: returning 8 /* times2(4) */
8
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
pow2next: returning 4 /* times2(2) */
pow2next: returning 8 /* times2(4) */
pow2next: returning 16 /* times2(8) */
16
/* and so on */
Вы можете ясно видеть, как результат самого верхнего вызова передается полностью обратно к первому вызову для формирования результат.