Nano Hash - криптовалюты, майнинг, программирование

Просмотр и использование отдельных байтов в указателях void в C

Я пытаюсь сделать калькулятор, который берет пустой указатель с именем yourVal, смотрит на первый байт и решает, является ли он «*» или «/». Основываясь на знаке, я умножаю байты на 3+4, 5+6 и 7+8. скажем, у меня *1234567. Я умножаю 23 * 45 * 67. При делении я делю байт 5 (45) на байт 3 (23). Я новичок с указателями в C, и я действительно понятия не имею, как даже установить значение для указателя void. Когда я делаю следующее в main

void *yourVal;
*yourVal = "*1234567";
printf("%s\n", yourVal);

Я не могу разыменовать пустой указатель. Но я пробовал с указателем char, и у меня та же проблема. Это мой код для функции калькулятора. В зависимости от того, использую я printf или нет, я получаю разные результаты.

int calculator(void *yourVal){
  char *byteOne;
  short int *byteThree, *byteFive, *byteSeven;
  int value;

  byteOne = (char *)yourVal;
  byteThree = (short int *)yourVal+2;
  byteFive = (short int *)yourVal+4;
  byteSeven= (short int *)yourVal+6;

  if(*byteOne == '*') {
    value = *byteThree * *byteFive * *byteSeven;
    printf("You multiplied\n");
  }
  else if(*byteOne == '/') {
    if (*byteThree == 0) {
        value = 0xBAD;
        printf("Your input is invalid\n");
    }
    else {
        value = *byteFive / *byteThree;
        printf("You divided\n");
    }
  }
  else {
    value = 0xBAD;
    printf("Your input is invalid\n");
  }
}

Деление вообще не работает, а умножение захватывает только одну цифру. Любые советы будут оценены. Я просмотрел разные источники, но не вижу, как эффективно работать с указателями на пустоту. Кроме того, я не могу использовать какие-либо библиотечные функции, кроме printf, и это школьное задание, поэтому постарайтесь не давать слишком много спойлеров и не делать это за меня. Нам дали одну подсказку, которая заключается в том, чтобы привести ваш Val к структуре. Но я теряюсь в этом. Спасибо

22.09.2017

  • Если yourVal является строкой "1+2+3", когда вы назначаете byteThree = (short int*)yourVal + 2, она абсолютно не делает того, что вы думаете. Если вы хотите преобразовать символ 2 в целочисленное значение 2, вы не можете просто выполнить приведение. (Скорее всего, символ 2 представляет собой целое число 50, хотя это зависит от используемого набора символов.) 22.09.2017
  • Почему вы вообще используете указатель void? Кажется очевидным, что вы работаете с chars. 22.09.2017
  • Это параметр, который нам дан для написания функции. У них, вероятно, есть несколько тестовых случаев, в которых нужно использовать указатели void, я не знаю. 22.09.2017
  • Вам следует рассмотреть возможность использования sscanf(input, "%d%n", &number, &bytes_read) для извлечения чисел из вашего ввода. 22.09.2017
  • мы можем использовать только printf для этого назначения. 22.09.2017
  • Тогда это не void*, а char* (или вы должны привести к одному), так как вы смотрите на первый символ ; например, смотреть на первый символ некоторого адреса double бесполезно (и зависит от реализации) 22.09.2017
  • Скомпилируйте со всеми предупреждениями и отладочной информацией gcc -Wall -Wextra -g с помощью GCC и используйте отладчик gdb 22.09.2017
  • пример кода 22.09.2017
  • Спасибо всем, GDB работает для меня, но я работаю в Windows, и отсутствие макетов src или asm в моем текущем отладчике мешает моим текущим знаниям. Я думал, что пытаюсь привести к символу *, по крайней мере, с первым значением? 22.09.2017

Ответы:


1
byteOne = (char *)payload;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;

Это не делает то, что вы думаете. Если вы хотите прочитать числа на этих позициях, вам нужно сделать что-то вроде.

char* Value = yourValue;
unsigned byteOne, byteThree, byteFive, byteSeven;
byteOne = Value[0] - '0';
byteThree = Value[2] - '0';
byteFive = Value[4] - '0';
byteSeven = Value[6] - '0';

Здесь я прочитал байт в этой позиции и вычел значение ASCII из '0' в получить числовое значение этого символа. Но опять же, это будет работать только для одного персонажа.

Если вам нужно прочитать больше символов, вам придется использовать библиотечные функции, такие как sscanf или atoi.

22.09.2017
  • Мы должны захватить короткий int в каждом байте, что, как я полагаю, означает 16 бит или два символа. Но нам также говорят не использовать какие-либо библиотечные функции. Я не уверен, как бы я взял два байта и поместил их в int из пустого указателя. Вычитание «0» действительно помогает, я уверен, что в какой-то момент я буду использовать это. 22.09.2017
  • @Avallauch Я думаю, вы путаетесь между десятичными символами и байтовым представлением. Да, unsigned short означает 16 бит (или 2 байта), но его максимальное значение может достигать 65536. Если вы просто читаете 2 символа из ввода, максимальное значение может быть 99. Поскольку оно представлено как десятичное число. Если вы хотите на самом деле прочитать короткое из строкового ввода (который может содержать до 5 цифр), вам нужно использовать atoi. 22.09.2017
  • @Avallauch также назвал свою переменную payload. Эти данные приходят по сети? В этом случае это может быть не десятичная кодировка, а необработанный двоичный код. В этом случае стратегия парсинга будет совершенно другой. 22.09.2017
  • Итак, по сути, они просят умножить любое значение, хранящееся в этой памяти? В нем сказано вернуть произведение 3 коротких целых чисел, начиная с байтов 3, 5 и 7. 22.09.2017
  • @Avallauch Я немного запутался, чего ты на самом деле хочешь сейчас. Можете ли вы опубликовать весь вопрос? 22.09.2017
  • Нет, это не по сети. Они просто запускают на нем тестовый файл main. 22.09.2017
  • если первый байт в вашем val представляет собой символ '*', верните произведение 3 коротких целых чисел, начиная с байтов 3, 5 и 7. Если первый байт представляет собой символ '/', верните частное при делении целого числа (не короткое целое ) в 5-м байте на short int в 3-м байте. если short int в 3-м байте равен 0, вернуть 0xbad. байт 1 находится в &yourval и так далее. 22.09.2017
  • @Avallauch У меня такое ощущение, что ввод в не десятичном формате закодирован в вопросе. На входе есть необработанные байты unsigned short. Вам необходимо уточнить это у вашего инструктора. Лучше попросите их предоставить образец ввода. 22.09.2017
  • Да, вопрос, кажется, задает что-то более близкое к... unsigned char yourVal_m = {'',0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; // Умножение 0x0304 * 0x0506 * 0x0708 unsigned char *yourVal_d = {'/',0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; // Разделить 0x05060708 / 0x0304 22.09.2017
  • Это больше похоже. Спасибо за визуализацию. 22.09.2017

  • 2
    • Указатель void не добавляет функциональности, необходимой для решения этой проблемы, он просто усложняет ситуацию. Вместо этого используйте указатель char.
    • "*1234567" — это строка, а не массив целых чисел. Вы не можете рассматривать его как массив целых чисел. Каждый символ должен быть преобразован в целое число, прежде чем выполнять арифметические действия. Самый простой способ сделать это — вычесть на символ ASCII '0'.
    • "... я умножаю байты на 3+4..." При подсчете байтов вы всегда начинаете с 0. В строке "*1234567" 2 - это байт с индексом 2, а не 3.
    • «Основываясь на знаке, я умножаю байты 3 + 4, 5 + 6 и 7 + 8. Скажем, у меня есть * 1234567. Я умножаю 23 * 45 * 67. С делением я делю байт 5 (45) на байт 3 (23)"
      Я не вижу смысла в этом алгоритме. Для чего там 1? Почему вы не используете какое-либо обычное форматирование, такое как префикс, постфикс или просто набранные уравнения?

    Пример:

    int calculator (const char* yourVal)
    ...
    
    int byte2 = yourVal[2] - '0';
    
    22.09.2017
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..