Reputation: 1955
I am assuming I am using this the wrong way, but the idea is for the command line argument to be the length of my fibonnaci serquence... however the way I am doing this, after 9 I am screwed... how can I resolve this issue?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for fork */
#include <sys/types.h> /* for pid_t */
#include <sys/wait.h> /* for wait */
int fibonacci(int n)
{
int first = 0;
int second = 1;
int total, i;
for (i=0;i<n;i++)
{
printf("%d\n", first);
total = first + second;
first = second;
second = total;
}
return 0;
}
int main(int argc, char *argv[])
{
/*Spawn a child to run the program.*/
pid_t pid=fork();
if (pid==0) { /* child process */
if(*argv[1] == 45){
printf("number invalid \n");
}else{
int number = *argv[1] - 48;
fibonacci(number);
}
}
else { /* pid!=0; parent process */
waitpid(pid,0,0); /* wait for child to exit */
}
return 0;
}
Upvotes: 0
Views: 927
Reputation: 755006
Command line arguments are strings; convert the strings to integers:
int number = 9;
if (argc > 1)
number = atoi(argv[1]);
This gives you a default value (9), and the option to override it. More thorough checking would reject more than 1 argument, and negative or zero returns from atoi()
:
enum { MAX_FIBONACCI = 47 };
if (argc > 2)
{
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2)
{
number = atoi(argv[1]);
if (number <= 0)
{
fprintf(stderr, "Invalid number %s\n", argv[1]);
exit(EXIT_FAILURE);
}
else if (number > MAX_FIBONACCI)
{
fprintf(stderr, "Number %s is too large (max is %d)\n", argv[1], MAX_FIBONACCI);
exit(1);
}
}
Note that key information is reported to help identify what went wrong. After 47 entries, you overflow a 32-bit signed integer.
Note that testing for errors from strtol()
et al properly is a moderately complex business if you have to accommodate any return value whatsoever. If you only need to accommodate the range that you can print Fibonacci numbers for, it is rather simpler.
The repeated four lines of error handling rapidly gets irksome. I use a function like this instead:
#include <stdarg.h>
void err_exit(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
This reduces the error reporting to one line per error, which is preferable to four lines. (My full system is more complex than that, by quite a margin — all else apart, it gets told the program name and reports it automatically. But that's a workable starting point.)
Upvotes: 0
Reputation: 183978
You should parse the command line argument using strtol
, or similar, for example
number = strtol(argv[1],NULL,0);
/* last parameter gives the base, 0 detects hexadecimal (0x) and octal, defaults to 10 */
if you want to skip error checking. Cleaner, with error checking:
char *end;
number = strtol(argv[1],end,0);
if (end == argv[1])
{
/* no valid digits */
exit(EXIT_FAILURE);
}
if (*end)
{
/* not all of argv[1] has been consumed
* handle errors
*/
}
/* full parse of argv[1], no problems, carry on */
Upvotes: 1
Reputation: 34031
Your way could be extended to handle more than one digit, but I think that what you're really looking for is atoi()
or the non-deprecated strtol()
.
Upvotes: 1