LINUX.ORG.RU

Демонстрация массива и цикла по нему

 ,


0

2

Учитывая не малое число откликов и отсутствие возражний по теме простейшей программы продолжаем, с учётом замечаний и идей…

Задание к следующему конкурсу звучит примерно так:

Написать на любимом языке программу, которая демонстрирует использование массива данных и применяет по ней цикл.

Условия:

  1. ясность, наглядность, понимаемость и простота восприятия
  2. минимализм, краткость не в ущерб наглядности и пункту выше

Начну со своего любимого Си , опять-таки с учётом полученного опыта и «набитых шишек».

Почему многие преподаватели и авторы книг, постов в блогах демонстрируют в качестве «пробы пера» дополнительные вводные переменные из массива и переменных цикла по нему, когда это загромождает код и усложняем новичком его восприятие.

Все рассказывают, про функцию main в Си, но молчат (видимо, откладывая на потом), что в её заголовке уже есть в качестве параметров и скалярная переменная argc и, логически связанный с ней, массив строк argv. Их ведь сразу можно использовать! Но почему же эти педагоги от программирования сразу не объясняют назначение и смысл этих переменных? Ведь всё равно придётся это проходить. Не проще ли их сразу начать использовать для демонстрации возможностей языка? И по ходу дела рассказать про циклы, логические выражения и условия в операторах…

У меня получилось всего 5 строчек простого и наглядного кода на Си. Вот текст файла arr_cycl.c:

#include <stdio.h>
void main(int argc, char* argv[]){
        for(argc-- ; argc>=0 ; argc--)
                printf("argv[%i]=%s\n" , argc, argv[argc]);
}

Компиляция и демонстрационный прогон:

gcc arr_cycl.c && ./a.out раз два три
argv[3]=три
argv[2]=два
argv[1]=раз
argv[0]=./a.out

Итерационный цикл с уменьшением переменной, которая и определяет фактически крайний наибольший по индексу элемент, использован чтобы не вводить дополнительных переменных, а нижняя граница массива argv строго табулирована нулём.

Тут можно многое рассказывать новичку в программировании про его нюансы: например, что наибольший индекс (крайний элемент) - это размер массива за вычетом 1, потому, что наименьший индекс - это нуль (нулевое смещение в Си). И это условие выполняется в первой части оператора for

Жду нечта аналогичного на других языках с разъяснениями. Даёшь простые и понятные альтернативы набившим оскомину заскорузлым подходам к изучению программирования (пробам пера)!

P.S.:

Кстати, наш насущный bash - тоже интересен тем, что там, в отличие от классического Bourne Shell - есть массивы.


.global _start
_start: mov %rsp,%r12
     1: add $8, %r12
        mov (%r12), %rdi
        cmp $0, %rdi
        je  2f
        call puts
        jmp 1b
     2: call exit

$ gcc -nostdlib -lc args.S -o args
$ ./args uno dos tres
./args
uno
dos
tres
anonymous
()
Ответ на: комментарий от anonymous

Биос использовать — это не по-джедайски.

luke ★★★★★
()
Ответ на: комментарий от luke

Но выглядеть он должен вот так:

00000000: b800 b88e d8b8 0000 8ec0 bba0 0fb8 0002  ................
00000010: 8907 83eb 0275 f9b9 1600 bb00 00bd ac7c  .....u.........|
00000020: b402 8a46 0045 8907 83c3 02e2 f5ba 0100  ...F.E..........
00000030: bd00 7c89 d3b8 a000 f6e3 89c3 89d0 48c1  ..|...........H.
00000040: e004 e83c 00c6 073a 83c3 04b9 0800 268b  ...<...:......&.
00000050: 4600 e82c 0083 c302 83c5 0226 8a46 00e2  F..,.......&.F..
00000060: ed42 83fa 1872 ccd1 ebba d403 b00f eefe  .B...r..........
00000070: c288 d8ee feca b00e eefe c288 f8ee f4eb  ................
00000080: fd51 56b9 0400 89c6 5149 7405 c1e8 04eb  .QV.....QIt.....
00000090: f859 240f 3c0a 7304 0430 eb02 0437 b402  .Y$.<.s..0...7..
000000a0: 8907 83c3 0289 f0e2 df5e 59c3 5072 696e  .........^Y.Prin
000000b0: 7420 6974 7365 6c66 2061 6e64 2068 616c  t itself and hal
000000c0: 743a 0000 0000 0000 0000 0000 0000 0000  t:..............
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

А у тебя hi и lo перепутаны. Это заметно уже по YrPnittiesfla dnh la:t в твоём дампе.

Ещё, магия в MBR таки 0x55aa, а не 0xaa55, как у тебя. ;)

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 3)
Ответ на: комментарий от beastie

https://imgur.com/a/QLfM4QW

Это хексдамп такой, под него всё и написано. Машинное слово для старенького i8086 16 бит, поэтому и печатаю я сгруппированно по шестнадцать бит, в памяти-то оно конечно идёт сначала младший, а потом старший.

luke ★★★★★
()

Чтобы кайф был полным

@beastie, @WitcherGeralt и анонимус, я думаю в этот наш MBR надо засунуть ещё отклик на клавиатуру, чтобы организовать прокрутку. Тогда мы сможем распечатать весь сектор целиком, вместе с магией. Надо девятое прерывание перехватить (банально засунуть в 36–37 байты указатель на начало прокрутки, а в 38–39 — нолик). Да, при инициализации не забыть замаскировать прерывания.

luke ★★★★★
()
Ответ на: комментарий от beastie

Всё дело в ключах.

hexdump без ключей показывает как у меня.

hexdump -C показывает как у тебя.

luke ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Радикальная субкультура Си

for(;argc--; printf("[%i] -> %s\n", argc, argv[argc]));

Ну это переосмысление на рекорд по краткости тянет. Но даже я посмотрев на такое, отчасти соглашусь со своими предыдущими критиками.

Если и новичку этот пример приводить - то с большими оговорками:

На всех четырёх позициях оператора for - полный отход от задуманного изначально замысла (стандарта де-юро):

  1. Начальная инициализация перед циклом отсутствует: пустой оператор. Но она и не нужна - уже нам дана переменная agrc с инициализованным значением, которое мы используем и выбросим . Ибо для нашего простейшего случая, оно в дальнейшем никогда не пригодится. Любители кровавого энтерпрайза - пусть утрутся своими инстинктами в стиле «сохранить на всякий случай, а вдруг при дописании (доработке) кода пригодится»!
  2. Собственно помимо проверки условия, которое состоит собственно в сличении с нулём самого значение переменной argc - сразу же после этой самой проверки идёт её уменьшение. Т.е. итерация цикла засунута в то самое место, где по-привычки задумывалась только проверка на возможность дальнейшего выполнения цикла.
  3. в том месте, где стоит итерация после исполнения тела (см. далее) - на самом деле происходит это самое тело - т.е. реально то, что должен выполнять цикл - вывод значений демонстрационного массива строк.
  4. ну, уже всё сказано - тело -пусто -опять пустой оператор.

Т.е. в итоге имеем - 2 из 4 мест оператора пусто: как в философии «стакан на половину полон или пуст». Думаю, Пушкин бы аплодировал стоя такому таланту краткости.

Android
() автор топика

Racket

#!/usr/bin/racket
#lang racket
(for ([n (in-naturals)]
      [arg (current-command-line-arguments)])
  (printf "argv[~a]=~a\n" n arg))
monk ★★★★★
()
Ответ на: комментарий от monk

LISP

Лиспом меня в универе мучали. Странно, что пока не было ни одного его диалекта. Но с таким экзотическим названием. На я так смотрю на синтаксис - там ещё как в TCL - квадратные скобки в дополнение к обычным только круглым в классическом Лиспе. В чём между скобами разница?

И как этот Рэкет попал в стандартные дистры? Им что мало этих Scheme, Closure, Guile, …? Вообще сколько наследников лиспа лежит в стандартных репах (допустим того же Дебиан)?

С розеты уже вторая ссылка. В принципе то, что я уже раз третий делаю - похоже на неё…

Android
() автор топика
Ответ на: LISP от Android

В чём между скобами разница?

Ни в чём. Просто для эстетики. Чтобы скобки «вызов функции» отделять визуально от скобок «начало-конец определения переменной».

И как этот Рэкет попал в стандартные дистры?

Как и все остальные достаточно распространённые компиляторы. Кто-то пользуется, кто-то поддерживает.

Им что мало этих Scheme, Closure, Guile, …?

Видимо да. Вообще, это про любой язык можно сказать: зачем нужен Python? Им что мало этих PERL, PHP, TCL, …?

Racket — это не только Scheme. Вот это тоже Racket:

#!/usr/bin/racket
#lang python
from "racket" import current_command_line_arguments

a = current_command_line_arguments()

for i, s in zip(xrange(0, len(a)), a):
  print 'argv[%s]=%s' % (i, s)

А если брать именно Debian, то там есть даже https://packages.debian.org/ru/jessie/clc-intercal

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от AntonI

print i

Некрофил? Или дебианщик? А хотя это одно и тоже.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.