Задать вопрос
Ответы пользователя по тегу C
  • По какой книге изучать язык Си: Эффективный Си или k&r?

    @res2001
    Developer, ex-admin
    KR не учебник и не стандарт, написана давно. Хотя есть довольно свежее издание, но текст не изменился.
    Берите Эффективный Си, хотя я не читал эту книгу, но выглядит норм. К тому же написана на основе свежих стандартов, в отличии от KR.
    У вас не плохой бэкграунд, сам язык достаточно прост, разберетесь с тонкими местами (массивы, строки, динамическая память, указатели, адресная арифметика) и можно начинать что-то делать.
    По функциям стандартной библиотеки полно информации в интернет, например тут
    Вообще книг на русском именно по Си не много, возможно это связано с тем, что язык достаточно прост и одна хорошая книга закрывает большую часть потребностей.
    Кстати, "экстремальный Си" выглядит то же многообещающе, но это, похоже, уже следующий уровень.
    Ответ написан
    3 комментария
  • Почему программа на C не выводит результат?

    @res2001
    Developer, ex-admin
    Не используйте pow. Она работает с double, а это числа с плавающей точкой. У double точность примерно до 15 значащих десятичных цифр, дальше все приближенно. https://en.wikipedia.org/wiki/IEEE_754#Basic_and_i...
    У вас целочисленная арифметика везде - просто домножайте каждую итерацию на 10. И не забывайте везде использовать long long.
    Вам же уже давали пример в одном из прошлых вопросов.
    И n там вроде - 18.
    Ответ написан
  • Из-за чего программа на C выдаёт неправильный ответ?

    @res2001
    Developer, ex-admin
    Потому что целочисленное деление: a / r дает в результате 2 без остатка. Вам нужно преобразовывать в числа с плавающей точкой, выполнять деление с плавающей точкой и получать остаток с помощью modf.

    Еще пара замечаний:
    1. явно ведь ваш алгоритм начинается с 12, т.к. это первое число с более 1 цифрой в составе, у которого младшая цифра двойка. Так что все что меньша 12 нет смысла перебирать.
    2. Нет смысла увеличивать а на 1 - увеличивайте сразу на 10, т.е. к следующему варианту с двойкой в конце, зачем перебирать варианты, которые вы пропустите. Кроме того в этом случае count можно не расчитывать так как делаете сейчас, а просто добавлять 1 каждые 10 итераций.
    Ответ написан
  • Нужно сделать циклический сдвиг вправо на 8 позиций. Считать из файла и записать в файл. Что не так?

    @res2001
    Developer, ex-admin
    Алгоритм циклического сдвига описан в старинной книге Джона Бентли "Жемчужины программирования".
    https://codelib.ru/task/cycle_shift/
    Ответ написан
    Комментировать
  • Как сортировать данные структуры по дате, если дата задаётся символьной строкой?

    @res2001
    Developer, ex-admin
    1. Строки сравниваются с помощью strcmp. Когда вы сравниваете так как у вас в коде, то вы сравниваете значения указателей, а не то на что указывают эти указатели.
    2. Чтобы сравнить числа в строковом представлении, строки должны быть одинаковой длинны, т.е. число в строковом представлении с меньшим количеством знаков должно быть дополнено слева нулями до длины большего числа (или дополнять оба числа до какой-то фиксированной длины).
    3. Когда у вас "склеено" несколько чисел в строку (каждое из чисел дополнено нулями), то порядок склейки для сортировки должен быть от большей сущности к меньшей. В вашем примере в начале строки должен идти месяц, а затем день.
    Только применив все три пункта вы сможете правильно отсортировать подобные строки.
    Все это кратко изложил jcmvbkbc в своем ответе.

    Но! Вам ничего не мешает сразу же при вводе преобразовывать дату в числовое представление и сортировать уже числа. Это будет гораздо быстрее, чем решать проблемы с текстовой сортировкой.
    Ответ написан
  • Задача на строки в Си: как конкатенировать строки без библиотечных функций(старый вопрос удален)?

    @res2001
    Developer, ex-admin
    Как можно было сделать то же самое, но при помощи традиционной обработки массива?

    А что такого по вашей ссылке не традиционного в смысле обработки массива? Там вполне традиционные операции.
    Видимо вы привыкли, что обращение к элементам массива это arr[i]. Но это лишь один из вариантов.
    Вариант примененный в коде по ссылке - инкремент указателей - просто смещает указатель на следующий элемент массива. По идее это должно работать немного быстрее, чем arr[i].
    Кстати, принцип работы итераторов в C++ std как раз тот же самый, что использован тут. Так что можете считать, что dest и src это итераторы по строке :-)

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

    По ссылке, реализован аналог strcat, но эта функция (так же как и функция по ссылке) может приводить к выходам за пределы массива, т.к. тут вообще ни как не контролируется размеры массивов. Было бы интересно реализовать аналоги strncat или strncat_s.
    Ответ написан
    Комментировать
  • Как сделать сортировку Шелла на Си?

    @res2001
    Developer, ex-admin
    Возвращайте значение iterations из shellsort. В main суммируйте эти значения и в конце находите среднее.
    Ответ написан
    Комментировать
  • Как правильно использовать указатель?

    @res2001
    Developer, ex-admin
    Когда вы передаете в функцию указатель на объект (на что угодно), это значит, что вы можете в функции изменять этот объект и все изменения будут видны вызывающему коду.
    Если вам надо что бы вызывающий код увидел новый указатель, то передайте в функцию указатель на указатель:
    int next_edge(edge_t **out_edge)
    {
      edge_t * tmp = malloc(sizeof(edge_t));
      if(tmp)
      {
         *out_edge = tmp;
         return 1;
      }
      return 0;
    }

    Но обычно проще в таком случае возвращать указатель в возвращаемом значении. Вызывающий код может сравнить возвращенное значение с NULL для выяснения того вернула функция нормальный указатель или произошла ошибка. Так делает, например, функция malloc().
    Ответ написан
    2 комментария
  • Почему массивы в Си заполняются "М"?

    @res2001
    Developer, ex-admin
    Не заполняются они М.
    Если объявляется массив автоматический на стеке без инициализатора, то просто отводится память на стеке (уменьшение/увеличение регистра счетчика стека), никаких "теневых" присваиваний элементам не происходит, элементы массива принимают те значения, которые были в этих ячейках памяти ранее.
    То же самое и с динамическим массивом, только механизам выделения памяти другой.
    По любому адресу в памяти всегда находится какое-то значение, даже если эта память еще не выделена, просто потому что плашка памяти уже вставлена в материнку и на нее подано питание.

    Возможно в вашем случае это и не случайность - вы же не приводите код, которым выделяете память.
    Ответ написан
    7 комментариев
  • Как найти в строке слова-палиндромы?

    @res2001
    Developer, ex-admin
    Проблема в том, что word у вас массив двойных указателей (**). Тогда как strtok возвращает обычный указатель.
    Из-за этого тут
    if(word[x] != word[y])
    вы сравниваете 2 указателя, а не 2 символа.

    Вообще я бы убрал массив word в принципе. Вы сразу можете вызывать polyndrome после того как нашли очередное слово.
    Ответ написан
    Комментировать
  • Как откинуть 5 число с массива?

    @res2001
    Developer, ex-admin
    Просто так взять и удалить элемент из массива на Си нельзя.
    Из статического массива удалить нельзя ничего в принципе - его размер не меняется никогда.
    В динамических массивах могут быть варианты:
    Вы можете переписать хвост массива, начиная с шестого элемента, на один элемент вперед, т.е. 6 элемент станет 5 и т.д. Но при этом в конце образуется не используемый элемент, избавится от него можно перевыделением массива с помощью realloc, например. Но если это делать, то проще сразу выделить память под новый массив и скопировать весь первый массив, кроме удаляемого элемента, как писал GavriKos.
    Другой вариант - помечать подобные не используемые элементы каким-то образом. Либо писать в них какое-то значение, обозначающее для вас, что это не используемый элемент, либо хранить где-то отдельно используемый размер массива (так сделано в std::vector).
    Ответ написан
    Комментировать
  • Почему этот код работает?

    @res2001
    Developer, ex-admin
    Код то где?

    На сколько я знаю, микрософтовский компилятор официально не поддерживает стандартов Си. Так что на самом деле, собирая Сишный код на msvc вы используете некий "микрософт Си" диалект языка.
    Так что не удивляйтесь подобным вещам.
    Некоторые фичи из более современных стандартов Си (С99, С11) в компилятор микрософт до сих пор не завезли или завезли, но в каком-то видоизмененном виде.
    Ответ написан
    Комментировать
  • Почему на линукс не работает библиотека conio.h?

    @res2001
    Developer, ex-admin
    conio.h - это чисто виндовый заголовочный файл, в линукс его нет и к стандартной библиотеке С/С++ он отношения не имеет.
    Для вашего примера он не нужен - просто уберите строку и откомпилируйте.
    Ответ написан
    Комментировать
  • Как решить проблему с открытием текстового файла в C?

    @res2001
    Developer, ex-admin
    Потому что практически все функции могут вернуть ошибку тем или иным образом.
    Когда fopen возвращает NULL, то это сигнал, что произошла ошибка при выполнения функции. Вы должны проанализировать значение errno и вывести осмысленное сообщение для пользователя.
    https://en.cppreference.com/w/c/io/fopen
    Сейчас же у вас на все ошибки выдается единственное сообщение. Вы можете просто вызывать функцию strerror с кодом ошибки errno, чтоб получить нормальное актуальное сообщение об ошибке.
    https://en.cppreference.com/w/c/string/byte/strerror

    Да. Вводите полный путь к файлу, тогда у вас не будет ошибок связанных с отсутствием файла там где программа пытается его найти. Но это не отменяет правильной обработки ошибок в программе.
    Ответ написан
    Комментировать
  • Как пишут код на C?

    @res2001
    Developer, ex-admin
    K&R - это не стандарт Си и даже не учебник. Просто популярная книжка от авторов языка про язык.
    Сам язык достаточно простой, выучить его можно легко. Начать можно с того же K&R.
    Ответ написан
    Комментировать
  • Как использовать одно состояние переменных заголовочного файла в нескольких исходных файлах программы?

    @res2001
    Developer, ex-admin
    Стоит знать, что #pragma once не стандартная директива. Ее наличие зависит от компилятора. В популярных компиляторах актуальных версий она поддерживается.
    Include guards - универсальный стандартный механизм, основанный на препроцессоре Си, поддерживается всеми компиляторами Си с лохматых времен.
    Ответ написан
  • Как реализован консольный ввод/вывод в C/C++?

    @res2001
    Developer, ex-admin
    Непосредственно вводом/выводом занимается ОС. Стандартная библиотека С/С++ использует API ОС для ввода/вывода.
    Ответ написан
    Комментировать
  • Как написать модуль для Python 3 на C?

    @res2001
    Developer, ex-admin
    У Бизли в "Подробном справочнике" есть хорошая глава введения в этот процесс (это лучшее, что я видел в печатной литературе на русском). Но там, конечно, только для старта информация, все остальное берите из докуменатции.
    Ответ написан
    Комментировать
  • Как копировать один символ строки в другую переменную?

    @res2001
    Developer, ex-admin
    Для кода нет никакой разницы английский символ в строке, русский или китайский.
    Но когда вы читаете текстовый файл глазами, чтобы символы правильно отображались вы должны выбрать правильную кодировку. Си никак не меняет кодировку символов, то что есть в строке то и пишется в файл.

    Вообще у вас как-то усложнена запись в файл. Зачем вы копируете этот единственный символ, да еще и выделяете для этих 2ух байт динамическую память (которую надо еще и освободить после использования).
    Си строка - это просто массив байт. С ним можно обращаться как с массивом (symb[i]). Для записи в файл одного символа используйте fputc(), для записи нескольких байт используйте fwrite().
    Ответ написан
    Комментировать
  • С чего начять новичку в СИ?

    @res2001
    Developer, ex-admin
    1.Си достаточно не большой и простой язык программирования. Возьмите любой учебник для начинающих. Изучите язык, порешайте задачи оттуда.
    Поймите все про Си строки. Все достаточно просто, но почему то у многих с этим проблемы в начале.
    Поймите тонкие моменты языка (это важно для системного программиста и для "железячника", да и просто для хорошего программиста): указатели, арифметика указателей, динамическое выделение памяти.

    2. Потом надо погрузиться в программирование для той ОС, которую планируете использовать. Обычно это линукс. Учитывая ваши интересы (системное программирование, железо), то тут можно порекомендовать следующие книги:
    - https://www.ozon.ru/product/linux-api-ischerpyvayu... - это для user space. Эта книга больше справочник по Linux API. Если у вас хорошо с английским то эту книгу может заменить встроенная справка линукс (man).
    - https://www.ozon.ru/product/yadro-linux-opisanie-p... - это kernel space (драйвера)

    3. Параллельно с первыми двумя пунктами есть смысл читать что-нибудь по алгоритмам. Например Кормена: https://www.ozon.ru/product/algoritmy-postroenie-i...

    4. После того как будете уверены в своих знаниях Си и Linux, можете выбирать платформу с которой вы хотите работать (железку) и начинать реализовывать свои задачи. По ходу дела возникнет куча вопросов. Большая часть из них может быть решена с помощью чтения TRM (Technical Reference Manual, предоставляется производителем железа/процессора). TRMы обычно оочень большие просто так их читать без конкретной цели смысла нет.
    Ответ написан
    1 комментарий