Ответы пользователя по тегу C
  • Как сравнить точность аналитического алгоритма и его программной реализации?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть вычитание близких чисел? Какие-нибудь циклы вроде СЛАУ больших порядков и решения дифуров? Знакопеременные ряды? Если нет, можно писать, что вклад машинной арифметики в точность алгоритма незначителен.
    А если есть, нужно исследовать, кто и как может многократно усилить ошибки округления.
    Ради эксперимента можно также сравнить результаты во float и double.

    Пример алгоритма, который аналитически устойчив, а вычислительно — нет: e−x «в лоб» при достаточно больших x. Связан он с тем самым вычитанием близких чисел: промежуточные члены ряды могут быть достаточно большие, а в результате выходит 0,0…01.

    UPD. Вот такую книжку нашёл: info.alnam.ru/book_clm.php?id=26
    Ответ написан
    2 комментария
  • Обьясните, что здесь происходит ++ndigi[c-'0']?

    @Mercury13
    Программист на «си с крестами» и не только
    '0' — это не число 0, а код символа «0». Во всех машинах, кроме совсем уж мамонтов, используются надмножества кодировки ASCII, и '0' = 48.

    И в ASCII, и в EBCDIC, и во внутренних кодировках, скажем, ЖК-индикаторов коды цифр идут последовательно от 0 до 9 — так что, отняв от кода цифры код символа «0», получаем числовое значение цифры.
    То есть ,
    '0' - '0' = 48 - 48 = 0
    '1' - '0' = 49 - 48 = 1
    ...
    '9' - '0' = 57 - 48 = 9
    (цифры справедливы для ASCII и его надмножеств, но в EBCDIC аналогично)

    В компьютере вообще нет понятия «символ», и что такое 48 — сорок восемь попугаев, X-координата на экране или код символа '0' — программист или компилятор должен думать сам. Так что Си (который, по сути, кроссплатформенный ассемблер), а ним и Java ставят очень эфемерную грань между одним и другим. В отличие от Паскаля, где надо писать Ord(c) - Ord('0').
    Ответ написан
  • Решение уравнения 5 класса в Си?

    @Mercury13
    Программист на «си с крестами» и не только
    Это дело сложное. И я бы разделил его на три перекрывающихся этапа.
    1. Увидеть в строке уравнение от одной переменной. Например, в таком виде.
    5ac73cfdb0af3347885965.png
    2. Увидеть в том, что получилось, линейное уравнение.
    3. Запустить модуль «Линейное уравнение», который приведёт подобные слагаемые и высчитает ответ.
    Ответ написан
    Комментировать
  • Как програмным путем, закрепить ярлык на "Начальном экране" Win 10?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть способы, но они периодически меняются.
    Это политика Microsoft: программы не должны засирать эти экраны.
    https://blogs.msdn.microsoft.com/oldnewthing/20030...
    Ответ написан
  • Почему sizeof показывает фактический размер массива хотя по сути имя массива это указатель на первый элемент?

    @Mercury13
    Программист на «си с крестами» и не только
    Несмотря на то, что массив часто отождествляют с указателем, массив — это НЕ указатель. У него, например, другие операции приводят к неопределённому поведению.

    И самое противное в Си — это то, что в коде
    void sort(int x[5]);
    x — это не массив, а именно что указатель. Чтобы был массив, надо Си++
    void sort(int (&x)[5]);
    И компилятор даже подсвечивает, что параметр функции, отмеченный как массив — всегда указатель.
    typedef int Arr[SIZE];
    int sum(Arr arr, int n)
    // warning: 'sizeof' on array function parameter 'arr' will return size of 'int *' [-Wsizeof-array-argument]|
    Ответ написан
    Комментировать
  • Как нарисовать на курсоре в RunTime?

    @Mercury13
    Программист на «си с крестами» и не только
    Попробуйте Brush.Color := $FF000000 or clBlue;. Велика вероятность, что механизмы работы с 32-битными изображениями тут слабоваты.
    Ответ написан
    1 комментарий
  • Почему не работает код (c)?

    @Mercury13
    Программист на «си с крестами» и не только
    https://ru.wikipedia.org/wiki/Условия_Йоды
    Аж в двух местах.

    Причём в Си не нужно ставить в сложных условиях скобки, как в Паскале, вполне покатит такое…
    if ((a >= 11 && a <= 14) || m == 0 || (m >= 5 && m <= 9))

    Но нет, вы наставили лишних скобок и заглушили ошибку.

    Также, что мне не нравится.
    Вместо 0,1,2,3 лучше использовать константы MANY/FEW/ONE/UNKNOWN.

    В case 1 символ подстановки плохо содран с доски.

    Если условие на MANY самое сложное и выполняется по остаточному принципу — почему его делаем самым первым? Лучше что-то типа…
    • 10…20 → MANY
    • 1 → ONE
    • 2…4 → FEW
    • Иначе MANY
    Ответ написан
    Комментировать
  • Как в си найти котангенс?

    @Mercury13
    Программист на «си с крестами» и не только
    Единственно правильный способ — tg(π/2 − x).
    Дело в том, что 1/tg будет глючить в районе 90°.
    Ответ написан
    4 комментария
  • По разному считается или ошибка в логике?

    @Mercury13
    Программист на «си с крестами» и не только
    Причина в другом. Если человек введёт −1 пройденного пути, надо сразу break, а не проходить огрызок цикла. Пока я проверял, ns 5d выписал действующий код.

    Ну и, конечно, ошибка в логике: среднее потребление (в mpg) = сумма миль / сумму галлонов.

    UPD. Раз уж не хотите break, то…
    while(petrol != -1)
        {
            printf("Enter the gallons used (-1 to end): ");
            scanf("%f", &petrol);
            if(petrol != -1)  {
               // Тут делай ВСЕ вычисления по MPG
            }
       }
    Ответ написан
    Комментировать
  • Не могу найти ошибку в использовании long double в C?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня всё сработало. Может, зависит от библиотеки Си? Какой компилятор?

    UPD. Сработало на MinGW.
    Ответ написан
    1 комментарий
  • Как реализовать сумму дробей?

    @Mercury13
    Программист на «си с крестами» и не только
    Заводим структуру-сумматор. Изначально она 0/1. Что-то типа
    typedef struct {
      int num, den;
    } Fraction;
    
    …
    
    Fraction sum = { 0, 1 };

    Дальше пишу псевдокодом, НОД и НОК разберись, как реализовать самому.
    для каждой очередной дроби
      ввести(дробь)
      новыйЗнам = НОК(сумматор.знам, дробь.знам)
      множСумм = новыйЗнам / сумматор.знам
      множДробь = новыйЗнам / дробь.знам
      новыйЧисл = сумматор.числ × множСумм + дробь.числ × множДробь
      сокрНод = НОД(новыйЧисл, новыйЗнам)
      сумматор.числ = новыйЧисл/сокрНод
      сумматор.знам = новыйЗнам/сокрНод

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

    И ещё. Одна из известных ошибок в написании НОК — произведение аргументов не влезает в свой тип, а НОК влезает. Поймёшь, как в такой ситуёвине избавиться от переполнения?
    Ответ написан
    Комментировать
  • Как написать путь файла с пробелами в функции system в C?

    @Mercury13
    Программист на «си с крестами» и не только
    Заэкранировать кавыки.
    system("gcc \"C:/Folder/My Folder/example.c\"" );

    Точно так же экранируется и обратный слэш, если вдруг потребуется.
    system("gcc \"C:\\Folder\\My Folder\\example.c\"" );


    Экранирование символов — механизм, имеющийся в текстовых языках и протоколах. Он служит, чтобы символы, которые считаются служебными и имеют особое значение, этого значения лишить и объявить «просто символами». Нам нужно двойное экранирование: для ОС (строка с пробелами закавычивается) и для Си (перед кавычкой слэш).
    Ответ написан
    Комментировать
  • Где располагаются переменные в данном случае (стэк, куча)?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы совершенно правы. Это массив из одного элемента, и при таком расположении он будет в стеке. Со всеми его полями: alloc, size и mp_d. При выходе из функции есть шансы, что он будет затёрт, и так действовать нельзя.

    Кто затрёт? Да кто угодно. Хоть драйвер, пожелавший воспользоваться твоим стеком. Хоть последующий вызов какой-нибудь функции.

    С другой стороны, на то и помечена структура __mpz_struct двумя подчерками, чтобы её не использовали.
    __mpz_struct* foo()
    {
        mpz_t var;
        return (__mpz_struct *)var;
    // C:\TestApps\RetLocal\main.cpp|15|warning: address of local variable 'var' returned [-Wreturn-local-addr]|
    }


    А так работает: всё в куче. Только не забывайте очищать через delete[].
    __mpz_struct* bar()
    {
        __mpz_struct* var = new mpz_t;
        return var;
    }
    Ответ написан
    2 комментария
  • Как правильно из zip архива считать текстовый файл с помощью PHYSFS?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужно закрыть Си-строку.
    int length = PHYSFS_fileLength(myfile)
    myBuf = new char[length + 1];
    int length_read = PHYSFS_read(myfile, myBuf, 1, length);
    myBuf[length_read] = 0;
    Ответ написан
    Комментировать
  • Как вывести результат этой функции?

    @Mercury13
    Программист на «си с крестами» и не только
    EOF — это маркер «файл закончился, данных больше нет». Обычно getchar даёт цифры от 0 до 255, а EOF — значение вне этих пределов (вообще-то −1).
    Консоль никогда не кончается, но конец файла можно сделать, нажав Ctrl+Z.

    Правильно писать int c; int r[]; int s[]; или int c, r[], s[];. Но в любом случае перед нами статический массив и ему надо дать размер.

    Иногда бывают массивы без размера — когда мы не заводим память, а просто говорим: «перед нами какой-то отрезок памяти». Например.
    void doSmth(int a[]) {}  // передаём в функцию отрезок памяти неизвестной длины
    int x[5];
    doSmth(x);
    
    extern int b[];  // компилятор рассматривает b как отрезок памяти неизвестной длины.
    int b[5];    // …и только линкер подставит на место b настоящий массив

    В Java массивы не статические и им размер дают тогда, когда выделяют им память.
    int[] x = new int[5];    // повторяю, это не Си++, а Java!

    Но это уже офтоп.
    Ответ написан
    8 комментариев
  • Почему в Си работают локальные функции?

    @Mercury13
    Программист на «си с крестами» и не только
    Очевидно, расширение GNU.
    MinGW, даже с ключом -std=c99, OK.

    Причём работает только в режиме Си. MinGW/Cи++
    C:\TestApps\NestedFunction3\main.cpp|7|error: a function-definition is not allowed here before '{' token|

    Embarcaredo x86 (Borland):
    [bcc32 Error] File1.c(7): E2141 Declaration syntax error

    Embarcadero x64 (clang):
    [bcc64 Error] File1.c(6): expected ';' at end of declaration
    Ответ написан
    1 комментарий
  • Для чего существует short?

    @Mercury13
    Программист на «си с крестами» и не только
    Си рассчитан на всякие машины. У некоторых байт более 8 бит — то есть к 8-битному октету обращаются как к битовой маске. Какие-то 16-битные, какие-то 32-битные.
    По всей видимости, int когда-то был «системным размером», коим сейчас является size_t.
    А char, short, long, long long — это 1/2/4/8 байт.
    Ваши знания «int равен 2 байтам» устарели — на современных машинах int равен 4 байтам.
    printf("%d\n", (int)(sizeof(int) * 8));
    Ответ написан
    9 комментариев
  • Как реализовать код для срабатывания нефиксированной Кнопки?

    @Mercury13
    Программист на «си с крестами» и не только
    UPD1. У вас опять игрушечное никогда не выполняющееся условие PINB &= 0b00000000.
    Если всё-таки сделаете работающее условие, то должно быть что-то вроде
    char oldState = 0, newState = 0
    ...
    oldState = newState;
    newState = PINB & 0b00000001;
    if (!newState && oldState) {
      // нажатие кнопки зарегистрировано.
      // 1. переключить состояние.
      // 2. Записать что надо в порт.
      // 3. Сделать задержку на дребезг.
    }

    Естественно, считается, что кнопка замыкается на землю и !newState — это как раз «прижата».
    Ответ написан
    3 комментария
  • Как передать counter is for loop внутрь макроса?

    @Mercury13
    Программист на «си с крестами» и не только
    Будет подставлено ИМЯ ПЕРЕМЕННОЙ b, а чему она равна — это уже другой вопрос. Никаких проблем не должно быть.
    #include <iostream>
    
    #define CHECK(a,b) \
       if ((a) == (b))     \
          std::cout << "Equal" << std::endl;  \
          else std::cout << "Inequal" << std::endl;
    
    int main()
    {
        for (int i = 0; i < 5; ++i) {
            CHECK (i, 2)
        }
        return 0;
    }


    После препроцессирования программа превратится вот во что…
    int main()
    {
        for (int i = 0; i < 5; ++i) {
            if ((i) == (2))
               std::cout << "Equal" << std::endl;
               else std::cout << "Inequal" << std::endl;
        }
        return 0;
    }


    Вывод в консоли
    Inequal
    Inequal
    Equal
    Inequal
    Inequal


    Разумеется, нехороши ситуации, когда в макрос подставляется код с побочными эффектами, но это другой вопрос.
    Ответ написан
    1 комментарий
  • Почему free() срабатывает только один раз?

    @Mercury13
    Программист на «си с крестами» и не только
    Переполняется longitude, говорите? Ну убедитесь, что он размера SIZE_J. Не этой функции, правда, дело.
    Кроме того, вы массивы latitude[] и longitude[] заполняете случайным мусором, появившимся в результате malloc.
    Ответ написан