Portál AbcLinuxu, 29. října 2025 09:02
Řešení dotazu:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// Licence: CC0
#define COUNT 10
int main()
{
int a;
uint16_t data[COUNT]={0};
FILE *file;
uint16_t tmp;
// nastavi hodnoty
for(a=0;a<COUNT; a++)
data[a]=a;
// ulozi hodnoty
file=fopen("data.bin", "wb");
if(file == NULL)
return(1);
if(fwrite(data, COUNT*sizeof(uint16_t), 1, file) != 1)
return(2);
fclose(file);
// mazem data
bzero(data, COUNT);
// nacitavam data zo suboru
file=fopen("data.bin", "rb");
if(file == NULL)
return 3;
for(a=0;a<COUNT; a++) // nacitava subor po sekvencne, da sa aj blokovo
{
if(fread(&tmp, sizeof(uint16_t), 1, file) != 1)
return 4;
data[a]=tmp;
}
fclose(file);
// kontrolujem, ci nacitalo to, co som zapisal
for(a=0;a<COUNT; a++)
if(data[a] != a)
{
fprintf(stderr, "data[a] != a: %u != %d\n", data[a], a);
return 5;
}
return 0;
}
bzero(data, COUNT*sizeof(uint16_t));
int pole[1000000]; fread(pole,sizeof(int16_t),1000000,f); int16_t *p=(int16_t *)&(pole[0]);... a "p" môžeš použiť ako pole: p[i]
Mezikrok v podobě 16bit pole samozřejmě funguje, ale raději bych tolik neplýtval pamětí.
Huh? Vždyť není třeba nikde plýtvat pamětí:
void stretch16b32b(void* array, size_t size) {
const uint16_t *input = (uint16_t*)array + size - 1;
uint32_t *output = (uint32_t*)array + size - 1;
while (output >= (uint32_t*)array) { *output-- = *input--; }
}
Tady je totéž v nějakém kontextu:
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
static void stretch16b32b(void* array, size_t size) {
const uint16_t *input = (uint16_t*)array + size - 1;
uint32_t *output = (uint32_t*)array + size - 1;
while (output >= (uint32_t*)array) { *output-- = *input--; }
}
static int try_close(FILE *f) {
int errors = 0;
if (ferror(f)) { fputs("Read error\n", stderr); ++errors; }
if (fclose(f)) { perror("Close error"); ++errors; }
return errors;
}
static int fread16b(const char* file, void *array, size_t size) {
FILE *const f = fopen(file, "r");
if (!f) { perror("Open error"); return 0x1; }
size_t items = fread(array, sizeof(uint16_t), size, f);
if (items != size) {
fputs("Too few elements or read error\n", stderr);
return 0x2 + try_close(f);
}
if (fread(array, 1, 1, f)) { fputs("Input too long\n", stderr);
return 0x4 + try_close(f); }
if (!feof(f)) { fputs("This must not happen\n", stderr);
return 0x6 + try_close(f); }
const int retval = try_close(f);
if (retval) { return 0x8 + retval; }
return 0;
}
static size_t readuint(const char *input, int *error) {
char *end;
errno = 0;
const size_t result = strtoul(input, &end, 10);
if (errno) { perror("Invalid number\n"); ++*error; return 0; }
if (*end || input == end) { fputs("Invalid number\n", stderr);
++*error; return 0; }
return result;
}
int main(int argc, const char *const *argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <number of shorts> "
"<input file>\n", argc ? argv[0] : "program");
return 0x1;
}
int error = 0;
const size_t size = readuint(argv[1], &error);
if (error) { return 0x1 + error; }
uint32_t *const array = malloc(size * sizeof(uint32_t));
if (!array) { fputs("Out of memory\n", stderr); return 0x4; }
const uint32_t *const end = array + size;
const int retval = fread16b(argv[2], array, size);
if (retval) { free(array); return 0x10 + retval; }
stretch16b32b(array, size);
for (const uint32_t *i = array; i < end; ++i) {
if (printf("%u\n", *i) < 0) { free(array); return 0x5; }
}
free(array);
return 0;
}
Přeložíme to…
clang -std=c11 -march=native -O3 -Wall -Wextra -pedantic compactread.c -o compactread
…a trochu to otestujeme:
Příklad 1 (little endian):
$ echo -en '\x1\x0\x2\x0\x3\x0\x4\x0\x5\x0\x6\x0\x7\x0' | ./compactread 7 /dev/stdin 1 2 3 4 5 6 7
Příklad 2 (little endian):
$ echo -en '\x1\x1\x1\x1' | ./compactread 2 /dev/stdin 257 257
Příklad 3 (little endian):
$ echo -en '\xff\xff' | ./compactread 1 /dev/stdin 65535
Příklad 4 (naprosto k hovnu, ale valgrindem taky projít musí):
$ echo -en '' | ./compactread 0 /dev/stdin
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.