Pull to refresh

Comments 70

Позабавил тэг "разработка игр"

Автор, вот вы когда сами пишете этот хаос из if'ов, у вас ничего не щелкает в голове?

Возможно, немного не в тему, но:

А какой фидбек вы ожидаете?

То, что вы попробовали Си - это классно. В любом случае это новый взгляд на программирование и управление ресурсами.

То, что в программе есть что доделать - это тоже очевидно:

scanf("%s", p_choice); -> scanf("%99s", p_choice);

Результат scanf лучше контролировать, т.к. если вы введёте один пробел, то p_choice рискует остаться неизменным;

p_choice на старте лучше обнулить/очистить. Так-то она мусором заполнена, и если это мусор соответствует букве q, то программа сразу же выйдет;

т.к. в программе нет отработки "мусорного" ввода (на запрос ввели "123"), то можно сделать немного полегче-получше: пользователь что-то вводит и в цикле по трём строкам идёт сравнение: какой из вариантов он ввёл? Если ни одному не соответствует, то просим повторить. А если вариант найден, то дальше идёт сравнение чисел. ЧИСЕЛ, КАРЛ! Лучше сравнивать числа: 0 тупит 1, 1 разрезает 2, 2 обёртывает 0.

// окончание игры

if (strcmp("q", p_choice) == 0) {

printf("\nQuitting...\n");

}

можно заменить на просто printf ... - в этом месте p_choice и так равен "q".

Прим.: в нативных языках Си, C++ строковый тип считается "не простым" типом данных (в общем, то это так и есть для всех языков, просто это стараются скрыть в тумане). И поэтому от строк стараются "отойти": если можно переключиться на числа - то лучше работать с числами.

Благодарю за критику. Обязательно приму во внимание Ваши советы.

Там вообще можно сравнение в два условия запихать если нумерацию перевернуть: 0 побеждает 2, а остальные тупо по увеличению значения..

А ведь вы правы. Надо бы мне побольше мыслить числами

В C если тело оператора if состоит из одного оператора, то фигурные скобки можно не писать, на 8 строк меньше.

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

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

Меня уже поставили в известие. Насколько я помню, из-за моего просчета (я не заключил "яблоко рандома" в цикле while) выбор выполняется только один раз, так что выбор тоже будет идти только однажды. Благодарю за комментарий.

Не совсем. Вызов srand() нужно оставить вне цикла, а вот вызов rand() внести вовнутрь.

Откуда вообще вы взяли термин яблоко рандома?

Для людей экономящих фигурные скобки после ифа в аду предусмотрен отдельный котел. Имхо).

Привет из котла

А вот MISRA C:2012 правило 15.6 рекомендует ставить фигурные скобки во всех случаях. Потому что сегодня там одна строка, завтра две. Да и читаемость улучшается

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

Ожидаю фидбека в комментариях!

Напрашиваетесь, сударь, напрашиваетесь...

Вы там, в Питоне своём, как сыр в масле катаясь расслабились до наивности детской. Хотите приложение под Андроид - Kivy, хотите фронтенд - да хоть Anvil.works, и так со всем - Питон и ещё совсем чуть-чуть дают результат. А на С - стоит выйти за вот такую ножницы-бумагу... Андроид приложение - извольте, SDK, NDK, Native Activity и куча подробностей, с которыми можно разобраться, но изложены они с точки зрения Котлина, а то и Джавы. Фронтенд - а Вам какой, на Emscripten или Clang/LLVM? Ну и кусок JavaScript в придачу.,

То, что Вы увидели на ножницах с бумагой - это парадный фасад, а на деле может быть так, что пока Вы, пытаясь получить реально полезный результат, будете учить С, а на это неделя по вечерам уже много, и всю обвязку что и есть задница, можно будет выучить весь Rust и получить тот же результат от Cargo, потом выучить Go и получить результат ещё раз от Go (замечаете - и того проще чем с Растом), а остаток времени провести в душевных метаниях - может быть надо было сразу отдаться, ну или примкнуть к, Flutter?

С Flutter, кстати, возможен пример. На Python вы берёте Flet и ездите на Flutter фрирайдером. На C - сначала Dart, потом Flutter, потом Dart FFI и только потом вопрос "а ради чего?". Если кто-то поклялся Вам хорошо платить за C, ну знает или думает что знает ради чего, это одно дело, а если нет...

Так что от меня фидбек такой - бросайте эту ерунду, вы знакомитесь с С так, как это делали тогда, когда альтернатив не было. Вы питонист? Отлично, напишите модуль на С. Убедитесь, что он и на Андроид, с тем же Kivy например, тоже работает. Напишите что-нибудь на SDL или Qt. И только после этого у Вас появится право решать - понравился С или нет.

Разве C не учат перед C++? В моем видении C — только промежуточная ступень, чтобы получше разобраться в тех же C++/Rust. Хотя, по такой же логике, перед C стоило бы посмотреть на Go/CSharp.

Если вам интересен C++ или Rust, то для этого совершенно необязательно учить C. В случае с C++ многое из того, что вы освоите в C будет доступно, но категорически не рекомендовано к использованию. Нет ничего плохого в изучении C, если он интересен сам по себе, но врядли полезно, как подготовку к изучению того же C++

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

Ну, писать на C++ как на python у вас всё равно не получилось бы, как не получилось на C. И не стоит ожидать, что C можно плавно "перетечь" в C++. Зная C, можно легко начать писать работающие программы, которые будут компилироваться C++ компилятором. Но для идиоматичного кода придётся учиться заново, местами переучиваясь от привычек из C

Можно знать C и не знать ничего больше, его достаточно для многих применений.

Если очень постараться, то можно и API для бэкенда написать на C.

Я сегодня ради эксперимента взял ИИ (я все еще не умею писать на C, могу только вникать в код) и провел бенчмарк FastAPI-обертки + бэкенда на C против уже существующей этой же обертки на TS. Суть программы была в том, что это была админ-панель (пользователи могли регистрироваться, а админы могли их банить).

Я построил архитектуру так, что Python асинхронно сгребает в батчи (10, 50, 100, 200) запросы и посылает их в C-бэкенд. С количеством обрабатываемых батчей росла и скорость обработки (98× скорости при батче в 200 запросов, и оно шло только вверх по метрике!)

На моем динозавре 2009 года с 6 ГБ ОЗУ оно летало. Я завтра попробую уйти от PostgreSQL и посмотреть в сторону RocksDB, там должно быть еще больше. C++ тоже мне интересен, но я пока не буду его трогать, пусть и знаю несколько прикольных фреймворков для обработки данных

Разве C не учат перед C++?

Наверняка есть и такие случаи, когда учат. Иначе вот такое вот без надобности было бы.

Sic!
Sic!

C и C++ языки очень разные. То, что они местами внешне похожи - следствие того, что на момент создания плюсов поголовно все заинтересованные лица знали C. Далее сходство сохраняли как дань традиции, но сами ответственные лица подчёркивают - это ни в какой степени не являлось целью и делалось строго по возможности.

Изучать C ради лучшего последующего изучения плюсов - ошибка. Чтобы C просто не мешал, его нужно не только основательно изучить, но и к нему привыкнуть, чтобы языки не смешивались один с другим. Если хочется и C и C++, тогда хорошо, если только плюсы - двойная работа в лучшем случае.

Ниже Вы пишете

Тогда я просто начал бы писать на C++, как на Python.

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

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

Например, заинтересовала тема функционального программирования (спецом подальше от C). Тогда можно прочитать про функциональное программирование и подумать как это будет на своём Пайтоне. Где именно прочитать, я не знаю, однако. Если Вы тоже не знаете, ну не удалось выяснить, то берёте книгу по функциональному языку, скажем по Лисп, и читаете по диагонали. Далее то же самое - уложить идеи на Пайтон. Ключевое слово - по диагонали, то есть никак не выучить.

Применительно к C или плюсам - посмотрите на Ассемблер и, если не в курсе то обязательно, на архитектуру машины, особенно на систему прерываний.

А что учить легче — C или плюсы? Не по отделению "по какому языку материалов больше", а скорее по именно усвоению материала

На мой скромный взгляд, чистый Си учить намного легче. Вот совсем (и намного) легче. На C++ одни пляски с шаблонами чего стоят!

НО: если рассматривать условно "большие" проекты, то более понятный, чистый, корректный код будет скорее всего на C++ (конечно, если вы на нём умеете). Просто потому, что стандартных средств для типовых задач - их намного больше. И контроль типов лучше. Повторюсь: это всё работает, если вы умеете "в плюсы". Если вы будете на C++ писать как на чистом Си (многие так и делают и это работает) - тогда преимуществ не будет.

Получается, что на C++ в сложности обучения идет кривая до небес, а после этого плато?

Попробую дать другую аналогию (скорость + дистанция) (также: сравнение с Питоном сделано для контраста, не нужно сильно придираться):

== Задаём скорость:

Питон - это как передвижение по просёлочной дороге (утоптано, умято, вполне ровно);

Си - это передвижение по перепаханному полю (вроде не проваливаемся по пояс, но если побежим, то можно и ноги повредить);

C++ - это передвижение по утрамбованному полю (двигаемся медленно, но возможность повредить ноги снижается).

== Включаем дистанцию:

Начинающий разработчик - ну что там говорить - это быстро везде, особенно с ИванИванычем;

Продвинутый разработчик:

на Си - добраться до деревни в 5 км на север;

на Питоне - это обойти 10 полян на севере на расстоянии 10 км;

на C++ - это побывать во всех полянах на севере на расстоянии 10 км.

---

А теперь переходим к исходному вопросу: что легче? По-моему, легче прийти в одну известную недалёкую точку, хоть и по перепаханному полю.

Очевидно, у Вас возможны другие приоритеты. Банально, разный темперамент может повлиять: кто-то не готов "медленно, в одном направлении, а деревни всё ещё не видно".

---

Прим.: по-моему, кривая обучаемости здесь несколько неинформативна, т.к. объём навыков (ордината графика) сильно разная - количество полян отличается очень-очень. Соответственно и сравнивать крутизну некорректно.

Прим.Прим.: В C++ нет как таковой сложности обучения до небес (например, если что-то не знаете - то вообще босса не замочить ничего сделать нельзя): если что-то слишком сложно, то вы такими средствами не пользуетесь (или используете готовые библиотеки) - и всё ок.

Так красиво расписано все... В поэты бы Вам.

Прим.Прим.: В C++ нет как таковой сложности обучения до небес (например, если что-то не знаете - то вообще босса не замочить ничего сделать нельзя): если что-то слишком сложно, то вы такими средствами не пользуетесь (или используете готовые библиотеки) - и всё ок.

Босс: ты же знаешь С++, у нас на новой платформе проект не собирается, что то с бустом, поправь...

Нет, потом следующая кривая до небес. Первая была еще пологой =)

Сам язык С максимально простой, но при этом и за программиста он ничего не делает. Поэтому за всеми подводными камнями нужно следить самостоятельно.
С++ может взять на себя рутину, но надо знать что написать.

void lower(char *str) {
	for (int i = 0; str[i]; i++) {
		str[i] = tolower(str[i]);
}

А теперь используем:

...
char just_char_array[] = {'e', 'n', 'd', 'l', 'e', 's', 's', ' ', 'F', 'u', 'n'};
lower(just_char_array);
...

Наслаждаемся UB.

Напомню две вещи:

  • Этот код я написал на второй день своего изучения C, причем не обошлось без интенсивного поиска информации по абстрактной логике, не говоря уже о багах и сегфолтах;

  • Код функции предназначен для строк, а не для массивов со строками

Я ценю и уважаю Ваш профессионализм, но надо же вникать в контекст ситуации.

Я же по этому поводу:

Ожидаю фидбека в комментариях!

Ничего страшного, научитесь еще.

  • Код функции предназначен для строк, а не для массивов со строками

И про этот "маленький" нюанс узнаете в процессе.

Прозвучало как страшное предзнаменование. Спасибо за предупреждение.

Указатели, массивы и строки, их взаимосвязь и то, как они передаются (или возвращаются) в функции — очень интересные темы и не такие уж сложные, как может показаться с первого взгляда. Вам должно понравиться.

Это и вправду так. scanf() дался мне очень легко, да и строки вида printf("Значение: %d", num) я полюбил даже больше питоновского форматирования строк. Я сам в предвкушении будущей работы с ними.

С "дружелюбным" scanf() Вас тоже ждёт сюрприз. Если Вы свою текущую программу на си будете вызывать на беке с передачей туда пользовательского ввода, то дадите remote code execuition.

Дело в том, что scanf не проверяет размер целевого буфера, т.к. физически не может это делать не зная его размер. В итоге он проедется по стеку, делая типичный buffer overflow. В умелых руках этого достаточно для атаки.

scanf("%99s", &p_choice) //ограничивает до 99 символов

Начните с Столярова, иначе сищность головного мозга не избежна

В его программе все char* заканчиваются нулями (из-за инициализации списком, надо же, сделали такое в C), поэтому UB не будет.

Поправка: scanf формирует null-terminated последовательность char, поэтому в случае p_choice UB тоже не будет.

Хорошо было бы предложить решение, которое бы позволило в данном случае избежать UB. Вопрос только в том, существует ли оно.

UFO landed and left these words here

Я просто не понял, что @Serpentine предлагает сделать, чтобы избежать UB непосредственно в функции lower. Какой бы тип не был выбран для строки(указатель, указатель+длина), всё равно пользователь функции сможет передать испорченные данные.

Последовательность char just_char_array[] должна обязательно заканчиваться нулем '\0', иначе это некорректная строка C.

А это не строка. Это массив, вообще-то. Сами-то посмотрите, что у вас объявлено - массив char.

Все верно, массив char содержит NUL-terminated строку C, т.е. последовательность символов, которая заканчивается символом NUL (\0).

Ваше утверждение было бы верно, если бы там был строковый литерал, но его там нет.

char arr1[] = "abc";         ///< вот тут есть null в конце
char arr2[] = {'a', 'b', 'c'}; ///< а вот тут нет

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

Я, зная и Си и ассемблер и ещё много других классических языков, точно также буду плеваться от Питона, который не знаю вообще.

Ассемблер пока отложим — кто знает, что будет через месяц

UFO landed and left these words here

Можно полный код такой версии?

UFO landed and left these words here

Гораздо больше 25 строк будет, однако

Недавно я задумался: Python — не единственный инструмент, которым я хочу оперировать в своих инструментах. Python, понятно, легко освоить и он применяется везде, но язык-то не идеальный!

«Неверная» постановка вопроса! Питон – язык идеальный, но, только для своего класса задач. Это – подготовка и обработка данных. Всё! Для работы с графикой, видео, звуком, ГУИ (графическим интерфейсом пользователя), потоками и много чем еще, выгодней использовать С++ с фреймворками.

Я лично предпочитаю WTL, библиотеку кода, занимающую, в исходниках, менее полутора мегабайт! На базе чего написал свою обучающую систему «Леколь» (см. https://lecole.free.nf/ и мои статьи, здесь).

У меня есть, также, неопубликованная программа для работы с медиа-файлами: «МедиаТекст».

Для загрузки любимых видосиком, написал графическую обёртку «MiniDL» для известной консольной утилиты «yt-dlp.exe» ( https://habr.com/ru/articles/955838/ )

Короче говоря, C++ / WTL – рулит! А вот данные для обучающей программы и видео, с двуязычными субтитрами делал на Питоне. Для подобных задач – ему цены нет!

Но, если надо скачать, допустим, онлайн-словарь, для изучения иностранного языка, то для борьбы с капчей, лучше использовать не Питон (там «дорогое» решение), а расширения для старой версии «Хрома», поддерживающую вторую, а не третью версия манифеста. Ибо, последняя – более ограничительная для подобных целей.

Короче, для разных задач – свое ПО!

А «чистый» Си, это, скорее, для нижнеуровневого и консольного программирования. Например, чтобы реализовать собственные видеоплейер в оконной программе, я взял опенсорсный «FFplay.c», переделал его в классы С++ и спокойно подключил к своему проекту. Кстати, ничего путного, на эту тему, на Гитхабе, я так и не нашел.

Так что, не делайте концептуальных ошибок и будет вас счастье!

А вы C++ с нуля учили?

Я все языки учил по принципу: Берешь простой прототип, компилируешь. Либо запускаешь на исполнение, если скрипт. Потом, экспериментируешь с кодом, пока не врубишься, что к чему. Книги по языку и документацию, особо, не читал. Из-за чего много времени приходилось сидеть в Интернете, в поисках подходящего прототипа. Сейчас, благо, есть ИИ-сервисы, которые в части поиска нужной информации представляют собой «Интернет-2.0».

Вообще-то, кормил меня язык «1С77». Проще учетной платформы не существует. Единственный минус – программистов «конфигурастов» никто за программистов не считал. Параллельно, я начал, на работе, осваивать ассемблер и декомпиляцию бинарного кода (см. мой сайт https://erfaren.narod.ru/ ). Этого оказалось мало, поэтому перешел на освоение С++. Сначала с MFC, потом с WTL. Последний прижился, пользуюсь им до сих пор. Затем был Питон и т.п. Для них в Visual Studio С++ существуют мастера, которые генерят различные прототипы кода. С их разбора я и начинал освоение языка. Плюс очень много помогал, в свое время, сайт codeproject.com (сейчас он в упадке). Не говоря уже о Гитхабе.

Мужик, ты задолбал с саморекламой

Мужик, ты задолбал с саморекламой

Мужик, ты не одинок в своих чувствах! Меня тоже достают пустые статьи, где много общих слов и ни одного конкретного примера. Я, конечно, повторяюсь, но по делу. Реплики делаю по существу, а не ради рекламы (смысла в которой нет никакого!). Реагируйте на них тоже по существу – будет предметный разговор. Но, обычно, авторы простых статей, сгенерированных ИИ-ями, хотят только, чтобы их хвалили, какие они молодцы, что научились промпты писать, либо никак не реагировали. Однако, критики боятся – в Интернет не ходить! Здесь все-таки технический форум, а не просто тусовка школьников. Что подразумевает некий уровень в текстах. Удивляет, что многим просто нечего сказать в ответ. Зачем тогда вообще ходить на технический форум? Есть другие площадки, попроще.

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

Зачем сравнивать строки? Можно изначально присвоить номер для введённого слова и пробросить через switch...

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

Наконец то хоть кто-то осмелился подобное написать. Это очень забавно со стороны выглядит.

Респект автору!

Было приятно получить подобный комментарий, спасибо! Кстати, определите, пожалуйста, "осмелился".

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

Но самое главное преимущество языка C именно для обучения - это возможность выстрелить себе в ногу в каждой строчке. Это позволяет ещё лучше понять железо, а потом писать более эффективный и разумный код на языках, предоставляющих инструменты защиты от утечки памяти. Ведь на самом деле утечку памяти можно прекрасно устроить и на Rust. И та база, которую вам даст боль от C, пригодится вам везде.

Поздно учить С, если учился начиная с Питона.

Будет теперь такой код, как в статью писать.

Надо память ресетить =)

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

Никогда не поздно, поверьте

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

По Моему мнению, любой программист, вне зависимости от используемого ЯП, платформы и фреймворков, должен "уметь в C", иначе компьюер и программы будут касатся непонятным чёрным ящиком, имхо.

Всегда пугало привидение типа.

Sign up to leave a comment.

Articles