"What's the book that has all the answers?" β The C Programming Language K&R
/s
comments
- Don't write in languages with UB.
End of list
Oh I see, many thanks.
That's generally how it's done.
I don't know what a .map file is, will look into that. This does work, when I objdump it _start is at 0x0. But I'm curious if there is a better solution, I'd like to learn how it's properly done.
That looks like it should work. Have your linker generate a .map file - where does it show your _start symbol? Is it also showing it in the .boot section?
Ohhh, that makes sense! Thank you for explaining!
'0'..'9' (characters in ASCII) are (0+48)..(9+48) when read as integer values.
For readability you can do:
unsigned char zero = '0';
int h = getchar() - zero;
int l = getchar() - zero;
And as I mentioned in another comment, if this was serious code, you would check that both h and l are between 0 and 9.
Note that one of the stupid quirks about C is that char is not guaranteed to be unsigned in certain implementations/architectures. So it's better to be explicit about expecting unsigned values. This is also why man 3 getchar states:
fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error.
getchar() is equivalent to fgetc(stdin).
Yeah, it worked, thanks a lot!! Could you explain what deducing 48 out of h and l does? I don't want to just copy and forget abt this(no pressure, you already helped a lot!!!)
oughhh right, thanks for pointing that out!!
If the input is anything of the form 00XX, then p1 == 0. This will fail for p1 != 0 as well as p1 >= 13, meaning neither of the top-level ifs will trigger.
This is unnecessarily complicated
really!
and I donβt see how your second version is supposed to be more optimal?
It was a half-joke. But since you asked, It doesn't do any duplicate range checks.
But it's not like any of this is going to be measurable.
Things you should/could have complained about:
- [semantics] not checking if
handlare in the [0, 9] range before taking the result ofh*10 + l. - [logical consistency] not using a set bet for [0, 100] and a set bit for [1, 12], and having both bits set for the latter.
- [cosmetic/visual] not having the props bits for p0 on the left in the switch.
And as a final note, you might want to check what kind of code compilers actually generate (with -O2/-O3 of course). Because your complaints don't point to someone who knows.
This is unnecessarily complicated, and I don't see how your second version is supposed to be more optimal? You're just adding pointless indirection by encoding the branching logic as an int, and then branching again in a switch statement.
This would be easier to understand if you defined a function like:
char IsMonth(int value){
return value > 0 && value <= 12;
}
Then try to rewrite your program using that inside of the if statements. For example
if(IsMonth(p1)){
...
}
If you do that, I'm pretty sure you'll find the problem. As a hint, notice that IsMonth is a boolean value, since a number can only either be a month (true) or not a month (false). I haven't debugged it, but I can tell there's a problem just by the number of printf statements you currently have.
Input 0000 and 0 are the same in the flow of your program.
Thank you so much for your time! Holy shit you went deep there, even optimized itπ I'm 4ever grateful, gotta go try it, be back with results!
The site where I submit my answers only inputs four digit positive numbers so idk either Β―_(γ)_/Β―
The site that accepts & checks this code is programmed to only input 4 digit inputs so i didn't account for any other options
Thank you for your reply!! I'll look into it! Although I don't think I'll be able to make it a function(I've been procrastinating studying that topicπ« )
Maybe something like this
#include <stdio.h>
// reads next 4 chars. doesn't check what's beyond that.
int get_pair() {
int h = getchar() - 48;
int l = getchar() - 48;
return h * 10 + l;
}
int main(){
int p0 = get_pair();
int p1 = get_pair();
if (p0 < 0 || p1 < 0 || p0 > 100 || p1 > 100) {
// not 4 digi seq, return with failure if that's a requirement
}
if ((p0 == 0 || p0 > 12) && (p1 >= 1 && p1 <= 12)) {
printf("YYMM");
} else if ((p1 == 0 || p1 > 12) && (p0 >= 1 && p0 <= 12)) {
printf("MMYY");
} else if ((p0 >= 1 && p0 <= 12) && (p1 >= 1 && p1 <= 12)) {
printf("AMBIGUOUS");
} else {
printf("NA");
}
return 0;
}
or if you want to optimize
#include <stdio.h>
#include <stdint.h>
// reads next 4 chars. doesn't check what's beyond that.
int get_pair() {
int h = getchar() - 48;
int l = getchar() - 48;
return h * 10 + l;
}
uint8_t props (int p) {
if (p >= 1 && p <= 12) {
return 0b10;
} else if (p < 0 || p >= 100) {
return 0b11;
} else {
return 0b00;
}
}
int main(){
int p0 = get_pair();
int p1 = get_pair();
switch (props(p0) | (props(p1) << 2)) {
case 0b1010: printf("AMBIGUOUS"); break;
case 0b1000: printf("YYMM"); break;
case 0b0010: printf("MMYY"); break;
default: printf("NA");
}
return 0;
}
What happens in your program when scanf stores -1 as the value, like if it hits EOL before finding matching input?
Maybe you covered this and I missed it.
If input is 0 then the program prints nothing instead of NA
No time to check but:
scanf("%4d", &S)or something- you have
if,else if, but no simpleelsein the end - add \n to printf
Last but not least: move the code after scanf to its own function that takes 1 number XXXX or 2 numbers (XX and YY), and call it in a loop for (int i = 0; i < 9999; ++i) and print the results like: "p1, p2, result", that way you'll quickly check which value is invalid or not.
@CodiUnicorn Good read
On the off-chance you haven't checked stackoverflow, C was much more popular in that site's heyday, and snippets were certainly something it was good for up until microsoft bought it.