4 ms·
No mention of printf and scanf. Printf is annoying because of the PRIu32 macros in case you want to print uint32_t in a portable way. How about conversion spe
by jhallenworld 4y ago
No mention of printf and scanf. Printf is annoying because of the PRIu32 macros in case you want to print uint32_t in a portable way. How about conversion specifiers for the stdints.. %u32 %d32 or whatever.
As for scanf: I want it to either succeed in parsing all of the arguments, or fail, but in this case leave the file position unchanged (so random access is required on input). This would allow trying to parse with another call to scanf, but with a different format string. For lists involving an arbitrary number of items, provide a conversion specifier that leaves the input alone and returns success: this way you can iterate the list.
For example, these would be equivalent:
if (scanf(f, "%d %d %d", &a, &b, &c)) printf("Success!\n");
if (scanf(f, "%d %e", &a) && scanf(f, "%d %e", &b) && scanf(f, "%d", &c)) printf("Success!\n");
/* %e means more input expected, without it scanf fails if no EOF at that point */
I should be able to provide my own parsing functions in it: imagine a conversion specifier for JSON that returns a tree.
The existence of sprintf and sscanf point to bad design: I should be able to open a block of memory as a FILE, which would make sprintf and sscanf redundant. Also I should be able to open some kind of block device: meaning the FILE has pointers to user provided read and write functions. With this I could printf and scanf to some indirect device such as an EEPROM.
We should be using scanf for the program's argument list. I mean the program should not get an array of pointers, but instead a FILE that contains the arguments. The memory layout is then abstracted. The pre-conversion of the command line to an array is totally unnecessary, only exists because libc's scanf sucks.
Arbitrary length strings could have been handled with FILEs..
- leni536 4y agoFrom the article: > As for formatted input, don’t ever bother with scanf. With an entire other article about scanf as the link. edit: As for your other point, files may not even be seekable, let alone random access. How should that be implemented for a pipe?
- jhallenworld 4y agoAck, you are right, I read it too fast (triggered my pet peeve too early..) If the input is really not random access capable, provide buffering. You could imagine a version of FILE that automatically does this. There could be a some kind of truncate call to make it forget all past input, once you are sure it's not needed. In an OS you will have the resources to do this (malloc..). In other contexts (embedded), you may not.. but likely in those cases you don't have pipes. With a bit more we can have full arbitrary backtracking parsing. This parses "<hex> bob | <decimal> fred" or prints the unknown input: if( fscan_push(f) && fscanf(f, "%d %e", &n) && fscanf(f, "fred") && fscan_done(f) || fscan_backup(f)) printf("got fred(%d)\n", n); else if( fscan_push(f) && fscanf(f, "%x bob", &n) && fscan_done(f) || fscan_backup(f)) printf("got bob(%x)\n", n); else printf("got something else '%f'\n", f); '%e' expect more input fscan_push: save current location on a stack associated with FILE. Return true. fscan_done: drop location from stack. Return true. If stack becomes empty, drop input history up to current file position. fscan_backup: restore to location from stack. Return false. '%f' in printf prints the rest of the specified FILE on the stdout.
- skissane 4y ago> No mention of printf and scanf. Printf is annoying because of the PRIu32 macros in case you want to print uint32_t in a portable way. How about conversion specifiers for the stdints.. %u32 %d32 or whatever. C23 fixes this - it introduces %w32d as a replacement for PRId32, %w64d to replace PRId64, %w64u, etc.