Segmentation Fault when using command-line arguments - c

I'm new to programming. Following is a program I wrote to calculate the probability distribution of random 6-sided dice throws. It works perfectly, however if I use command-line argument for number of throws, it starts throwing up segmentation fault error. Can somebody help me understand what I am doing wrong ?
// distribution of rand numbers
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
const unsigned short NUM_FACES = 6;
int main(int argc, char * argv[])
{
if(argc != 2 || isdigit(argv[1]))
{
printf("Invalid arguments!!\n");
printf("Usage: %s numThrows\n", argv[0]); //correct usage of arguments
exit(EXIT_FAILURE);
}
system("clear");
srand(time(0)); //updating seed
long upperLim = atol(argv[1]);
long dist[7] = {0};
double probab = 0.0;
unsigned int i;
for(i = 0; i < upperLim; i++)
++dist[rand()%6 + 1]; //generating random numbers (1-6)
for(i = 0; i < NUM_FACES; i++)
{
probab = 100.0*dist[i]/upperLim; //calculating probability of each throws
printf("DICE THROW %d -> Number of throws: %ld Distribution: %.2lf%c\n", i+1, dist[i], probab, '%');
}
getchar();
return 0;
}

isdigit(argv[1])
isdigit wants an int, not a char *
If you want to ckeck if all characters are digits you can use something like:
bool strIsDigit(const char *str)
{
while (*str)
{
if (!isdigit((unsigned char)*str++))
{
return false;
}
}
return true;
}

Related

How to get parameters from the command line

I've got this code written in C that makes a decimal to binary conversion.
How can I make it that it gets the parameter from the command line in linux?
I know i have to use something like int main(int argc, char *argv[]) but i dont know how to implement it.
#include <stdio.h>
int main()
{
int a[10], decimal, i, j;
printf("\nIntroduceti numarul decimal: ");
scanf("%d", &decimal);
for(i = 0; decimal > 0; i++)
{
a[i] = decimal % 2;
decimal = decimal / 2;
}
printf("\nNumarul binar este: ");
for(j = i - 1; j >= 0; j--) {
printf("%d", a[j]);
}
printf("\n");
return 0;
}
You want this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("missing command line argument\n");
return 1;
}
int decimal = (int)strtol(argv[1], NULL, 10);
...
}
you need a minimal understanding of strings.
The (int) cast is for making clear that we explicitely convert the long int returned by strtol to int which may or may not be a smaller type than long int, depending on your platform.
Documentation for strtol.
Explanation about argc and argv
Answer:
#include <stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int a[10], decimal, i, j;
decimal = atoi(argv[1]);
for(i = 0; decimal > 0; i++)
{
a[i] = decimal % 2;
decimal = decimal / 2;
}
printf("\nNumarul binar este: ");
for(j = i - 1; j >= 0; j--) {
printf("%d", a[j]);
}
printf("\n");
return 0;
}
Here gcc is the c-compiler, and demo.c is the file name
After your file gets successfully compiled then ./a.out is the command to run that build file, and append the command-line argument with it, as shown in the image.
atoi(argv1) see argv[0] is the file name, argv1 is the argument, and atoi is used to convert string to int, as we can take only string input from the command line, and argc is the total number of argument user have given.

Finding the factorial of odd number from the input value in C

#include <stdio.h>
int main()
{
int input;
int result = 1;
printf("Enter the integer number : ");
scanf("%d", &input);
printf("n:!\n\n");
for(int i = 1; i <= input; i = i + 2)
{
for(int k = 1; k <= i; k++)
{
result *= k;
}
printf("%d:%d\n", i, result);
}
return 0;
}
I have created such code to determine the factorial of input's odd number. During the testing, I have found out that beyond the factorial of 5, the value gets wrong. Seems like the calculation is going wrong but I don't know what is the problem in my code.
your problem is you are multiplying result with the old value it has in each inner loop. to solve this before the start of inner loop reset result to 1 by :
result = 1;
and this is not related to the question but I prefer to avoid this algorithm as it is O(n^2 /2) we can consider it O(n^2), rather you can use this one it is O(n) :
#include <stdio.h>
int main()
{
int input;
long double result = 1;
printf("Enter the integer number : ");
scanf("%d", &input);
printf("n:!\n\n");
for(int i = 1; i <= input; i++)
{
result *= i;
if(i%2==1){ printf("%d:%Le\n", i, result); } //note that im using %Le for long double type
}
also be careful with int type you are using for result, int is limited you should use long double because fact operation's result will be big
Firstly, it's probably best not to use scanf for ill defined data such as user input. In fact, the rule "don't use scanf" very often valid. A program such as this might be better off using a command line argument instead.
Technically in C main should be int main(void) or some variation of int main(int argc, char *argv[].
As others have mentioned, it would be more reasonable to use unsigned integers for a calculation like this where negative numbers are impossible. For something like a factorial it would make sense to use a larger integer type too.
Anyway, on topic: why don't you do it more simply? The factorial function can be iterated in one loop. If you only want to print the result when i is odd, just check whether it's odd.
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
static unsigned get_input(void);
static unsigned interpret_string(const char *str);
int
main(int argc, char *argv[])
{
unsigned input;
uint64_t result = 1;
if (argc == 1) {
printf("Enter the integer number : ");
input = get_input();
putchar('\n');
} else {
input = interpret_string(argv[1]);
}
for (unsigned i = 1; i <= input; ++i) {
result *= i;
if (i & 1)
printf("%-2d = %"PRIu64"\n", (int)i, result);
}
return 0;
}
static unsigned
interpret_string(const char *str)
{
char *endp = NULL;
unsigned ret = strtoll(str, &endp, 10);
if (endp == str) {
fprintf(stderr, "Invalid input \"%s\"\n", str);
exit(1);
}
return ret;
}
static unsigned
get_input(void)
{
char buf[1024];
fgets(buf, 1024, stdin);
return interpret_string(buf);
}

For Loop Not Iterating the Right Amount of times

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int rnd = list[modo];
}
return 1;
}
This code compiles fine, I just have a question as to why the for loop isn't iterating till size < i Where i is the same size as the integer argument that gets passed int.
It's supposed to keep printing %d until it reaches size i but it only prints one random number.
I'm trying to get it to print the amount of random numbers that are passed as an argument.
So if you enter ./main 3 to run the program for example it prints: 0 4 5 or ./main 4 it prints: 2 1 5 6
There is a return 0 inside the for statement block, this exits the main function and ends the program, remove this line. (And change the last line return 1 to return 0.)
isrnick answer is spot on. Anyway, the program has many other problems.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main( int argc, int *argv[] ) { // <--- Must be int main(int argc, char *argv[])
srand(time(NULL)); // <--- Warning, you need a cast here.
int list[10] = {0,1,2,3,4,5,6,7,8,9}; // <--- Why?
int modo = rand() %11; // <--- Must be %10 if desired max is 9
int rnd = list[modo]; // <--- This will be a single value for the program
int arr[argc]; // <--- VLAs? Why?
int i = argv[1]; // <--- Warning, C string to int... you need a conversion function
int size = 0;
for (size = 0; size < i; size++){ // <--- Do yourself a favor, use i as the looping variable
srand(time(NULL)); // <--- One srand per program
printf("%d \n", rnd); // <--- always print the same number
return 0; // <--- Terminate program here? No, no.
}
return 1; // <--- If no error, return 0.
}
Minimal fixed version (no checks):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
srand((unsigned int)time(NULL));
int n = atoi(argv[1]);
for (int i = 0; i < n; i++) {
int rnd = rand() % 10;
printf("%d ", rnd);
}
return EXIT_SUCCESS;
}
More controls:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
if (argc != 2) {
return EXIT_FAILURE;
}
srand((unsigned int)time(NULL));
int n;
if (sscanf(argv[1], "%i", &n) != 1) {
return EXIT_FAILURE;
}
if (n < 0) {
return EXIT_FAILURE;
}
for (int i = 0; i < n; i++) {
int rnd = rand() % 10;
printf("%d ", rnd);
}
return EXIT_SUCCESS;
}

Check command line input in C

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int allDigits(char *S) {
while ( *S ) {
if ( ! isdigit(*S)) return 0;
S++;
}
return 1;
}
int main (int argc, char *argv[]) {
int i, /*for loop index*/
sum=0; /*the sum of the arguments*/
for (i=1; i<argc; i++) {
if ( allDigits(argv[i]))
sum = sum + atoi(argv[i]);
else {
fprintf(stderr,"Usage: %s [<int> <int> ... <int>]\n",argv[0]);
exit(1);
}
}
printf("Sum of the %d integers is %d\n", argc-1, sum);
exit(0);
}
I got this example from my notes, which check the command line input to see whether is a number or not. However, there is one part I don't really understand how that works, in the function allDigits we used isdigit() to check the input. But why we put ! in front of isdigit?
Can anyone explain this part to me?

How do I find the average of double numbers entered at the command line?

I have to find the average of double numbers that the user inputs at the command line, so my program should work with any amount of inputs. I understand that I have to find the sum of all of the numbers and then divide by the number of inputs.
I was thinking, to find the number of inputs, I would use sscanf to read "char *num" in my argument list. Because sscanf returns the characters read. And then I was thinking of using that to divide the sum by to get the average. But I'm having trouble with my code. :(
#include <stdio.h>
void average(int arg_list, char *num[])
{
int x;
double sum, average;
x = sscanf(num, "%s\n", &x);
for (int i = 0; i != '\0'; i++)
{
sum = sum + num[i];
}
average = sum/x;
printf("%lf\n", average);;
}
int main(int argc, char *argv[])
{
if (argc == 0)
{
perror("Error!\n");
}
average(argc, argv);
}
Specifically, when I try to compile my program, the compiler complains about the "sscanf" and the sum. :/
"%s" reads a string. you want to read a double out of the string, so you should use "%lf". inside the loop:
double sum = 0; //you forgot to initialize
//start from i=1, not 0; the first argument is the program's name
for (int i = 1; i < arg_list; i++) {
double x;
//from the i'th argument, read a double, into x :
sscanf(num[i], "%lf", &x);
sum += x;
}
average = sum/(arg_list-1);
you should also fix your check:
if (argc <= 1) {
perror("Error!\n");
}
#include <stdio.h>
#include <stdlib.h>
void average(int arg_list, char *num[])
{
double sum = 0, average;//sum : 0 initialize
int i;
for (i = 1; i < arg_list; i++){
sum = sum + atof(num[i]);
}
average = sum/(--i);
printf("%lf\n", average);;
}
int main(int argc, char *argv[])
{
if (argc < 2)//include program name argv[0], argc == 1 even when only ./a.out
{
perror("Error!\n");
return -1;
}
average(argc, argv);
return 0;
}

Resources