patterncMinor
A simple command line linear interpolator in C
Viewed 0 times
linearsimplelinecommandinterpolator
Problem
I'm trying to become more familiar with C (been working through the MIT Practical Programming in C course and K&R) so decided to write a simple command-line linear interpolator. You can feed it a vector (where missing values are represented by 0n) and it should print an interpolated vector. Any comments on style etc are much appreciated.
#include
#include
#include
#define NULLA "0n"
#define NULLF -1000
#define MAXLEN 1000
int main(int argc, char * argv[])
{
if(argc MAXLEN)
{
printf("vector is too long\n");
return 2;
}
float start, end, delta; //bound values and change for interpolation
int num_nulls = 0; //number of nulls in a given interpolation range
float filled[MAXLEN]; //vector where we will put our values
int i, j; //indices, for argv[] and filled[] vectors, correspondingly
//we want all values in filled to be initalized to zero, to avoid junk vals
for(j = 0; j 0)
{
end = atof(argv[i]);
delta = (end - start) / (1 + num_nulls);
while(num_nulls-- > 0)
{
start+=delta;
filled[j++] = start;
}
filled[j++] = end;
start = end; //we should be ready for another interpolation
num_nulls = 0;
}
else
num_nulls++;
}
//add in any trailing nulls, since interpolation can't be performed
while(num_nulls-- > 0)
filled[j++] = NULLF;
for(i = 0; i < j; i++)
{
if(filled[i] != NULLF)
printf("%.2f ", filled[i]);
else
printf("%s ", NULLA);
}
putchar('\n');
return 0;
}Solution
Program Usage:
Your usage string is a little...aenimic. I didn't read the initial
part of your post about needing to use 0n as a "missing" value, and
had to squint a little bit before I figured out what is was doing.
This sort of information should ideally be printed out (either when
the user doesn't input enough arguments, or if a flag is passed;
generally this would be
Initialization:
There's a little trick for array initialization in C that comes in
handy. Instead of having to loop over an array, initializing it
with the same value:
You can simply write:
This will initialize each value of your array to 0.0.
Functions:
When you start writing programs, they're generally quite small, and
a lot of the time everything fits neatly into
you start writing slightly larger programs, this starts to become
inconvenient. It makes your program harder to follow, lets variables
live for longer than they should, and means parts of a program cannot
easily be reused (and further along in your programming career, it
makes things harder to test, too). A large part of programming
is breaking things down into small pieces, writing those small
pieces separately, and composing them together into a solution.
Here, there are a few things that should exist as functions. The
first one we've already shown;
performs the interpolation should also be inside its own function:
Braces:
It's tempting to omit braces when you're only using a single-line
command:
Although this is a point of some contention, it's (generally) not
seen as very good practice, especially in a language like C. It is
all too easy for you (or someone else) to come back to the code to
make a minor modification, and forget that there are no braces:
Prefer to wrap even single line statements in { }. It is almost
zero effort, and will stop these kinds of mistakes.
const vs #define:
Prefer to use
of the quirks of C, this is not always possible:
A lot of older C code uses it (because there was no other option),
but it is still a good idea to keep its use to a minimum.
Your usage string is a little...aenimic. I didn't read the initial
part of your post about needing to use 0n as a "missing" value, and
had to squint a little bit before I figured out what is was doing.
This sort of information should ideally be printed out (either when
the user doesn't input enough arguments, or if a flag is passed;
generally this would be
-h or --help):void print_usage()
{
printf("Usage: lin_interp \n");
printf("lin_interp linearly interpolates pairwise. To input "
"values to be interpolated, use 0n. For example:\n"
"lin_interp 100 0n 200\n"
"will produce 100.0 150.0 200.0, where 0n has been "
"replaced by the interpolated value.");
exit(1);
}Initialization:
There's a little trick for array initialization in C that comes in
handy. Instead of having to loop over an array, initializing it
with the same value:
for(j = 0; j < MAXLEN; j++)
filled[j] = 0.;You can simply write:
float filled[MAXLEN] = {0.0f};This will initialize each value of your array to 0.0.
Functions:
When you start writing programs, they're generally quite small, and
a lot of the time everything fits neatly into
main. However, whenyou start writing slightly larger programs, this starts to become
inconvenient. It makes your program harder to follow, lets variables
live for longer than they should, and means parts of a program cannot
easily be reused (and further along in your programming career, it
makes things harder to test, too). A large part of programming
is breaking things down into small pieces, writing those small
pieces separately, and composing them together into a solution.
Here, there are a few things that should exist as functions. The
first one we've already shown;
print_usage(). The code thatperforms the interpolation should also be inside its own function:
size_t interpolate(float* filled, size_t len)
{
// Interpolation Code
}Braces:
It's tempting to omit braces when you're only using a single-line
command:
for(i = 1, j = 0; i < argc && strcmp(argv[i], NULLA) == 0; i++)
filled[j++] = NULLF;Although this is a point of some contention, it's (generally) not
seen as very good practice, especially in a language like C. It is
all too easy for you (or someone else) to come back to the code to
make a minor modification, and forget that there are no braces:
int starting_nulls = 0;
for(i = 1, j = 0; i < argc && strcmp(argv[i], NULLA) == 0; i++)
filled[j++] = NULLF;
++starting_nulls; //Uh-oh!Prefer to wrap even single line statements in { }. It is almost
zero effort, and will stop these kinds of mistakes.
const vs #define:
Prefer to use
const instead of #define whenever you can. Becauseof the quirks of C, this is not always possible:
// This has to be a #define to be used in an array length
#define MAXLEN 1000
// These can both be const
const char NULLA[] = "0n"
const float NULLF = -1000.0f;#define is a very crude mechanism that can cause a lot of headaches.A lot of older C code uses it (because there was no other option),
but it is still a good idea to keep its use to a minimum.
Code Snippets
void print_usage()
{
printf("Usage: lin_interp <list of floating point values>\n");
printf("lin_interp linearly interpolates pairwise. To input "
"values to be interpolated, use 0n. For example:\n"
"lin_interp 100 0n 200\n"
"will produce 100.0 150.0 200.0, where 0n has been "
"replaced by the interpolated value.");
exit(1);
}for(j = 0; j < MAXLEN; j++)
filled[j] = 0.;float filled[MAXLEN] = {0.0f};size_t interpolate(float* filled, size_t len)
{
// Interpolation Code
}for(i = 1, j = 0; i < argc && strcmp(argv[i], NULLA) == 0; i++)
filled[j++] = NULLF;Context
StackExchange Code Review Q#60342, answer score: 7
Revisions (0)
No revisions yet.