6 ms·
Show HN: Calc, a simple command-line calulator in C
- jhallenworld 11y agoFor your amusement: a calculator written in BASIC: https://github.com/jhallen/joes-sandbox/blob/master/snippets/parse.bas https://github.com/jhallen/joes-sandbox/blob/master/snippets...
- pwg 11y agoHow is this different from the existing command-line calculator 'bc'? echo "3+4" | bc 7 Other than not needing equations to be piped to it? Note also that bc allows defining functions (among other features), and is also arbitrary precision (factorial of 200 below): $ echo "define f (x) { if (x <= 1) return (1); return (f(x-1) * x); }; f(200)"| bc 78865786736479050355236321393218506229513597768717326329474253324435\ 94499634033429203042840119846239041772121389196388302576427902426371\ 05061926624952829931113462857270763317237396988943922445621451664240\ 25403329186413122742829485327752424240757390324032125740557956866022\ 60319041703240623517008587961789222227896237038973747200000000000000\ 00000000000000000000000000000000000
- creshal 11y agoWriting your own calculator is a nice programming exercise (touches a lot of different problems and is still a small, manageable task), especially for languages you're not familiar with. Of course there's better ones for "production" use.
- vivekkannan 11y agoObviously, bc is much more capable than calc. However, calc was not created to replace or even compete with bc or any other awesome command-line calculators. calc is my way of learning a bunch of stuffs (shunting yard).
- nemoniac 11y agoFirst learning tip: .h files are not the place for definitions.
- vivekkannan 11y agoduly noted. will change it ASAP.
- Dewie3 11y agoThat function syntax is a nice example of C-isms bleeding through. If I want to write some arithmetic, I want something more declarative and succinct than C.
- murbard2 11y agoGive the venerable dc a try. It can be quite succinct. http://en.wikipedia.org/wiki/Dc_%28computer_program%29 http://en.wikipedia.org/wiki/Dc_%28computer_program%29
- torrent-of-ions 11y agoThis one doesn't have abitrary precision?
- bstamour 11y agoYou can use bc interactively just fine, no needing to pipe anything. $ bc 3+4 7 ^D $
- sudmishra 11y agoWhy not just use simple python or sympy?
- SamReidHughes 11y agoVery cool. But let me warn you: Your method of code organization won't scale to anything whose #include graph doesn't form a tree. You should learn how to put your declarations into include-guarded header files and your implementations into C files. Also, abs has signature int abs(int x). I think you want to use fabs. Edit: Also, it is quite peculiar to have the program print out null characters. The output for ./calc '2' is four characters: {'2', '\0', '\0', '\n'}. In places where you're using %c and printing '\0', you could use %s and print "" instead.
- maq123 11y agoRegarding code organization ... Any learning sources where some approaches are being explained ? I am sysadmin and sometimes I find it hard to understand how source files I just downloaded connected to each other. Thx
- SamReidHughes 11y agoAny book on C. The early chapters of an online C tutorial.
- dagw 11y agoI just checked the first 5 C tutorials the showed up in Google and non of them talked about code organization in anything but the most superficial sense.
- kevinnk 11y agoTry http://www.tutorialspoint.com/cprogramming/c_header_files.htm http://www.tutorialspoint.com/cprogramming/c_header_files.ht...
- enesunal 11y agosearch for 'C best practices'. I've even seen a guideline from Linus Torvalds a few months ago.
- 11y ago
- jhallenworld 11y agoIt's weird that most of the code is in the header files.. also do you check for divide by zero? Try to rewrite the whole thing as a single recursive function with two arguments (rest of input string, precedence of left side). You could use longjmp/setjmp to abort when there are errors.
- vivekkannan 11y agoI checked division by zero initially, but then realised that 1/0 causes double to represent inf. Thought that this could be useful(?) in some situations. For example, atan(1/0) --> 1.57... instead of error.
- jhallenworld 11y agoI was thinking to catch errors which could crash the program. Actually you should install a signal handler for SIGFPE to take care of this.
- harunurhan 11y agoSeveral months ago, I was looking for something like this. Then I started using bc but wasn't enough for me then I thought why not Python? It has tons of math and statistics libraries/functions and easier than shell script with bc. So I started using Python by simply typing Python and do my stuff. It is fast enough and super productive.
- bnegreve 11y agoFWIW, I use awk, which is POSIX standard $ awk 'BEGIN{print sqrt(2)+4;}'; 5.41421 bc is also standard but for some arbitrary reason I don't like it.
- acomjean 11y agoAnother option would be to use the language called "R". I'm fairly new to it but its pretty much a programming language for math. Lots of libraries. Great programmatic graphing capability (ggplot2). Easy to dump file data into it. In my lab a lot of biologists run there data with it. I think something like 80% of the graphs they publish are created in it. Better then excel in my opinion. R, and Rstudio is what I've been using.
- leni536 11y agoI prefer explicit parenthesis for functions. That way you won't bump into much trouble if you want to implement functions with multiple arguments.
- mct 11y agoI've been using a perl-based calc for a number of years now. It started as a one liner eval-ing expressions on the command line. My favorite feature is that if symlinked as "hex", "oct", or "bin", it prints the output in hexadecimal, octal, or binary. And, because the evaluation is done by perl, hexadecimal, octal, and binary numbers can be entered using "0x", "0", and "0b" prefixes. A minor improvement was the substitution of commas with underscores, which perl allows in numbers for easier readability. Entering "1,000,000" is much nicer on the eyes than carefully counting the number of trailing zeros. Two weeks ago, after becoming fed up with having to copy and paste results from one line to the next, I wrapped it in a repl and added bc(1)-like support for "." expanding to the last value. Rather embarrassingly, I started to implement bc(1)-style variables, but then realized this was incredibly silly as you can simply use perl variables directly. :-) https://github.com/mct/junkdrawer/commits/master/bin/calc https://github.com/mct/junkdrawer/commits/master/bin/calc I fully support writing other calc implementations, especially in languages such as C! It's a great exercise, and can become very complex very quickly. bc(1) supports arbitrary precision (try: echo "scale=500; 4a(1) 42" | bc -l), which is super awesome. In C, I've only implemented RPN calculators, never infix, which would be fun to try.
- jhallenworld 11y agoActually strtod will convert 0x to hex.. It would be nice if it had an option to ignore commas.
- sbrk 11y agoBeen done, a long time ago. http://www.isthe.com/chongo/tech/comp/calc/index.html http://www.isthe.com/chongo/tech/comp/calc/index.html
- joshbaptiste 11y agoFYI, a Go version was announced not too long ago also: https://github.com/alfredxing/calc https://github.com/alfredxing/calc
- agentultra 11y agoNice! Suggestion: you could probably use `asprintf` to malloc the input expression string and use the Stopif variadic macro to return an error if the input takes up more than the available memory. Unless of course your target platform doesn't have the GNU libraries in which case you could write a test macro and insert your own implementation using `vsnprintf`. :) You might also want to check your input lengths for reasonable size before allocating memory for them. My first stop learning a new language is usually a project like this or a guess-the-number game. I hope it's been helpful to you.
- enesunal 11y agoSuggestion: Move your business logic into .c files. Headers is there for other reasons. Take a look at, http://embeddedgurus.com/barr-code/2010/11/what-belongs-in-a-c-h-header-file/ http://embeddedgurus.com/barr-code/2010/11/what-belongs-in-a...
- ihuk 11y agoSo being barely able to write C is now Hacker News-worthy?
- antocv 11y agoNext, "Show HN: I programmed this hello world program, in Java Script". Yes, with space between Java Script, and "programmed a program".
- deutronium 11y agoPlease don't put the functions themselves in .h files, only the prototypes
- powercf 11y agoYour value of pi is incorrect in the code, comments and readme. pi is 3.1415926... (and not 3.14151926...).
- vivekkannan 11y agochanged it. thanks.
- userbinator 11y agoI assume you posted this looking for feedback, so here is my advices: - A 16-line main.c with a single function that does almost nothing is annoying to say the least; this application is simple enough that I think it really shouldn't be more than a single file. - You really don't need to use dynamic allocation for this. Try a simpler algorithm like recursive-descent/precedence climbing, and tokenise+evaluate as you go. - isSymbol()/getSymbol() should be merged into one function - you are doing duplicate work here since once you know that it is one of those special identifiers, you should be able to return the value immediately instead of doing another set of comparisons. This is an almost-complete C interpreter in roughly the same number of lines of code as your calculator, but its structure is actually much simpler. It's probably a bit far toward the side of terseness, but good to study in any case: https://github.com/rswier/c4/blob/master/c4.c https://github.com/rswier/c4/blob/master/c4.c For understanding precedence climbing/recursive descent, this is a good article: https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm One thing I see with a lot of beginners is a tendency to overcomplicate solutions, writing far more code than necessary. It takes practice to avoid this, but giving them some extremely minimal implementations to study can help them to better understand the essence of the problem and its solution; to a beginner, it is often simpler than they seem to be at first glance.
- jbert 11y agoSomeone did a nice calculator hack a little while back, based upon an old reddit comment of mine: http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horribly-awesome-abuse-of-gcc/ http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horri... http://www.reddit.com/r/programming/comments/62v70/first_class_functions_in_c/c02nqcu http://www.reddit.com/r/programming/comments/62v70/first_cla...
- freefouran 11y agoInteresting, this is basically a very simple interpreter with a REPL. You should look into interpreters if this is something you enjoyed creating, there are many efficient and simple algorithms you could use to make this program a lot simpler and even more advanced too. For instance, recursive descent parsing, and the shunting yard algorithm.
- RhysU 11y agoNice. Mucked about with Boost Spirit's examples once to do something similar in one grammar-driven file: http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-... Final production version with better error reporting is under "expr*" files at https://github.com/RhysU/suzerain/tree/master/suzerain https://github.com/RhysU/suzerain/tree/master/suzerain