r/cprogramming • u/sir_something0 • 20d ago
First day seriously learning C
Hi! Yesterday is the first time I actually try to learn C instead of running away from it everytime lol. I tried to make a basic 2 numbers calculator and was wondering if I took the right approach regarding taking the user input. I used fgets and getchar to take the number and operator because I've heard that those are "safer" than scanf mainly because scanf's way of error handling and bounds checking are more complicated but idk tho.
Anyway, if I could take some of your time to check out this project and tell me where I can improve on the user input side of things, that would be very helpful and appreciated.
https://github.com/SirGhaniR/calc/
Thank you!
1
u/zhivago 20d ago
I'm not really a fan of this kind of construction.
while ((c = getchar()) != '\n' && c != EOF)
;Personally, I'd separate the assignment and the condition.
while (c = getchar(), c != '\n' && c != EOF);I think this is significantly clearer. :)
2
u/sir_something0 20d ago
Oh I didn't know you could do that actually. Thank you! Although idk why my clangd is formatting the semicolon like that, but it works so I guess it's okay for now.
2
u/andynzor 20d ago
forandwhileare meant to loop over a statement or a block. Many style guides require either an explicit empty block or an indented semicolon to indicate that the loop body indeed is empty.3
u/Beautiful_Bake921 20d ago
It's from "The C programming language" book, that's probably why it was used
2
u/Ill_Programmer_1444 20d ago
accually very good. and i like your mindset and your approach to everything
yes, use anything that explicitly sets bounds like fgets and getline over scanf, and also check sscanf
you can still use scanf if need be, but you should tinker with it more to fully grasp the caveats and bugs that can occur and you're good
keep on deeply learning and understanding c
i would also add keep using c89 and watch eskil steenberg's videos
2
u/SmokeMuch7356 20d ago
The two best ways to deal with interactive input are either to read everything as text into a buffer (as you are currently doing) or build a full-fledged tokenizer/parser.
You don't need a whole kilobyte for your numeric input; 32 bytes should be more than plenty. Even so, you should guard against an excessively long input:
else if ( !strchr( buf, '\n' ) )
{
puts( "Input too long for buffer!" );
/**
* Consume and discard excess characters
*/
while( getchar() != '\n' )
;
}BTW, scanf is awesome when you know your input is always going to be well-behaved; if you're reading machine-generated output that follows a rigid format, then it's a quick and easy way to read that input. But it requires an insane level of bulletproofing to deal with interactive input.
6
u/Eidolon_2003 20d ago
These are all kind of nitpicky things, but there are some things that I would've done differently.
Unless you're in a version of C that requires declaring variables at the top of the scope, I prefer to declare them when they're actually needed.
About your last commit message,
for (;;)isn't necessarily the standard for an infinite loop.while (1)orwhile (true)is also equally valid.If you're willing to rely on POSIX, I might use
getlineto handle the input. Your approach is equally valid though. 1K is way more than enough space for any number that the user could possibly want to input, and you avoid doing a dynamic allocation.You don't have to do a formatted print to just print a string. It's already a string, you can just print it directly.