Чтение байтовых методов в C / C++

Я новичок в C, и мне было интересно, есть ли стандартные методы библиотеки для чтения байтов / int / long, такие как: getChar (), getInt (), getLong ().

Так, например, если я вызову getInt (), он вернет 4 байта в виде строки и переместит адрес указателя символа на 4. Где я могу найти эти методы?

4 ответа

Решение

Поскольку арифметика указателей находится в самой природе C, такие Java-подобные функции там недоступны.

Чтобы получить int из некоторого буфера памяти вы могли бы сделать:

/* assuming that buf is of type void * */
int x = *((int *) buf);
/* advance to the position after the end of the int */
((int *) buf)++;

или более компактно:

int x = *((int *) buf)++;

Нет, двоичная (де) сериализация напрямую не поддерживается систематически библиотекой. read() Функция будет перемещать указатель потока вдоль, но я не думаю, что вы можете обойти платформо-зависимый фрагмент кода для интерпретации потока байтов:

std::infile thefile("data.bin", "rb");

float f;
double d;
uint32_t i;

// the following is OK and doesn't constitute type punning
char * const pf = reinterpret_cast<char*>(&f);
char * const pd = reinterpret_cast<char*>(&d);
char * const pi = reinterpret_cast<char*>(&i);

// the following may or may not give you what you expect
// Caveat emptor, and add your own platform-specific code here.
thefile.read(pf, sizeof(float));
thefile.read(pd, sizeof(double));
thefile.read(pi, sizeof(uint32_t));

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

unsigned char buf[sizeof(uint32_t)];
thefile.read(reinterpret_cast<char*>(buf), sizeof(uint32_t));

uint32_t n = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); // little-endian

Чтение данных с плавающей запятой в двоичном формате особенно утомительно, потому что вам нужно знать довольно много дополнительной информации о вашем потоке данных: использует ли он IEEE754? (Ваша платформа?) Что такое enidanness (порядковый номер с плавающей точкой не зависит от целочисленного endianness)? Или это представлено как нечто совсем другое? Хорошая документация формата файла имеет решающее значение.


В C вы бы использовали fread() и броски в стиле C, char * const pf = (char*)(&f),

Я полагаю, что вы имеете в виду методы Java ByteBuffer.

Обратите внимание, что если вы работаете с одними и теми же данными, обрабатываемыми этими функциями, Java всегда имеет БОЛЬШОЙ порядковый номер независимо от собственного порядка байтов хоста. Если вы точно не знаете, что это не так, ваш код на C, вероятно, компилируется для запуска на машине с прямым порядком байтов. Некоторые грубые рекомендации, если вы не уверены: x86 (большинство компьютеров) - это LE. ARM может быть и другим, но обычно LE. PowerPC и Itanium - это БЫТЬ.

Кроме того, никогда не разыменовывать char * или же void * к любому типу, большему чем 1 байт, если вы не знаете, что это правильно выровнено. Это приведет к неисправности шины или аналогичной ошибке, если это не так.

Так что здесь будет мой getInt() impl, предполагая буфер порядка байтов BE/ сети (например, созданный Java). Мои извинения за краткость.

typedef struct ByteBuffer {
    const char * buffer;   /* Buffer base pointer */
    int          nextByte; /* Next byte to parse */
    int          size;     /* Size of buffer */
} ByteBuffer_t;

/* Get int from byte buffer, store results in 'i'. Return 0 on success, -1 on error */
int getInt(ByteBuffer * bb, int * i) {
   const char * b;
   if( (bb->nextByte + 3) < bb->size ) {
      b = &(bb->buffer[bb->nextByte]);
      /* Read as big-endian value */
      *i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[0];
      bb->nextByte += 4;
      return 0;
   } else {
      return -1;
   }
}


void test(const char * buf, int bufSize) {
   ByteBuffer_t bb;
   int ival;

   bb.buffer = buf;
   bb.size   = bufSize;
   bb.nextByte = 0;

   while(1) {
      if( 0 == getInt(&bb, &ival) )
          printf("%d\n", ival);
      else
          break;     
   }
}

РЕДАКТИРОВАТЬ: Удален вызов ntohl().... он не принадлежал, если ваши исходные данные были действительно с прямым порядком байтов. Если это сработало с этим вызовом, вам, вероятно, нужно поменять порядок байтов в пакете shift, что означает, что вместо этого он будет анализировать байтовые потоки с прямым порядком байтов.

Есть функция getchar().

Стандартные методы ввода с использованием

scanf("<format specifer string>",input param1, param2,...)

Посмотрите на http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

Другие вопросы по тегам