-1

I have a problem with pointers in c programming. I would love to get variables from the command line in Linux and than be assigning the value of the variables from command line to a non pointer variable and printing them out!

char *argv[]

this is the function that takes everything written after the name of the c program on the command line and stores it in the pointer *argv[]; Now i would love to store these pointer values in a normal variable and print it on the command line. I get segmentation fault when i execute my code.

int main ( int argc, char *argv[] )
{

    char r1;
    char a = *argv[1];
    char b = *argv[2];
    char c = *argv[3];

    if ( b == '+') {

    r1 = a + c;
    printf("%s", r1);
    }
}
4
  • 1
    Step 1 is to check the value of argc which must be the number of command line arguments you are providing + 1. Commented Oct 29, 2019 at 16:49
  • 4
    @yhyrcanus in his defense, i think he started from 1 to skip the program's name that is stored in argv[0] Commented Oct 29, 2019 at 16:53
  • 2
    printf("%s", r1); shoudl have generated a compiler warning (-Wformat) telling you that you are passing a char to a function that expects a char*. Commented Oct 29, 2019 at 16:54
  • @josef_october, how are you executing your program on the command line? Commented Oct 29, 2019 at 17:00

3 Answers 3

3

printf("%s", r1);

This is where your segfault is coming from.

The %s conversion specifier expects its corresponding argument to have type char * and to be the address of the first element of a zero-terminated array of char. r1 is the result of adding the values in a and c, which is not going to be a valid address.

C is not Python or Javascript - values are not magically converted between numbers and strings based on context. If you want to work with numeric values from the command line, you must first manually convert the string representations of those values to their corresponding types.

For example, if your command line is ./foo 1, then argv[1] contains the string "1" (represented as the sequence {'1', 0}). The value of *argv[1] is not 1, it's the encoding value of the character '1', which, assuming ASCII, is 49. You need to use a library function like atoi() or strtol() to convert the string "1" to the integer value 1.

Assuming your input is something like

./foo 1 + 2

and you want it to print 3, then you need to do something like the following:

#include <stdlib.h>
#include <stdio.h>

int main( int argc, char **argv )
{
  if ( argc < 4 )
  {
    fprintf( stderr, "USAGE: %s <val> <op> <val>\n", argv[0] );
    return EXIT_FAILURE;
  }

  /**
   * strtol() allows you to detect and reject non-numeric input,
   * but I'm omitting that here for brevity.
   */
  int lhs = (int) strtol( argv[1], NULL, 0 ); 
  int rhs = (int) strtol( argv[3], NULL, 0 );

  if ( *argv[2] == '+' )
  {
    int r1 = lhs + rhs;
    printf( "%d\n", r1 );
  }

  return EXIT_SUCCESS;
}

Things to remember:

In C, a string is a sequence of character values including a zero-valued terminator - the string "Hello" is represented as the sequence {'H', 'e', 'l', 'l', 'o', 0 }. That trailing 0 is necessary for the sequence to be a string.

Strings are stored in arrays of character type (char for encodings like ASCII, EBCDIC, and UTF-8, wchar_t for "wide" encodings like UTF-16).

Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

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

Comments

0

There are lots of errors in this code. A solution, not elegant but working, is the following:

int main(int argc, char *argv[])
{
    char r1;
    char *a = argv[1];
    char b = argv[2][0];
    char *c = argv[3];

    if ( b == '+') {
        r1 = atoi(a) + atoi(c);
        printf("%d", r1);
    }
}

This code will work as you expect, but are more elegant ways to do that.

5 Comments

Maybe also add a test if (argc >= 4) ?
There is no tests in this code. It is not a safe implementation to a real world application @JohanC
atoi(a) will produce a compiler warning about converting an integer to a pointer without a cast, just like OP's code. If you ignore the warning, a segfault is likely, also just like OP's code.
@rici what conversion are talking about? There is no conversion from int to pointer. The atoi is converting from char* to int, and the int to a char, what is perfectly ok. Again, there is no testing in this piece of code, is just a correction above the original code.
You have char a = *argv[1];. a is not a pointer, it's a char. You want const char* = argv[1];; the const is not strictly necessary but it is recommended.
-1

Finally I got it! This is my code now!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( int argc, char *argv[] )
{
    if(argc < 4) {
        printf("Benötige mindestens 4 Argumente!\n");
        printf("Aufruf: %s <zahl><op><zahl> ...\n", argv[0]);
        return EXIT_FAILURE;
    }

    int  r1;
    int a = strtol (argv[1], NULL, 0);
    int c = strtol (argv[3], NULL, 0);

    if(strcmp(argv[2],"+") == 0) {
        r1 = a + c;
        printf("%d \n", r1);
    }

    return EXIT_SUCCESS; 

}

1 Comment

I'd advise accepting @JohnBode's answer by clicking the check mark next to it. That's the best way to say "thank you". You don't need to post your fixed code if the accepted answer explains everything already.

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.