Как пре­по­да­вать Си?

Ко­гда па­ру лет на­зад пе­ре­до мной ста­ла за­да­ча на­учить пер­во­курс­ни­ков МФТИ про­грам­ми­ро­вать на Си, я столк­нул­ся со сле­дую­щей труд­но­стью: как по­до­брать та­кую по­сле­до­ва­тель­ность по­да­чи ма­те­ри­а­ла, что­бы каж­дая но­вая те­ма опи­ра­лась на преды­ду­щие те­мы, и при этом не тре­бо­ва­ла ис­поль­зо­ва­ния ещё не изу­чен­но­го ма­те­ри­а­ла?

В этом пла­не хо­ро­ши Пас­каль и Пи­тон: в них ввод-вы­вод осу­ществ­ля­ет­ся опе­ра­то­ра­ми язы­ков (не функ­ци­я­ми), а для на­пи­са­ния про­стей­ших про­грамм не нуж­но со­зда­вать функ­ции и ис­поль­зо­вать ука­за­те­ли.

Язык Си как буд­то спе­ци­аль­но со­здан так, что­бы иметь за­ви­си­мость сво­их кон­цеп­ций друг от дру­га. Хо­ти­те на­пи­сать про­грам­му, вы­во­дя­щую «Hello, world»? Будь­те до­бры, вклю­чи­те за­го­ло­воч­ный файл stdio.h (ис­поль­зу­ет­ся пре­про­цес­сор), со­здай­те функ­цию main (для это­го нуж­но знать функ­ции), со­здай­те стро­ко­вый ли­те­рал "Hello, world" (ука­затель на стро­ку сим­во­лов, окан­чи­ва­ю­щу­ю­ся ну­лём), вы­зо­ви­те функ­цию printf, и так да­лее (ри­су­нок 1).

Про­грам­ма сло­же­ния двух чи­сел
Про­грам­ма сло­же­ния двух чи­сел

Ри­су­нок 1. На­пи­са­ние про­стей­шей про­грам­мы сло­же­ния двух чи­сел
тре­бу­ет глу­бо­ких зна­ний язы­ка про­грам­ми­ро­ва­ния

Ре­ше­ние про­бле­мы, прак­ти­ку­е­мое мно­ги­ми пре­по­да­ва­те­ля­ми: «Что­бы сде­лать это, нуж­но на­пи­сать вот так. По­ка не пы­тай­тесь по­нять, я рас­ска­жу вам это в кон­це кур­са». То есть не­ко­то­рые ве­щи да­ют­ся без объ­яс­не­ния, про­сто так. Я счи­таю этот под­ход опас­ным. Прак­ти­ка по­ка­зы­ва­ет, что ес­ли обу­чае­мый мно­го­крат­но при­ме­ня­ет при­ём, ко­то­ро­го не по­ни­ма­ет, то у не­го скла­ды­ва­ет­ся соб­ствен­ное по­ни­ма­ние это­го при­ё­ма (за­ча­стую оши­боч­ное). Это при­во­дит к то­му, что сту­ден­та по­том очень слож­но пе­ре­учить и на­пра­вить в пра­виль­ное рус­ло. Бы­ва­ет и так, что сту­ден­ты на­столь­ко уве­рен­но при­ме­ня­ют не­ко­то­рые приё­мы, что пре­по­да­ватель за­бы­ва­ет, что не рас­ска­зы­вал им об этом.

Я встре­чал не­сколь­ких сту­ден­тов, ко­то­рые в ре­зуль­та­те та­ко­го обу­че­ния счи­та­ли, что char* — это стро­ка. Не ука­затель, а про­сто стро­ка, ана­лог пас­ка­лев­ско­го string. Звёз­доч­ка, по их мне­нию, озна­ча­ла «мно­го­крат­ное по­вто­ре­ние char». Эти сту­ден­ты при­сваи­ва­ли «стро­ки» обыч­ным при­сваи­ва­ни­ем, чи­та­ли их при по­мо­щи scanf, не вы­де­лив па­мять, и так да­лее.

На мой взгляд, сле­дую­щие кон­цеп­ции пред­став­ля­ют опас­ность для сту­ден­тов (в том смыс­ле, что про них луч­ше во­об­ще не знать, чем знать не­пра­виль­но):

  • мас­си­вы;
  • стро­ко­вые ли­те­ра­лы, стро­ки и стро­ко­вые функ­ции;
  • ука­за­те­ли;
  • функ­ции вво­да-вы­во­да, так как они ис­поль­зу­ют стро­ки и ука­за­те­ли;

Нуж­но бы­ло по­стро­ить курс так, что­бы ис­клю­чить пе­ре­чис­лен­ные ве­щи из на­чаль­но­го из­ло­же­ния.

Не­мно­го по­раз­мыс­лив, я на­шёл ре­ше­ние про­бле­мы вво­да-вы­во­да, а так­же ис­поль­зо­ва­ния строк и ука­за­те­лей: от­лад­чик. Он поз­во­ля­ет во­об­ще обой­тись без ис­поль­зо­ва­ния функ­ций вво­да-вы­во­да. Зна­че­ния всех пе­ре­мен­ных как на ла­до­ни; их не нуж­но ни­ку­да вы­во­дить.

Кро­ме то­го, нель­зя бы­ло вы­ры­вать сту­ден­тов из при­выч­ной сре­ды оби­та­ния. По­это­му в ка­че­стве опе­ра­ци­он­ной си­сте­мы бы­ла вы­бра­на Windows, а в ка­че­стве сре­ды про­грам­ми­ро­ва­ния — Visual Studio. Кра­си­вый ин­тер­фейс Visual Studio из­на­чаль­но рас­по­ла­га­ет сту­ден­тов к се­бе. Они мо­гут по ша­гам вы­пол­нять свою про­грам­му, воз­вра­щать­ся на­зад, смот­реть и ме­нять зна­че­ния пе­ре­мен­ных, и да­же ме­нять ис­ход­ный код про­грам­мы без её пе­ре­за­пус­ка. По­ло­ви­ну все­го вре­ме­ни обу­че­ния сту­ден­ты ра­бо­та­ли со сво­и­ми про­грам­ма­ми в от­лад­чи­ке. В ре­зуль­та­те они с лёг­ко­стью мог­ли на­хо­дить ошиб­ки в про­грам­мах. Это, я счи­таю, са­мое глав­ное.

По­сле то­го, как я дал сту­ден­там об­щие по­ня­тия о пре­про­цес­со­ре, ком­пи­ля­то­ре, и ком­по­нов­щи­ке, я рас­ска­зал им сле­дую­щие ве­щи:

  • ба­зо­вые ти­пы дан­ных;
  • пе­ре­мен­ные;
  • функ­ции;
  • услов­ный опе­ра­тор if и опе­ра­тор цик­ла while;

Этих зна­ний хва­ти­ло для ре­ше­ния боль­шо­го чис­ла за­дач. Сту­ден­ты лег­ко справ­ля­лись с ре­кур­си­ей, усло­ви­я­ми и цик­ла­ми. Ни­ка­ких ука­за­те­лей и не­по­нят­ных за­го­ло­воч­ных фай­лов. Толь­ко функ­ции, со­здан­ные сво­и­ми ру­ка­ми. Пе­ре­мен­ные — ко­ро­боч­ки с дан­ны­ми, функ­ции — ме­ха­низ­мы для пе­ре­ма­лы­ва­ния этих ко­ро­бо­чек. Сту­ден­ты со­кра­ща­ли дро­би, вы­чис­ля­ли фак­то­ри­ал и чис­ла Фи­бо­нач­чи, рас­кла­ды­ва­ли чис­ла на мно­жи­те­ли...

При­шло вре­мя узнать про па­мять и ука­за­те­ли. Я рас­ска­зал о боль­шой ли­ней­ной вир­ту­аль­ной па­мя­ти, о ко­де про­грам­мы, о гло­баль­ных пе­ре­мен­ных, о ку­че и сте­ке, о ме­ха­низ­ме вы­зо­ва функ­ций и пе­ре­да­чи па­ра­мет­ров. И об ука­за­те­лях. Ко­гда сту­ден­ты в со­вер­шен­стве осво­и­ли ариф­ме­ти­ку ука­за­те­лей (вклю­чая опе­ра­тор ин­дек­са­ции), я дал им све­де­ния о ст­рук­ту­рах (struct), функ­ци­ях malloc и free. Ста­ло воз­мож­ным со­зда­вать мас­си­вы и бо­лее слож­ные ст­рук­ту­ры дан­ных: спис­ки, мат­ри­цы, и да­же ба­лан­си­рую­щие­ся де­ре­вья. Сор­ти­ров­ка, по­иск... на­бор ре­шае­мых за­дач рас­ши­рил­ся. Ну и ввод-вы­вод, ко­неч­но же; те­перь его мож­но бы­ло сме­ло да­вать сту­ден­там без рис­ка воз­ник­но­ве­ния не­вер­но­го по­ни­ма­ния.

Рас­ска­зы­вать про «стро­ки» по­сле это­го да­же не при­шлось. Над­пись char* бы­ла по­нят­на сту­ден­там без вся­ких объ­яс­не­ний, ведь это бы­ло под­мно­же­ством ра­нее прой­ден­но­го ма­те­ри­а­ла.

Мас­си­вы сту­ден­там я так и не рас­ска­зал. Это очень слож­ная, не­по­нят­ная вещь, осо­бен­но в мно­го­мер­ном слу­чае (мно­го­мер­ные мас­си­вы сту­ден­ты лег­ко де­ла­ли сво­и­ми ру­ка­ми). И, глав­ное, мас­си­вы аб­со­лют­но бес­по­лез­ны. Так ли ча­сто вы ис­поль­зу­е­те их в сво­их про­ек­тах?

P.S. А по­том на­чал­ся вто­рой се­местр. Ас­сем­блер, про­цес­сор, со­про­цес­сор, ре­ги­стры,... Сту­ден­ты пи­са­ли код пе­ре­мно­же­ния чи­сел с пла­ваю­щей за­пя­той (вклю­чая де­нор­ма­ли­зо­ван­ные чис­ла) при по­мо­щи би­то­вых опе­ра­ций, и срав­ни­ва­ли ре­зуль­тат «руч­но­го» пе­ре­мно­же­ния с ре­зуль­та­том со­про­цес­со­ра. Но это уже дру­гая ис­то­рия...

Шесть отзывов на запись «Как пре­по­да­вать Си?»

Воз­мож­но у вас оста­лись тек­сты лек­ций, ко­то­рые вы чи­та­ли? Ес­ли не труд­но дай­те ссыл­ку, ин­те­рес­но бу­дет по­чи­тать:)
Бы­ло бы не­пло­хо посмот­реть на этот курс. Сам сей­час один го­тов­лю, но не по Си и не­мно­го с дру­гой пред­по­сыл­кой, хо­тя в бу­ду­щем мне Си воз­мож­но по­тре­бу­ет­ся, да и па­ра­л­лель­ным кур­сом как раз с со­сед­ней ка­фед­ры его пер­во­курс­ни­кам чи­та­ют. Ду­ма­ем те­перь что­бы к се­бе на ка­фед­ру вер­нуть этот курс, а то там ни­че­му тол­ко­во­му не учат и вго­ня­ют на де­тей тос­ку. В ито­ге как раз мне и по­про­си­ли на­пи­сать и за­чи­тать курс по язы­кам про­грам­ми­ро­ва­ния с це­лью не от­бить охо­ту у де­тей за­ни­мать­ся этим и на­обо­рот при­влечь.
Tenormin 50 Mg
buy cheap antabuse
vpxl online
cefadroxil

Оставить отзыв

Жёлтые поля обязательны к заполнению

   

Можете использовать теги <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang=""> <div class=""> <span class=""> <br>