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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Может, ручной разбор будет быстрее. Читайте весь файл в большой буфер. Трехсимвольные строки - это пусть будут тупо char* на начало строк в этом буфере. Там пробелы замените на '\0' только. Вот вы уже сэкономили на разборе строк и выделении под них памяти. Числа руками разобрать придется правда (умножение на 10 + следующий символ - '0').

    Еще, вместо чтения файла какой-нибудь mmap может быть быстрее.

    Потом это можно еще и распараллелить каким-нибудь OpenMP, например. Разбейте буфер на примерно равные части, чуть подвигайте границы, чтоб они на переводы строк приходились и каждый кусок разбирайте отдельно.
    Ответ написан
  • Почему возникает malloc(): corrupted top size?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вот тут: (long long int*) calloc(len_s1, sizeof(int)); вы выделяете массив int на len_s1 элементов, а потом работаете с ним, как с массивом long long той же длины. Но long long занимает больше байт! Поэтому вы выделяете меньше памяти, чем используете, а это UB.

    В этом случае программа может даже отработать, если повезет. И любое изиенение в ней может непредсказуемо изменить, как ошибка проявится: упадет ли программа, повиснет или просто не так отработает.
    Ответ написан
    1 комментарий
  • Стоит ли очищать оперативную память от массивов структур в Си?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Нет, если это локальная переменная, ничего делать не надо. Она выделяется на стеке и отчищается автоматически по выходу из функции.

    Надо вызывать free только для тех блоков памяти, который вы сами получили через malloc.
    Ответ написан
    Комментировать
  • Как создать массив из типов данных в си?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Если массив фиксирован, то можно попробовать через variadic macros это сделать. Но это такой ужас получится. Вам же кроме размеров типов что-то еще делать надо с разными типами. Проще завести enum типов данных, массив из этого, и через switch считать размеры для каждого значения enum.

    Edit: был не прав: variadic macro тут не поможет.
    Ответ написан
  • Можно ли передать тип данных как параметр функции?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    В C - нет. В C++ можно воспользоватся шаблонами. Но если вопрос действительно про C, то надо передавать в функцию какой-нибуть enum где все возможные типы перечисленны. Или, как в scanf, передавать идентификатор типа в строке.
    Ответ написан
    6 комментариев
  • Есть ли флаг компиляции gcc, чтобы неявное приведение типов выводилась как ошибка?

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Без теории тут никак.
    Тут 2 варианта: или стройте конечный недетерменированный автомат (с эпсилон переходами), который соответствует этому регулярному выражению и дальше применяйте стандартный алгоритм проверки. что автомат принимает заданную строку. Или второй вариант: пишите динамическое программирование "соответствует ли вот этот префикс заданной строки вот этому префиксу регулярного выражения".

    Конечный автомат будет и побыстрее работать и памяти меньше требовать.

    upd: ну и, конечно, тут полным перебором рекурсивно можно сделать. Но это будет гораздо медленнее любого из указанных выше методов.
    Ответ написан
    2 комментария
  • Почему scanf считывает значение только первой переменной?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Если вам нужен ввод целых чисел, то читайте их в целые переменные через %d. Еще, scanf возвращает количество прочитанных значений. Т.е. сравнивать надо с тройкой, а не единицей.

    Еще одна проблема: возможно, из-за настроек локализации, оно ждет десятичные запятые, а не точки. Попробуйте ввести "1,0 2,0 3,0" или "1 2 3".

    И вообще весь ваш сценарий - это комбинация ошибок в пером и втором абзаце. Из за точек вместо запятых оно читает только первую переменную сначала, видит, что ввело 1 переменную и завершает цикл. При вооде "1 2 3" оно читает все переменные, но из-за ошибки в проверке (вы же хотите, чтобы одна прочиталась) читает опять. При повтороном вводе "1.0 2.0 3.0" оно читает только первую переменную и завершается. При этом в b и c остались значения от прошлого ввода.
    Ответ написан
    2 комментария
  • Почему при передаче имени файла как аргумент функции я не могу его открыть?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Смотрите внимателно на тип параметра в функции. Это char. Один символ, или число от 0 до 255. А вы потом рабоатете с ним, как со строкой (указателем на char). Вы передаете это число от 0 до 255 в strcat, он пытается записать что-то по адресу от 0 до 255 и, ожидаемо, падает.

    Поставьте там звездочку.

    Еще комментарии: ".txt\0". Терминирующий \0 ставить не надо, "" уже его ставит само. 10 символов на filename может не хватить.
    Ответ написан
    3 комментария
  • Почему вначале все работает, а потом нет?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Потому что кривой алгоритм. Вы пропускаете те строки, где 0 на диагонали стоит. А надо искать строку, где в i-ом столбце стоит не 0 и менять ее с i-ой строкой сначала. Перечитайте алгоритм в методичке. Или погуглите алгоритм гаусса.

    Да и я уж не помню, для не квадратных матриц ранг вообще определен-то?
    Ответ написан
    Комментировать
  • Как найти сумму элементов массива, находящихся на нечётных позициях?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Код выглядит правильно, только массив объявлен на 15 элементов, а цикл до 16 идет. И, возможно, надо 0 на 1 в проверке поменять. "Нечетные позиции", по человечески - это первая, третье и т.д. Но им соответствуют четные индексы 0, 2...

    Edit: А еще в коде стоит точка с запятой после for, из-за чего цикл оказывается пустым, а вводится только один элемент (и тот за границей массива):
    for (i=0; i<16; i++); // <----------
    scanf("%d", &A[i]);
    Ответ написан
  • Как выделить память в другой функции, передавая pointer через аргументы?

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

    Если уж очень надо через аргументы, то передавайте указатель на указатель:
    static void update_callback(char **ptr)
    {
        *ptr = (char *)malloc(sizeof(char) * TEST_STR_SIZE + 1);
    ...


    P.s. В вашем коде утечка памяти. Вы выделяете память, потом единственный указатель на эту память переписываете указателем на TEST_STR.
    Ответ написан
    6 комментариев
  • Как не обрезать стркоу после \0?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Все sendto, что я знаю, принимают указатель и размер в байтах. Именно из-за возможности нулевых байт.
    Ответ написан
    Комментировать
  • Как разбить строку в Си на части?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Это не разбиение на части, а разбор строки.
    Вычтите из второго символа '0'. Ведь символы в C - это числа, просто каждому числу назначен символ по кодам ascii. Буквы английского алфавита и цифры идут по порядку в этих кодах. Поэтому при вычитании символа 0 вы получите численное значение цифры.

    Для первой переменной просто скопируйте первый символ.
    Ответ написан
    Комментировать
  • Почему происходит сегфолт?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Комментарии в коде вроде //4 значение по адресу однозначно говорят, в чем проблема. Вы хотите работать с четверкой чисел, а в строке их у вас всего 2.
    Ответ написан
  • Подсчет чисел в массиве, в языке C?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Человек под номером i (c 0) идет в команду i % K, где K - количество команд (опять же, нумерация с 0).

    Вам надо лишь в цикле пройтись по всем числам и прибавить их в соответствующую ячейку ответа.
    Ответ написан
    Комментировать
  • Быстро ли мое решение?

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

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

    Но на практике все зависит от кучи факторов. Много ли у вас чисел, попадают ли они в кеш процессора, как далеко лежат две части буффера, как долго идет обработка каждого числа. Проверить это в итоге можно только практикой, но, скорее всего, ваше текущее решение будет быстрее memcpy, потому что единственное приемущество memcopy будет в том, что данные лежат в памяти подряд, что очень дружественно к кешу. Но вашем текущем решении и сами указатели и то, куда они указывают, итак лежат в памяти подряд (кроме одного индекса, где меняются массивы).
    Ответ написан
    Комментировать
  • Как работать с указателями?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вы там поменяли местами значкения двух переменных указателей. Поскольку переменные (указатели) переданы по значению, то вне функции ничего не поменялось.

    Вы же менянте местами значения int, значит временная переменная tmp должна быть int, а указатели надо разименовывать.
    Ответ написан
    Комментировать
  • Как посчитать количество разных букв в массиве строк?

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

    Второй вариант - отсортировать символы. Там уже проще подсчитать все символы - это 1 + сколько разных соседей в отсортированном массиве. Это быстрее, если использовать быструю сортировку.

    Ну или самый быстрый способ - в массиве на 256 счетчиков подсчитайте, сколько раз каждый символ встречается. Потом подсчитайте, сколько там ненулевых элементов.
    Ответ написан
  • Как в Си вывести в консоль без записи в буфер?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Можно выводить в stderr через fprintf. Тогда перенаправление в файл запишет туда только то, что выведено в stdout через printf.

    А так /a.out > file.log просто перенаправляет stdout в файл и все, что будет туда выведено, будет записано в файл самой системой. Ваша программа не знает, куда там система будет содержимое потока выводить - в консоль или в файл. Никак на это повлиять вы не сможете. Остается только писать в другой поток, например stderr.
    Ответ написан