18

I would like a user to pass either two parameters or leave it blank. For instance:

./program 50 50

or

./program

When I tried to use int main(int argc, char *argv[]), first thing I have done was to change char *argv[] to int *argv[] but it did not work. What I want is from the user is just to enter two integers between 0 and 100. So if it is not two integers then it should give an error.

I was sort of thinking to give out an error with types (as I used to program on C#) but whatever I enter, argv[1] would be 'char' type all the time.

So what I have done is

for (int i = 0; i <= 100; i++) {
    //printf("%d", i);
    if (argv[1] == i) {
        argcheck++;
        printf("1st one %d\n", i);
    }
    else if (argv[2] == i) {
        argcheck++;
        printf("2nd one %d\n", i);
    }

This does not work as well. Also it gives warning when compiling, but if I change argv with atoi(argv[1]) for instance, then it gives a Segmentation fault (core dumped) error.

I need a simple way to solve this problem.

EDIT:

So I fixed with atoi(), the reason why it was giving segmentation fault was because I was trying it with null value when I have no parameter. So I fixed it up by adding an extra cond. But now the problem is if the value is let's say

./program asd asd

Then the output of atoi(argv[1]) would be 0. Is there a way to change this value?

2
  • Please post your edit as a separate question. Your original question has been answered. Commented Aug 23, 2012 at 12:39
  • Before calling atoi, check that the string you are passing is an integer. Use a loop and isdigit() from ctype.h. Commented Aug 23, 2012 at 12:59

8 Answers 8

34

Don't use atoi() and don't use strtol(). atoi() has no error checking (as you found out!) and strtol() has to be error-checked using the global errno variable, which means you have to set errno to 0, then call strtol(), then check errno again for errors. A better way is to use sscanf(), which also lets you parse any primitive type from a string, not just an integer, and it lets you read fancy formats (like hex).

For example, to parse integer "1435" from a string:

if (sscanf (argv[1], "%i", &intvar) != 1) {
    fprintf(stderr, "error - not an integer");
}

To parse a single character 'Z' from a string

if (sscanf (argv[1], "%c", &charvar)!=1) {
    fprintf(stderr, "error - not a char");
}

To parse a float "3.1459" from a string

if (sscanf (argv[1], "%f", &floatvar)!=1) {
    fprintf(stderr, "error - not a float");
}

To parse a large unsigned hexadecimal integer "0x332561" from a string

if (sscanf (argv[1], "%xu", &uintvar)!=1) {
    fprintf(stderr, "error - not a hex integer");
}

If you need more error-handling than that, use a regex library.

Sign up to request clarification or add additional context in comments.

9 Comments

You can use strtol()'s second argument (the end-pointer) to error-check without involving errno.
You can indeed use the second argument to strtol() to check for all errors that are not valid 0l, overflow or underflow, meaning you still have to check errno for over/underflow.
Erm? sscanf is just as bad itt can't detect overflow. If the scanned integer value can't git, it's undefined behaviour. While you can specify widths in the format string, you still need to know the range of the integers, it doesn't get any easier than strtol (you need to know the platform's INT_MAX format example and decide to specify a closest approximation as the width in the format string accordingly). So strto[u]* functions are actually the better option, more so for user-supplied inputs.
1. There is no overflow in sscanf()ing an integer. 2. If the input cannot be scanned there is no undefined behaviour because you can check the return from scanf in the same line that it is invoked. 3. You don't need to use INT_MAX. 4. the strto() group of functions need two separate statements to check for errors, hence most uses of it don't check for errors.
@Lelanthran If input is too large, sscanf'ing will overflow. The return value check isn't useful because, if input can't be represented, overflow already happened. See: onlinegdb.com/SJ5VOuOIN
|
14

This will do:

int main(int argc, char*argv[])
{
   long a,b;
   if (argc > 2) 
   {
      a = strtol(argv[1], NULL, 0);
      b = strtol(argv[2], NULL, 0);
      printf("%ld %ld", a,b);
   }
   return 0;
}

Comments

4

The arguments are always passed as strings, you can't change the prototype of main(). The operating system and surrounding machinery always pass strings, and are not able to figure out that you've changed it.

You need to use e.g. strtol() to convert the strings to integers.

Comments

2

You want to check whether

  1. 0 or 2 argument is received
  2. two values received are between 0 and 100
  3. received argument is not a string. If string comes sscanf will return 0.

Below logic will helps you

int main(int argc, char *argv[])
{
    int no1 = 0, no2 = 0, ret = 0;

    if ((argc != 0) && (argc != 2)) 
    {
        return 0;
    }

    if (2 == argc)
    {
        ret = sscanf(argv[1], "%d", &no1);
        if (ret != 1)return 0;
        ret = sscanf(argv[2], "%d", &no2);
        if (ret != 1)return 0;          

        if ((no1 < 0) || (no1 >100)) return 0;
        if ((no2 < 0) || (no2 >100)) return 0;          
    }

    //now do your stuff
}

Comments

0

The things you have done so innocently are blunder in C. No matter what, you have to take strings or chars as your arguments and then later you can do whatever you like with them. Either change them to integer using strtol or let them be the strings and check each char of the string in the range of 48 to 57 as these are the decimal values of char 0 to 9. Personally, this is not a good idea and not so good coding practice. Better convert them and check for the integer range you want.

Comments

0

You can still use atoi, just check whether the argument is a number first ;)
btw ppl will tell you goto is evil, but they're usually brainwashed by non-sensible "goto is bad", "goto is evil", "goto is the devil" statements that were just tossed out without elaboration on the internet.
Yes, spaggethi code is less managable. And goto in that context is from an age where it replaced functions...

    int r, n, I;
    for (I = 0; I < argc; ++I)
    {
      n = 0;
      do
        if ( !((argv + I) [n] >= '0' && (argv + I) [n] <= '9') )
        {
          err:
            fprintf(stderr,"ONLY INTEGERS 0-100 ALLOWED AS ARGUMENTS!\n");
            return 1;
        }
      while ((argv + I) [++n] != '\0')
      r = atoi(argv[I]);
      if (r > 100)
        goto err;
    }

Comments

-1

You can not change the arguments of main() function. So you should just use atoi() function to convert arguments from string to integer.

atoi() has its drawbacks. Same is true for strtol() or strtoul() functions. These functions will return a 0 value if the input to the function is non-numeric i.e user enters asdf or anything other than a valid number. To overcome this you will need to parse the string before passing it to atoi() and call isdigit() on each character to make sure that the user has input a valid number. After that you can use atoi() to convert to integer.

2 Comments

atoi() function causes Segmentation fault (core dumped) error.
@SarpKaya I have added more about atoi() to my answer. Plz take a look.
-1
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
main(int argc,char *args[])
{
    int i,sum=0;
    for(i=0;i<=argc;i++)
    {
        printf("\n The %d argument is: %s",i,args[i]);
    }
    printf("\nTHe sum of given argumnets are:");
    for(i=1;i<argc;i++)
    {
       int n;
       n=atoi(args[i]);
       printf("\nN=%d",n);
       sum += n;
    }
    printf("\nThe sum of given numbers are %d",sum);
    return(0);

  }

check this program i added another library stdlib.h and so i can convert the character array to string using function atoi.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.