Portál AbcLinuxu, 12. května 2025 06:46
Ř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 valgrind
em taky projít musí):
$ echo -en '' | ./compactread 0 /dev/stdin
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.