Show HN: Calc, a simple command-line calulator in C
github.com
github.com
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.
* The dependencies (includes) of the implentation
* A list of function signatures, data structures it provides, etc
* Any constant definition specific to the module
Another "feature" of separating the header file from the implementation is that it guards against recursive includes, as the commenter above suggested.
So your calc.h and calc.c should look something like this: https://gist.github.com/jdiez17/2f093b2c8cc2913bb890
Main problem with dependencies in the headers is that if any header of your library include headers from the different libraries the user will have have to (1) have those headers, (2) probably configure their build to use them, even if they bring zero useful information for them.
Besides, in my mind it's the logical place to put it: the header file is almost like the "spec" or the "coversheet" of a .c. It includes the name, the authors, possibly a description of what it does, a list of functions and datatypes, so why not a list of dependencies as well?
Another reason is namespace pollution (if only for better autocomplete), and another is that you don't walk yourself into a situation where editing one header file suddenly gives you a zillion name lookup errors (because that's mildly annoying).
In C++, the biggest and most substantial benefit can be the effect on compile times.
It may just be that this is the specific way in which my mind works, but I find it easier to get a clearer picture of the file if I just read the .h. It would have a summary (in terms of comments and code, like function declarations) and a list of includes.
>it is often very useful if you can immediately see a short list of .c files that could possibly access the interface exposed by a particular header file.
If you wanted to see which files use the interface in that header file directly, you can scan your headers for ones that include it explicitly, instead of working backward from the header. And a similar thing with the autocomplete problem: only load the header files mentioned in thing.h (assuming you're editing thing.c).
The increased compilation time is a good argument. I don't know any good way to mitigate it, but all these three problems sound like engineering problems to me, rather than a problem intrinsic to this approach.
Your .c files that use the interface will often be including it implicitly though, projects very quickly drift in that direction.
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.h files are not the place for definitions.
$ bc
3+4
7
^D
$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.
- 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
For understanding precedence climbing/recursive descent, this is a good article:
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.
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
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.
So I started using Python by simply typing Python and do my stuff. It is fast enough and super productive.
$ awk 'BEGIN{print sqrt(2)+4;}';
5.41421
bc is also standard but for some arbitrary reason I don't like 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.
Take a look at, http://embeddedgurus.com/barr-code/2010/11/what-belongs-in-a...
Final production version with better error reporting is under "expr*" files at https://github.com/RhysU/suzerain/tree/master/suzerain
http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horri...
http://www.reddit.com/r/programming/comments/62v70/first_cla...
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.
https://github.com/jhallen/joes-sandbox/blob/master/snippets...