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

★★★★★

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

Дык, напиши, что интересно и нужно народу? Мой вариант: плезиозавры. Нужны просто позарез.

anonymous
()

зачем нужно городить вот такую вот портянку?

чтобы блджат понимали зачем нужен lex(flex) и что он делает внутри..это просто учебный пример, который каждый должен решить сам за себя

ps/ когда-то давным давно сам-для-себя ставил искусственную цель - обогнать cat в синтетических тестах. Желающие могут повторить этот фейл

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

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

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

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

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

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

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

Хм, сарказм?

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

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

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

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

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

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

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

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

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

Deleted
()

больные

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

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

И зачем вообще ты адептов кастишь - ты хоть раз видел от них нормальный код, а не тонну лапши?

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

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

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

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

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

То же нет.

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

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

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

Он не это делает внутри.

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

Уровень детсада.

ps/ когда-то давным давно сам-для-себя ставил искусственную цель - обогнать cat в синтетических тестах. Желающие могут повторить этот фейл

Смешно. А, дак ты ещё и не смог. Отличная история. Давай я тебя научу:

int main(int argc, char * argv[]) {
  return !!sendfile(STDOUT_FILENO, open(*(argv + 1), O_RDONLY), &(off_t){0}, 1024 * 1024 * 1024 * 1024ul);
}

Обгоняет cat в 10раз, есличё.

Всегда удивляли эти куллстори про задачи - перед тем как ставить «задачи» и что-то там мерить - надо понимать что ты меришь и что обгоняешь. А так да, если днище, то так и будешь до скончания веков соревноваться с read+write - что ты там хотел «обогнать»-то? Мне даже неведомо. Ну это такое - спрашивать про логику от куллпацанов.

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

Обгоняет cat в 10раз, есличё.

:-) вот на это и клюёт школота... а теперь открой man cat, исходник и посмотри как и что делается :-)

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

:-) вот на это и клюёт школота...

Смешно когда днище тебе что-то рассказывает.

а теперь открой man cat

Открыл - дальше что? Почему так трудно вякнуть что-то конкретное и вразумительное, а я тебе отвечу - ибо вякнуть-то нечего.

исходник и посмотри как и что делается :-)

Опять же - балаболка боится что-то конкретное сказать и прячется за невнятным. В целом твоя реакция понятна, ибо я уже надрессировал вас на «вякнул что-то конкретное - обделался».

Ну предъяви мне что-то конкретное уже.

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

Смотри,

Рассмотрим программу, определяющую число вхождений каждого ключевого слова в текст Си-программы.

Эта программа реализована в ОП на массиве структур, далее авторы ставят задачу

Haшa вepcия getword не обрабатывает должным образом знак подчеркивания,

строковые константы, комментарии и управляющие строки препроцессора.

Напишите более совершенный вариант программы.

Другой вопрос, что значит должным образом, т.е. можно сделать функцию типа:


int acceptable(char c)
{
  return  ((c == '_') || (c == '"') || (c == '#') || (c == '/') || isalnum(c));
}

И пойти за пирожком, но ведь так не честно, правда?!

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

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

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

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

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

Эта программа реализована в ОП на массиве структур, далее авторы ставят задачу

Какие массивы? Чего массивы?

Другой вопрос, что значит должным образом, т.е. можно сделать функцию типа:

Выше я уже написал, что значит должным образом. Нельзя.

Ну можно забахать однострочники.

char * skip_pp(char * str) {
  return ({while((str = strchrnul(str, '\n')), *str && (*(++str - 2) == '\\'));str;});
}

char * skip_mlc(char * str) {
  return ({while(*str && (!((*str == '*') & (*(str + 1) == '/')) || ((str += 2), 0))) ++str;str;});
}

Комменты типа // скипаются просто вызовом strchr(), но в любом случае там надо писать детектилку всех этих случаев, либо впиливать в каждую самодетект и вызывать их все подряд.

Ах да, функции на работоспособность не проверял.

И пойти за пирожком, но ведь так не честно, правда?!

Не честно что?

Я не понимаю - чего ты хочешь?

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

Я не понимаю - чего ты хочешь?

Хотел увидеть рабочий код,

нормально реализующий данную задачу, покороче, чем ~400 LOC.

Но, похоже, это невозможно.

Какие массивы? Чего массивы?

Почитай 6-й раздел K&R, тогда поймёшь о чем я.

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

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

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

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

Хотел увидеть рабочий код,

Ни та ни та портянка, которые ты запастил - не делает то, что нужно тебе.

нормально реализующий данную задачу, покороче, чем ~400 LOC.

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

Почитай 6-й раздел K&R, тогда поймёшь о чем я.

Зачем мне читать это днище - зачем ты ссылаешься и прячешь за кого-то? Сказал - отвечай сам.

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

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

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

это днище

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

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

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

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

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

Зачем мне читать это днище - зачем ты ссылаешься и прячешь за кого-то? Сказал - отвечай сам.

У нас тут свободное общение если что,

так что я совсем не понял причем тут игра в прятки.

Есть ОП, там все ясно сказано, есть ответы.

Я здесь, я с тобою и никуда не прячусь.

А если ты хочешь просто поскандалить, ты обратился не по адресу ;-)

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

А если ты хочешь просто поскандалить, ты обратился не по адресу ;-)

Заметь, ты сам его пригласил.

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

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

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

registrant27492
()

включая Царя

Вот это верно. Этот человек решит данную задачу, быстро и оперативно, без воды, как некоторые, чисто конкретно, просто возьмет и напишет как надо.

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

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

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

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

так что я совсем не понял причем тут игра в прятки.

Дело было так:

Эта программа реализована в ОП на массиве структур, далее авторы ставят задачу

Какие массивы? Чего массивы?

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

Есть ОП, там все ясно сказано, есть ответы.

Там ничего не сказано. Ты выклал это:

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

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

int acceptable(char c) {
  return  ((c == '_') || isalnum(c));
}

директивы препроцессора

Тебе дали функцию.

комментарии

Тебе дали функцию.

строковые константы

Этого я не увидел, но это делается функцией пропуска препроцессора с заменой одного символа.

Я здесь, я с тобою и никуда не прячусь.

Прячешься. Зачем ты заигнорил это?

И пойти за пирожком, но ведь так не честно, правда?!

Не честно что?

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

А если ты хочешь просто поскандалить, ты обратился не по адресу ;-)

О боже. Тебе задают конкретные вопросы - ты их игнорируешь. В чём твоя проблема? А виноват оказывается я.

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

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

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

Царь не решает дерьмо для школьников, которое ему не интересно форфан.

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

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

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

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

+1

Очередная попытка социализации Царя провалилась, плак, плак!

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

Тебе надо ответить на конкретные вопросы - что ты там реализовал и причём тут массив структур.

То есть, начнём с того, что кода в ОП,

кроме pastebin ты в упор не видишь,

ну ОК, тогда все ясно ;-)

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

((c == '_') || isalnum(c));

Не делай так, это лишнее условие. Посчитай табличку значений и используй её.

i-rinat ★★★★★
()
Ответ на: комментарий от arturpub

Честно, пока нет времени )))

Но, если тред не потрут за «психоделические сентенции» некоторых, обязательно

напишу сюда свои 5 копеек.

А свой код на 60 покажешь?

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

Нет, там все в лучших традициях перл-ниндзя, только на сишке. Порядочные люди такое не выкладывают. Но в целом там страйфорвард автомат, хавающий альфу, дробь, кавычку, прочее и юзающий bsearch по массиву кейвордов с кол-вом. Без маллока и ангетов, но с лукахедом для // и /*.

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

в последнем издании «как написать компилятор» автор указал что отказался от бинпоиска в пользу линейного ибо для современных железок при тех размерах ускорение(если оно вообще есть) не перевешивает усложнения кода учебного.

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