Easy: Passing data to c program from terminal (Mac) - c

So, this is a really basic question. For an assignment we had to write a c program that would calculate the page and offset number of a virtual address. My program seems to work fine when I make a vocal variable of the virtual address that we are supposed to do calculations on, but I can't figure out how to pass it.
The assignment says that we should run our program like this
./program_name 19982
I just can't figure out how to pass that 19982 in terminal on my mac. Any help is appreciated. (And in before someone makes a mac joke.)

It sounds like you are looking for argv, which I suppose is difficult to search for if you don't know what it is called! This isn't specific to Mac OS X's Terminal.
The argv argument of a main() function is an array of strings; its elements are the individual command line argument strings.
The path to the program being run is the first element of argv, that is argv[0].
The number of elements in argv is stored in argc:
#include <stdio.h>
int main(int argc, char* argv[])
{
int arg;
for (arg = 0; arg < argc; ++arg)
{
printf("Arg %d is %s\n", arg, argv[arg]);
}
return 0;
}
Compile:
% gcc program_name.c -o program_name
Run:
% ./program_name 19982
Arg 0 is ./program_name
Arg 1 is 19982
Converting argv[1] to an int is left as an exercise.

You can use argc and argv to access program's arguments. argc is the "arguments count" - the number of arguments passed. argv is the "arguments vector", where the first member is the name of the program.
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char* argv[] )
{
int Address;
if (argc > 1)
{
Address = atoi(argv[1]);
}
else
{
printf("No arguments passed\n");
return 1;
}
return 0;
}

Typically, you'd use "argv/argc" in main. For example:
#include<stdio.h>
int
main (int argc, char *argv[])
{
if (argc < 2)
printf ("You didn't enter any arguments\n");
else
printf ("Your first argument is %s\n", argv[1]);
return 0;
}
Under Linux, you'd compile and run like this:
gcc -o hello hello.c
./hello howdy!
Again under Linux, it would output something like this:
Your first argument is howdy!

All C (and C++, don't know about objective-c) programs start their execution in the function main. This function takes two arguments: An integer, usually named argc which is a counter of the number of arguments given to the program; The second function argument is an array of char pointers, usually called argv and is the actual command line arguments.
The first entry in argv is always the name of the command itself, which means that argc will always be at least 1.
The following program prints all arguments given on the command line:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Total number of values in argv: %d\n", argc);
for (int a = 0; a < argc; a++)
printf("argv[%02d]: %s\n", a, argv[a]);
}

Related

Can't accept multiple command line arguments and assign to variable

I am learning C and I am not used to pointers and the way C handles strings. I am trying to create a program that accepts multiple command line arguments and assigns them to variables so that I can later use them. I can get the program to accept the first argument and assign it as a int. But when I try to accept the second argument I get a SEGMENTATION FAULT. I have tried testing by removing the second variable (service) and then assigning port to argv[2] and it doesn't work. It is something about accepting the second argument that the compiler does not like but I am not able to figure it out.
#include <stdio.h>
int main(int argc, char *argv[]) {
int port = atoi(argv[1]);
char service = argv[2];
return 0;
}
When you write char service = argv[2];, you are assigning a char pointer to a char. You know argv is a char pointer array, because you define it as char *argv[]. Fix by just adding char *service = argv[2];
So your rewritten code could look like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Requires more arguments");
return 1;
}
int port = atoi(argv[1]);
char *service = argv[2];
printf("%s", service); //From edit
return 0;
}
You may want to add a check for the value of argc (i.e. argc >= 3), since it will seg fault if there aren't three arguments.
Edit (response to comment):
To print the service, use:
printf("%s", service);
The %s specifies you will print a string of characters (char *) and you simply use service, because you need to specify the pointer.
Edit 2:
If you don't add #include <stdlib.h>, you will receive something along the lines of "warning: implicit declaration of 'atoi' is invalid in C99", which may also produce an error depending on your compiler settings.

Finding number of arguments in argv?

So something simple like this:
int main(int argc, char* argv[]) {
int size = sizeof(argv);
printf("%d", size);
}
If I pass it 5 arguments, it tells me there's 4 arguments. If I pass it 10 arguments, it tells me there's 4 arguments. Is something wrong here or is my compiler messed up?
int size = sizeof(argv);
This does not give you the number of arguments in the argv array, it gives you the size of the argv variable in bytes. This is commonly four or eight for pointers at the time I'm answering this question and it's obviously four in your particular case.
If you want to know how many items are in argv, that's exactly what argc is for.
The argc integer holds the number of arguments, including the first one which usually represents the program being run. So, you can get the arguments with a loop like:
#include <stdio.h>
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; ++i) {
printf("Argument #%d is %s\n", i, argv[i]);
}
return 0;
}
Running that with certain arguments show it in action:
pax$ ./testprog abc def 123 789
Argument #0 is ./testprog
Argument #1 is abc
Argument #2 is def
Argument #3 is 123
Argument #4 is 789
Another way, since it's mandated that argv[argc] must be the NULL pointer, is to bypass the count and check the values directly:
#include <stdio.h>
int main(int argc, char *argv[]) {
for (char **arg = argv; *arg != NULL; ++arg) {
printf("Argument is %s\n", *arg);
}
return 0;
}
That has slightly different output because I'm not using a counter but the arguments are exactly the same:
pax$ ./testprog pax diablo
Argument is ./testprog
Argument is pax
Argument is diablo
Please refer to the documentation from gcc here
Quote:
The value of the argc argument is the number of command line
arguments. The argv argument is a vector of C strings; its elements
are the individual command line argument strings. The file name of the
program being run is also included in the vector as the first element;
the value of argc counts this element. A null pointer always follows
the last element: argv[argc] is this null pointer.
For the command ‘cat foo bar’, argc is 3 and argv has three elements,
"cat", "foo" and "bar".
argc is essentially there to know total count of commandline arguments passed in the command line. Even the executable name is listed in the command arguments (If you are wondering why - Look here (Advanced)).
So As a short answer, argc - 1 will give you total number of arguments. It is a very common programming practice to check argc to confirm whether the minimum required number of arguments are passed or not.

C produce error if no argument is given in command line

In C, how can I produce an error if no arguments are given on the command line? I'm not using int main(int argc , * char[] argv). my main has no input so I'm getting my variable using scanf("%d", input)
Your question is inconsistent: if you want to get arguments from the command line, you must define main with argc and argv.
Your prototype for main is incorrect, it should be:
int main(int argc, char *argv[])
If the program is run without any command line arguments, arc will have the value 1. You can test it this way:
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("error: missing command line arguments\n");
return 1;
}
...
}
If you define main with int main(void) you have no portable access to command line arguments. Reading standard input has nothing to do with command line arguments.
Given the code:
#include <stdio.h>
int main() {
int input;
int rc = scanf("%d", &input);
}
We can verify that scanf() was able to successfully get some input from the user by checking its return value. Only when rc == 1 has the user properly given us valid input.
If you'd like to know more, I recommend reading scanf's documentation.
well, the definition of your main arguments are as follow:
argc is the number of arguments
argv are the argument strings
This means you only need to check if argc is equal to one (the program name only) and output an error ;-)
If you use int main() only, you have no way to know.

Command line arguments in main

I've written a code that sums up integers brought in from the command line:
#include <stdio.h>
int main(int argc, int* argv[]) {
int i, s=0;
for (i=1;i<argc;i++)
s=s + *argv[i];
printf("Sum: %d\n", s);
return 0;
}
The best part is, it passes the gcc compiling process, but when I actually run it and insert the numbers, the result seems I somehow breached the range of int.
It seems that you are compiling your code in C89 mode in which s is taken as int by default by compiler. s is uninitialized therefore nothing good could be expected. If fact it will invoke undefined behavior.
Note that argv[i] is of char * type (change your main signature) and you need to convert it to int before adding it to s.
The 2nd argument of main should be either of type char** or of type char*[] and not int*[]. So, *argv[i] is of type char. Instead of getting each character, you can get each string(argv[i] which is of type char*) and then extract the number from it and assign it to a variable, say num. This can be done by using the sscanf function:
#include <stdio.h>
int main(int argc, char* argv[]) { //int changed to char here
int i, s=0,num;
for (i=1;i<argc;i++)
if(sscanf(argv[i],"%d",&num)) //if extraction was successful
s=s + num;
printf("Sum: %d\n", s);
return 0;
}
Assuming you have s initialized properly as shown below.
Along with this the prototype of your main() should be as shown below inorder to get the command line arguments.
int main(int argc, char **argv)
{
int s =0;
// Check for argc matches the required number of arguments */
for(i=1;i<argc;i++)
s=s + atoi(argv[i]); /* Use atoi() to convert your string to integer strtol() can also be used */
printf("%d\n",s);
return 0;
}
PS: Using uninitialized variables lead to undefined behvaior

Implementing a command-line argument

I have to implement the main function with the following signature:
int main(int argc, char *argv[])
What is a command-line argument and why don't I need test cases for it? And what do they mean by "signature"? Is it just the function prototype?
And I will definitely edit this question to include my attempt at the solution once I get these things clarified.
I'm confused on what this program essentially does, I can see it returns an integer value, but what does that integer value represent? Also, how would I return an integer value with the arguments specified in the argument list? What do they mean? Thanks for the help!
While this is a terrible question that shows little effort, I feel obligated to help ease your confusion.
Here's a program which prints out it's name (argv[0]), and requires at least one argument. If it isn't given at least one argument, it returns 1 to indicate failure. Otherwise, it prints out its arguments and returns 0 to indicate success (to the shell, or whoever started it).
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("Hello World, my name is \"%s\" \n", argv[0]);
if (argc < 2) {
printf("I require at least 1 argument! Exiting!\n");
return 1; // Indicate failure.
}
printf("I was given %d command-line arguments:\n", argc-1);
for (i=1; i<argc; i++) {
printf(" [%d] %s\n", i, argv[i]);
}
return 0; // Indicate success
}
Compile and run that program, things should become more clear.

Resources