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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Проблема в том, что * выполняется перед вычетанием. *(current-1) - это предыдущий элемент. (*current-1) в плохой версии - это текущее значение минус 1.
    Ответ написан
    Комментировать
  • Как решить данную задачу на двумерные массивы c++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    int sum = 0;
    int cnt = 0;
    for (int dx = -1; dx <= 1; ++dx) {
      for (int dy = -1; dy <= 1; ++dy) {
        if (dx == 0 && dy == 0) continue;
        int nx = i + dx;
        int ny = j + dy;
        if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue;
        sum += A[nx][ny];
        ++cnt;
      }
    }
    B[i][j] = cnt == 0 ? 0 : sum / cnt;
    Ответ написан
    Комментировать
  • Почему не работает ввод?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Попробуйте ваши строки на экран выводить. Нет ли там всяких лишних пробелов или переводов строк? Завершается ли программа, если ввести только конечную фразу? А если вы вводите что-то вроде "abc. Dragon flew away!", то строка будет " Dragon flew away!".
    Ответ написан
    Комментировать
  • Где ошибка в коде?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема в том, что strtok нельзя вот так использовать вложенно. Вы когда разбиваете строку по пробелам, вы ломаете состояние доя разбития по строкам. Выделите сначала все строки.

    Но вообще, тут не надо никаких strtok. Нельзя строки сразу читать через scanf, например? А вообще, лучше читать число и символ. И там в зависимостм от символа или начинать новую строку, или нет.
    Ответ написан
    Комментировать
  • Как исправить ошибку Е0028 Выражение должно иметь константное значение на С?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    С вообще говоря, не умеет выделять массивы произвольного размера на стеке (вот так как у вас x локальная переменная). Ему надо знать размер массива во время компиляции. Вот про это он и ругается, n - не константа.

    Есть расширение VLA, которое есть в стандарте C99. С ним вот такие вот массивы можно заводить. Оно включено не во всех компиляторах из коробки. В некоторых его вообще, наверное, нет.
    Попробуйте передать компилятору в ключах флаг -std=c99.

    Или, выделяйте массив через malloc (не забудьте free сделать потом).

    Еще, можно завести достаточно большой глобальный массив фиксированного размера.
    Ответ написан
    Комментировать
  • Верно ли я понял процесс преобразование целого типа данных в символьный на C?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Не совсем. Действительно, вы получаете в x код символа '4'. Но вы не преобразуете его в символьный. Это все еще int (скорее всего, 4-х байтный). В данном конкретном случае, это работает. Но тут вам повезло, что printf может вместо char принять int и правильно его синтерпретировать. Правильнее было бы преобразовать к char перед передачей в printf:
    printf("%c", (char)x);

    Вот тут уже действительно происходит преобразование к символьному типу char.

    Edit:
    Немного не прав был. printf надо передавать int, даже если формат "%с". Но какой-нибудь другой функции может понадобится именно char.
    Ответ написан
    5 комментариев
  • Получение значения указателя в структуре которая является указателем?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    В чем проблема? Если бы у вас в структуре было поле типа int, как бы вы получали значение этого поля? вот точно так же, только у вас тип не int, а char*

    struct Foo {
    char* data;
    };
    
    Foo* bar;
    char* pointer = bar->data;
    Ответ написан
    Комментировать
  • В чём ошибка вычисления бесконечно убывающей прогрессии с точностью до эпсилон?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Целочисленное переполнение при умножении i на i+1. Замените на, скажем prog += 1/((double)i*(i+1));, должно сработать.

    При i порядка 50000 результат перемножения не влезает в int. А у вас там 6697830 операций. В результате используются отрицательные или слишком маленькие неправильные значения i для вычисления слагаемых после 50000, и результат вообще не правильный.

    Ну и, кстати, логика решения у вас неправильная. Надо не с конечным значением сравнивать, а останавливаться, когда следующее слагаемое становится слишком маленьким.
    Ответ написан
    5 комментариев
  • C выдаёт ошибку при попытке сравнить 2 int?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Отключити оптимизацию и соберите проект в режиме Debug.

    У вас там Undefined Behavior и, очевидно, проблемы работы с памятью. Ошибку вы замечаете не там, где она, собственно, происходит.

    Сразу вижу проблему вот тут:
    strcat(result, alph[mod]);

    Тут вы приписываете строку с адресом alph[mod] к строке по адресу result. Обратите внимание, не строку, начинающуюся с позиции mod в массиве alph, а строку с адресом вроде кода символа 'F'.

    Ну и, вряд ли вы хотите часть строки alph скопировать в result. Плюс у вас в alph[] нет места под терминирущий 0, поэтому strcat вызовет переполнение буфера. Вам там надо дописывать один символ в конец result. Библиотечных функций именно для этого нет. Заведите счетчик количества символов в ответе и тупо переписывайте значение result[cnt].
    Ответ написан
    2 комментария
  • Почему после ассемблера учить Си легче?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Изучать ассемблер стоит, потому что это вправляет мозги. У программиста появляется какое-то понимание того, как все на самом деле устроено, как вообще работает компьютер. Тут в первую очередь не про сам ассемблер, а про устройство ЭВМ, которое почти всегда дается вместе с ассемблером вместе.

    Это понимание особенно важно тем, кто работает на относительно низкоуровневых языках (коим Си и является). Потому что абстракции не слишком далекие от ассемблера.

    Те же указатели, конечно, можно объяснять и как номер коробочки с данными, но если знать, что это адрес в памяти, то как-то понятнее и почему индексация работает, и что происходит при выделении памяти. Понимание стека и как процессор вызывает функции объясняет, что происходит с локальными переменными и в чем разница между ними и данными, выделенными через malloc.

    Еще один фактор: Учить язык более высокого уровня всегда легче после освоения языка более низкого уровня. Ну как после подготовки к марафону вам будет сильно проще ходить на 3-ий этаж пешком. Потому что там за счет абстрагирования и отдаления от предыдущего уровня, становится легче писать программы. Поэтому после ассемблера будет легче учить и питон и си++ и хаскель. А после си будет проще учить си++, чем если бы вы сразу взялись за си++. При этом учтите, что общее потраченное время и силы на изучение ассемблера + си может быть больше чем просто обучение си.

    Но вообще, я бы советовал не учить сначала ассемблер. а потом си. Ибо досконально знать ассемблер вам не надо будет. Да и кучу времени потратите на него. Стоит учить их параллельно, не особо углубляясь в ассембрер. Сможете функцию вызвать, вывести на экран строку, сложить 2 введенных с экрана числа - уже хорошо.
    Ответ написан
    Комментировать
  • Нужно ли писать суффиксы литералов?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    При инициализации переменных это обычно не используют. Ну, происходит тут преобразование типа - ошибки быть не может. Это лишь немного снижает читабельность кода и все.

    Вот когда вы константы передаете в какие-то перегруженные функции, где имеет значение unsigned ли ей передан или signed, или есть разница между float и double, то тогда - да, надо писать.
    Ответ написан
    4 комментария
  • Как сделать побитовое умножение и сложение большого числа decimal?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Вот эти побитовые сдвиги работли бы, если бы вы хранили число в двоичной системе счисления. Допустим, по 16 бит в каждом int. В таком виде вычисления побыстрее будут немного, но при выводе надо переводить число в 10-ую систему счисления. Судя по примеру ответа, вы храните по 3 десятичных знака в каждой ячейке. Т.е. у вас основание системы счисления 1000. И тут нужны сдвиги не битовые, а тысячные (которых не существует).

    Вообще, основной цикл умножения должен быть примерно такой:

    for (i = 0; i < len1; ++i)
      for (j = 0; j < len2; ++j) 
        c[i+j] += a[i]*b[j];


    И потом надо сделать все переносы. Вот тут и происходят сдвиг на i позиций (в системе счисления 1000) - это то самое +i в индексе у массива результата. И вместо выполнения прибавления, когда бит равен 1, тут происходит умножение на a[i]. В битовом случае оно как раз вырождается в умножение на 1 или 0 - прибавление или пропуск прибавления.

    Это работает даже если вы в массивах a,b храните по несколько бит в каждой ячейке, или даже десятичных знаков. Это просто умножение в столбик в произвольной системе счисления.

    Правда, тут проблема, что вот такое вот умножение, если вы храните по 32 бита, оно переполнится, и ответ надо в 64-битном типе получать. И даже если вы храните по 16 бит, то сумма может переполниться из-за большого количества слагаемых. Ну это решается выполнением переноса сразу же:
    const int BASE = 1000; // База системы счисления. Оно же максимальное число в ячейке +1.
    for (i = 0; i < len1; ++i) {
      int carry = 0;
      for (j = 0; j < len2; ++j) {
        carry += c[i+j] + a[i]*b[j];
        c[i+j] = carry % BASE; 
        carry /= BASE;
      }
      int i = len1+len2-1;
      while (carry > 0) {
        carry += c[i];
        c[i] = carry % BASE;
        carry /= BASE;
        ++i;
      }
    }
    Ответ написан
  • Как присвоить динамическому массиву типа void* значение в Си?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Если это произвольный тип, то какой у него размер? Какими значениями вы его заполнять-то пытаетесь?

    А так, скорее всего вам подойдет функция memset. Какими-нибудь нулями все заполнить - отлично можно. Хоть там int, хоть char, хоть float.
    Ответ написан
  • Как написать функцию sin из библиотеки math.h в Си?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Все у вас правильно написано, вы запутались.

    Ваша функция, как и стандартная, работает с радианами и выдает такой же результат от того же аргумента Pi*30/180=Pi/6.

    Посмотрите, ведь в result и во второй строке вывода вы передаете один и тот же агумент и получаете один итот же 0.500000. Только во второй строке у вас вместо Pi написано 3.1415265.
    Ответ написан
  • Почему free() выводит ошибку?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Какая-то проблема из-за чего один и тот же элемент удаляется дважды, судя по всему.

    Вижу сразу ошибку в delete_node: Если вершина в списке всего одна, произойдет фингя: this_list->last не обновится, да и next_node->prev несуществующее будет переписано.
    Ответ написан
    2 комментария
  • Как "умножить" строку в си?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Руками. Циклом на x_len-2 итераций. Раз у вас там, судя по коду, есть обрамление, то лучше гнать цикл с 1.
    for (int j = 1; j < x_len-1; ++j) {
      map[i][j] = ' ';
    }


    Еще, конечно, можно извратиться с memset, но лучше ненадо. Это тяжело читать и можно налажать запросто.
    Ответ написан
    Комментировать
  • Как управлять значением пикселей на экране в виндовс?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Гугли "GDI+"
    Это библиотека под винду, которя позволяет рисовать в окнах/на экране.
    Надо получить DeviceContext для экрана, и там рисовать что хочешь.
    Ответ написан
  • Returning 'int (*)[(sizetype)(*sizeMas)]' from a function with incompatible return type 'int *' [-Wincompatible-pointer-types] в Си. Что делать?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    mas уже указатель. Массивы в C - указатели. Не надо & использовать где вы его возвращаете. Только в этом случае оно скомпилируется, но работать не будет, потому что mas - локальный массив. По выходу из функции это будет указатель на отчищенную память. Надл выделять массив через malloc.
    Ответ написан
    Комментировать
  • Почему программа на языке C не выполняется?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Оно не компилируется. Нажмите показать ошибки, там будут детали.

    Просто догадки:
    У вас опечатка - функция mian вместо main.
    Потом, в конце функции должно стоять return 0;
    Ответ написан
    4 комментария
  • Как умно распараллелить вложенный цикл OpenMP?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Внешний цикл по итерацийм не распараллелить, потому что каждая итерация зависит от предыдущей.

    Внутри можно циклы по i объединить все в один.

    Ну и параллельте цикл по i через pragma omp for.
    Ответ написан