LINUX.ORG.RU
ФорумTalks

Что-то конкурсов у нас давно не было... где моя K&R !

 , , , ,


0

6

Итак, взял я на досуге почитать незабвенный сабжевый труд наткнулся на задачу 6.1 — доработать функцию getword,

чтобы она корректно обрабатывала символы подчеркивания, директивы препроцессора, комментарии и строковые константы.

Программа, которую следует усовершенствовать такова:


#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define MAXWORD 100
#define NKEYS (sizeof keytab / sizeof keytab[0])

struct key 
{
  char *word;
  int count;
} keytab[] = 
  {
    "auto", 0,
    "break", 0,
    "case", 0,
    "char", 0,
    "continue", 0,
    /*...*/
    "unsigned", 0,
    "void", 0,
    "volatile", 0,
    "while", 0
  };

int getword(char *, int);
int binsearch(char *, struct key *, int);

/* count C keywords */
int main(void)
{
  int n;
  char word[MAXWORD];

  while(getword(word, MAXWORD) != EOF)
    if (isalpha(word[0]))
      if ((n = binsearch(word, keytab, NKEYS)) >= 0)
	keytab[n].count++;
  for (n = 0; n < NKEYS; n++)
    if (keytab[n].count > 0)
      printf("%4d %s\n",
	     keytab[n].count, keytab[n].word);
  return 0;
}

/* binsearch: find word in tab[0]... tab[n-1] */
int binsearch(char *word, struct key tab[], int n)
{
  int cond;
  int low, high, mid;

  low = 0;
  high = n - 1;
  while (low <= high)
    {
      mid = (low + high) / 2;
      if ((cond = strcmp(word, tab[mid].word)) < 0)
	high = mid - 1;
      else if (cond > 0)
	low = mid + 1;
      else return mid;
    }
  return -1;
}

/* getword: get next word or character from input */
int getword(char *word, int lim)
{
  int c, getch(void);
  void ungetch(int);
  char *w = word;

  while (isspace(c = getch()))
    ;
  if (c != EOF)
    *w++ = c;
  if (!isalpha(c))
    {
      *w = '\0';
      return c;
    }
  for ( ; --lim > 0; w++)
    if (!isalnum(*w = getch()))
      {
	ungetch(*w);
	break;
      }
  *w = '\0';
  return word[0];
}

#define BUFFSIZE 100

char buf[BUFFSIZE];  // buffer for ungetch
int bufp = 0;        // next free posotion in buf

int getch(void)      // get a (possibly pushed back) character
{
  return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)  // push back on input
{
  if (bufp >= BUFFSIZE)
    printf("ungetch: too many characters\n");
  else buf[bufp++] = c;
}

Я конечно все понимаю, но у меня вопрос, неужели для решения данной задачи в Си, который известен кратким и гибким синтаксисом, для вышеуказанного фикса нужно городить вот такую вот портянку?

Пример решения взят мной с clc-wiki.net

sudo cast beastie, tailgunner и все сишники включая Царя ;-)

Хочу увидеть краткий, красивый, ёмкий пускай и не быстрый код, реализующий эту задачу :-)

Вперёд!

Перемещено tailgunner из development

★★★★★
Ответ на: комментарий от MKuznetsov

понимали зачем нужен lex(flex) и что он делает внутри..

Т.е. набить шишек в процессе решения задачи и привлечь внимание обучаемого к парсеру грамматики?!

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

Т.е. набить шишек в процессе решения задачи и привлечь внимание обучаемого к парсеру грамматики?!

а как ты догадался ? ТЫ ЗНАЛ ?!

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

Хм, сарказм?

Нет, просто если решение задачи порождает такой код,

значит пора брать какой-то качественно иной инструмент.

Пирожок с полки взять можно?! :-)

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

Пирожок с полки взять можно?! :-)

нет. надо таки предварительно решить исходную задачу :-) хотя-бы в виде простыни, если кажется простым то с разумными ограничениями..например с запретом адресной арифметики, предположи что у тебя Паскаль - мелочь вроде бы, но доставит гемороя

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

который известен кратким и гибким синтаксисом

Если синтаксис языка краткий и гибкий - это ещё не значит, что код на этом языке будет кратким и гибким. Зато ты можешь выстрелить в ногу решить задачу кучей способов, с применением кучи неочевидных хаков.

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

Ну напиши мне на «каком-то» куллязычке то же самое, чтобы код был «кратким и гибким». Даже подскажу - единственный твой шанс - это что-то типа: reremove(«\#(.+(\\\n).+)+»), раз у пацана там не смоглось с «дерективами пп».

registrant27492
()
Ответ на: комментарий от Twissel

Нет. Просто тот, кто составлял эту задачу - днище заморское.

привлечь внимание обучаемого к парсеру грамматики?!

То же нет.

Никому не интересно и не нужно писать «парсеры» - всем нужно и интересно писать генераторы.

registrant27492
()
Ответ на: комментарий от MKuznetsov

например с запретом адресной арифметики, предположи что у тебя Паскаль

Оффтоп, что-то я не припомню, честно, какие там у Паскаля ограничения на адресную арифметику?

Хоть это и не принципиально, в данном конкретном случае.

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

Ну напиши мне на «каком-то» куллязычке то же самое, чтобы код был «кратким и гибким». Даже подскажу - единственный твой шанс - это что-то типа: reremove(«\#(.+(\\\n).+)+»), раз у пацана там не смоглось с «дерективами пп».

Ты не умеешь в автоматы, да?

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

Причём тут автоматы? Автомат нихрена не «краткий» и нихрена не «гибкий». Что сказать-то хотел? Или он на каком-нибудь жабаскрипте будет более краткий, чем на си? Развивай тему.

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

Причём тут автоматы?

Тебе интересно какая связь между ЛА и автоматами? В экстремальных случаях ЛА умудряются делать через регулярки. Подумай почему.

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

Конкретное что-то будет, либо так и дальше будешь кукарекать что-то невнятное?

Тебе задали вопрос - тебе надо ответить в контексте, в котором задан вопрос. А не нести какую-то неведомую херню.

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

Тебе задали вопрос - тебе надо ответить в контексте, в котором задан вопрос. А не нести какую-то неведомую херню.

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

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

Слив засчитан. Какие же там у тебя реальный задачи, что твой уровень развития не позволяет тебе ответить в темке на лоре не обделавшись при этом. А основная проблема в чём? Попытался выставить себя «шарящим», выкатывая ключевые слова, а после оказалось, что высер-то никуда не годиться и не имеет смысла. Такие дела.

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

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

Не пытался. Обычно это делаешь ты. Зачем отбирать у тебя работу?

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