Чтение байтовых методов в C / C ++ - PullRequest
1 голос
/ 16 сентября 2011

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

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

Ответы [ 4 ]

8 голосов
/ 16 сентября 2011

Нет, двоичная (де) сериализация напрямую не поддерживается систематически библиотекой.Функция 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));

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

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 (порядковый номер с плавающей точкой не зависит от целочисленного порядкового номера)?Или это представлено как нечто совсем другое?Хорошая документация о формате файла имеет решающее значение.


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

1 голос
/ 16 сентября 2011

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

Обратите внимание, что если вы работаете с одними и теми же данными, обрабатываемыми этими функциями, то Java всегда имеет БОЛЬШОЙ порядковый номер независимо от порядка байтов собственного хоста .Если вы точно не знаете, что это не так, ваш код C , вероятно, компилируется для запуска на LITTLE endian машине.Некоторые грубые рекомендации, если вы не уверены: 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, что означает, что вместо этого он будет анализировать байтовые потоки с прямым порядком байтов.

0 голосов
/ 16 сентября 2011

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

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

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

Взгляните на http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

0 голосов
/ 16 сентября 2011

Поскольку арифметика указателей находится в самой природе 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)++;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...