Ответы пользователя по тегу C
  • Функция gets() в C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Первые два работают нормально, но когда доходит до 3, он не выполняется и длина выводится 0?

    Потому что scanf("%d", &n); зачитывает только один int из стандартного ввода. Если ты вводишь число и жмёшь enter, то конец строки остаётся в потоке ввода и читается gets'ом.
    Поэтому нужно либо вводить строку предназначенную для gets следом за числом предназначенным для scanf, либо scanf сделать таким: scanf("%d ", &n);
    Ответ написан
    Комментировать
  • Как передать двумерный статический массив в функцию на Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Есть массив char mass[1024][1024] и функция int fun(char*)

    в такую функцию можно передать fun(&mass[0][0]).

    Есть ли возможность для указания статического массива как аргумента?

    В смысле массива статической размерности? Легко: int fun(char a[][1000]); ... fun(mass);
    Ответ написан
  • Как запустить приложение через forkpty?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    может быть так?

    #include <pty.h>
    #include <unistd.h>
    #include <thread>
    #include <future>
    #include <iostream>
    #include <string>
    
    ssize_t sz = 1;
    
    int main()
    {
      int mfd;
    
      pid_t pid_fork = forkpty(&mfd, NULL, NULL, NULL);
    
      if (!pid_fork) {
        // Дочерний процесс
        execl("/bin/sh", "-", NULL);
      } else {
        // Родительский процесс
        char buf[1024];
    
        // Async
        auto future = std::async(std::launch::async, [mfd]() {
          std::string line;
          while (sz) {
            std::getline(std::cin, line);
            line = line  + "\n";
            write(mfd, line.c_str(), line.size()); // Нужно направить в дочерний процесс как stdin
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
          }
        });
    
        while (sz = read(mfd, buf, sizeof(buf))) {
          write(STDOUT_FILENO, buf, sz); // Вывод из дочернего процесса stdout
          std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    
        exit(0);
      }
    }

    Поскольку это теперь терминал, то имеет смысл установить размеры pty такими же, как у терминала вызывающей программы, например так:

    ...
    #include <sys/ioctl.h>
    ...
      struct winsize ws, *pws = NULL;
    
      if (ioctl(1, TIOCGWINSZ, &ws) >= 0)
        pws = &ws;
      pid_t pid_fork = forkpty(&mfd, NULL, NULL, pws);


    Кроме того, sleep_for в циклах чтения и записи не нужен, поскольку операции чтения присутствующие в обоих циклах -- блокирующие. Но нужна проверка того, что записались все прочитанные данные.
    Ответ написан
    1 комментарий
  • Как изменить строку, инициализированную при объявлении массива символьных указателей, с помощью scanf?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    char * suit [4] = { "Hearts", "Diamonds", "Clubs", "Spades" };

    Как изменить строку, инициализированную при объявлении массива символьных указателей, с помощью scanf?

    В данном случае -- только выделив память для новой строки, сделав scanf туда и присвоив указатель на выделенную память элементу массива suit. Напрямую в первоначальный массив -- никак, потому что указатели указывают на константные строки (а возможность писать char * вместо const char * -- это устаревшее средство обеспечения совместимости с древними версиями стандарта).
    Ответ написан
    3 комментария
  • Си. Как добавить программу в автозагрузку?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как добавить программу на Си в автозагрузку Windows?

    Так же как и на любом другом языке -- прописав её в соответствующий ключ реестра.

    И еще: как искать информацию на ответы по Си, если я пишу в гугле "Си как добавить программу в автозагрузку", но везде появляется только С++? Нереально найти ответ.

    Потому что ты задаёшь неправильный вопрос. Язык -- это способ делать действия, а не сами действия. Добавить программу в автозагрузку можно через реестр. Писать в реестр можно через winapi. Справка по winapi есть тут.
    Ответ написан
    Комментировать
  • Почему считывается не по порядку?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему результат вывода именно такой?

    Потому что если внимательно прочитать man dup, особенно вот эту часть:
    After a successful return from one of these system calls, the old
    and new file descriptors may be used interchangeably. They refer
    to the same open file description (see open(2)) and thus share file
    offset and file status flags; for example, if the file offset is modified
    by using lseek(2) on one of the descriptors, the offset is also
    changed for the other.

    то окажется, что это поведение предписанное стандартом.
    fhandle2 открыт независимо от fhandle1, поэтому у него все параметры состояния свои.
    Ответ написан
    Комментировать
  • Передача массива в функцию?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    printMAS (&MAS);//будет ошибкой! Почему?

    Будет ошибкой только с точки зрения соответствия типов, потому что тип выражения &MAS -- int (*)[5]. Значение же адреса будет одним и тем же.

    Вот такие инструкции же работают...

    Потому что значение адреса передаётся в них через ... и интерпретируется внутри как void *, т.е. тип исходного адреса больше не имеет значения.
    Ответ написан
    4 комментария
  • Нужно ли вообще очищать память в этом месте?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Нужно ли вообще очищать память в старом указателе?

    Зависит от логики этой функции: если string всегда выделена в куче и нигде не остаётся ссылок на неё, то можно её освобождать. В противном случае -- нет.

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как не сложно заметить при большой точности, мой результат отличается от результата библиотечного printf.

    Как не сложно заметить, long double имеет 19 значащих цифр, т.е. 0,0000000000000012300000000000000679 -- это всё что имеет смысл печатать, и эта часть одинакова в выводе printf и ft_printf. Всё что идёт дальше -- это мусор, который не содержится в исходном числе.

    long double tt = 0.00000000000000123;

    Число справа от знака = имеет тип double. См.
    Ответ написан
    4 комментария
  • На каких правилах основана шестнадцатеричная нотация в printf для вещественных чисел?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Где можно почитать почему так происходит, почему такие разные вариации записи одно числа в шестнадцатеричной системе исчисления?

    Разве что в спецификации использованной библиотеки языка C. Потому что в стандарте явно сказано, что первая цифра в таком представлении -- unspecified:
    A double argument representing a floating-point number is converted in the
    style [−]0xh.hhhh p±d, where there is one hexadecimal digit (which is
    nonzero if the argument is a normalized floating-point number and is
    otherwise unspecified) before the decimal-point character...
    Ответ написан
    Комментировать
  • Почему fgets не работает второй раз?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    char str1[5];
      char str2[3];
    
      fgets(str1,5,stdin);
      fgets(str2,3,stdin);

    Я ожидаю, что при запуске введу слово из 5 букв, потом слово из 3

    Чтение man fgets легко отвечает на этот вопрос:
    fgets() reads in at most one less than size characters from stream
    and stores them into the buffer pointed to by s.
    Reading stops after an EOF or a newline.
    If a newline is read, it is stored into the buffer.

    Т.е. чтобы прочитать ровно 5 и ровно 3 символа, нужно вызывать fgets с аргументом размера 6 и 4 соответственно. Кроме того, когда первая строка заканчивается символом конца строки, этот символ тоже должен быть считан. Т.е. 7 и 5.
    Ответ написан
    1 комментарий
  • Почему не выводится матрица?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    void readm(int N, int* X, FILE * dat)
    ... 
      int *X = nullptr;
      readm(N, X, dat);
    ...
      writem(N, X, res);

    Потому что ни N ни X внутри main не меняются, потому что их новое значения не возвращаются из функции readm.
    Минимальное изменение с которым всё заработает:
    void readm(int& N, int*& X, FILE * dat)
    Ответ написан
    2 комментария
  • Как правильно прервать поток в Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Общее правило при работе с потоками, не специфичное для С или pthreads: состояние резделяемое между потоками должно быть или атомарным или должно быть защищено примитивом синхронизации.
    Код функции thread_process никак не гарантирует, что компилятор не выкинет проверку !quit, потому что quit не меняется в этой функции и в функциях вызываемых из неё.

    Учитывая, что атомарность и потоки вошли в стандарт С11 имеет смысл смотреть туда.
    Если С11 недоступен, смотреть в pthread_mutex_*, pthread_cond_*, ...

    Может стоит вынести флаг в параметры потока

    По-хорошему -- да, стоит. Это, однако, ортогонально к синхронизации доступа.

    while(!quit) {
            if(difftime(time(NULL), last_cycle) > 30) {
                last_cycle = time(NULL);
                // Тут мои грязные дела
            }
        }

    Вместо busy wait лучше использовать sleep или что-нибудь типа pthread_mutex_timedlock/pthread_cond_timedwait.

    Я бы оформил код этого примера так:
    #include <sys/time.h>
    #include <pthread.h>
    #include <stdbool.h>
    #include <string.h>
    #include <stdio.h>
    
    struct thread1 {
        pthread_mutex_t lock;
        pthread_cond_t cond;
        bool quit;
    };
    
    static void* thread_process(void *p) {
        struct thread1 *arg = p;
    
        for (;;) {
            bool quit;
    
            pthread_mutex_lock(&arg->lock);
            if (!arg->quit) {
                struct timeval now;
                struct timespec ts;
    
                gettimeofday(&now, NULL);
                ts.tv_sec = now.tv_sec + 30;
                ts.tv_nsec = now.tv_usec * 1000;
                pthread_cond_timedwait(&arg->cond, &arg->lock, &ts);
            }
            quit = arg->quit;
            pthread_mutex_unlock(&arg->lock);
            if (quit)
                return NULL;
    
            // Тут мои грязные дела
        }
        return NULL;
    }
    
    int main() {
        pthread_t th;
        struct thread1 arg = {
            .lock = PTHREAD_MUTEX_INITIALIZER,
            .cond = PTHREAD_COND_INITIALIZER,
            .quit = false,
        };
        pthread_create(&th, NULL, thread_process, &arg);
    
        char cmd[16];
        while(true) {
            scanf("%s", cmd);
            if(!strcmp(cmd, "quit")) {
                pthread_mutex_lock(&arg.lock);
                arg.quit = true;
                pthread_cond_broadcast(&arg.cond);
                pthread_mutex_unlock(&arg.lock);
                break;
            }
            // остальные команды
        }
    
        pthread_join(th, NULL);
        return 0;
    }
    Ответ написан
    1 комментарий
  • Если к int добавить в конце точку без буквы f, то к какому типу будет произведено приведение?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    x = float(a) / 4.;

    Этот код не на С а на С++. В С++ тип выражения справа -- double, потому что это деление float на double. См. eelis.net/c++draft/lex.fcon
    Ответ написан
    Комментировать
  • Почему рандомные элементы массива заполняются мусором?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    char **array;
    array = malloc(arr_len);
    
    for(unsigned long step = 0; step <= arr_len; step++)
    {
        array[step] =

    Потому что в этом коде две большие ошибки. Первая: памяти для массива указателей из arr_len элементов требуется не arr_len, а arr_len * sizeof(char *). Вторая: цикл выполняет не arr_len, а arr_len + 1 итерацию.
    Ответ написан
    3 комментария
  • Как получить данные от пользователя с пробелами простым способом (С)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    scanf("%[^\n]\n", name);
    man scanf
    Проблема с этим способом: нельзя ввести пустую строку.

    Либо, если нет желания использовать исключительно scanf -- fgets.
    Ответ написан
  • Фрагментированный ввод/вывод: быстрее ли стандартного?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    1. корреткно ли я делал замеры времени? (может есть какая библиотека на Си или прочее?).

    Я подозреваю, что ты замерил в основном время вывода в stdout, если он не был перенаправлен в файл.

    2. Правильно ли я инициализоровал сегменты ? (может есть упрощенная форма)

    Вполне.

    3. Как правильно подобрать размер сегмента?

    Размеры сегментов диктуются структурой читаемых данных. Если у данных нет структуры -- читай всё с помощью read в один большой массив.

    4. В каких случаях лучше использовать фрагментированный ввод/вывод? (любые советы по его использованию)

    Когда данные имеют чётко выраженную структуру и время выполнения системного вызова приближается ко времени требуемому для копирования данных. Переход с read на readv позволяет не заниматься копированием данных в юзерспейсе и сэкономить N-1 системный вызов при одновременном чтении N сегментов.
    Ответ написан
    Комментировать
  • Как создать указатель на функцию main?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    int main(void)
    {
        int (*pmain)(void) = main;
    }


    например int* func;

    Это указатель на int, а не на функцию.
    Ответ написан
    Комментировать
  • Почему код именно так работает?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Символы повторяются из-за static?

    Не из-за static, а из-за того, что _itoa всегда возвращает один и тот же адрес. Попробуй так, зацени разницу:
    char *_itoa(int i) {
      static int slot;
      static char buf[10][2];
      slot = (slot + 1) % 10;
      buf[slot][0] = i + '0';
      buf[slot][1] = '\0';
      return buf[slot];
    }
    
    int main() {
    
      printf("%s + %s = %s", _itoa(2), _itoa(2), itoa(4));
      _getch();
    }
    Ответ написан
    Комментировать
  • Почему не срабатывает шеллкод?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    при компиляции флаг из реестра не удаляется. В чем может быть проблема?

    В том, что ты засунул бинарный код в параметр функции, в котором должна быть строка с именем программы для запуска и её параметрами. Непонятно, почему ты ожидаешь, что WinExec бросится выполнять машинный код в этой строке. WinExec имеет код возврата, который недвусмысленно тебе сказал бы в чём ошибка (путь или файл для запуска не найдены), если бы ты его проверил.
    И, кстати, байт с кодом 0 по смещению 0x246 -- это тоже часть шелл-кода, терминатор командной строки.

    Байты из зеленой области, как я понял, это информация линкера golink. Так ли это?

    Это заголовок файла формата PE. Да, его туда записал линкер. Нет, это не информация линкера, это информация в основном для загрузчика ОС, а так же для дизассемблера и прочих binutils.
    Ответ написан
    1 комментарий