Why we use argc as argument in getopt() function? - c

I have recently started learning C language so I don't much about the functions of C.
Recently I saw a program written in C on Internet article. It was like this:-
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i = 0;
int j = 0;
char ch;
ch = getopt(argc, argv, "n:");
if(ch == 'n')
{
j = atoi(optarg);
}
while(j--)
{
printf("%i\n",j);
}
return 0;
}
Can anyone tell what is the actual purpose of argc in getopt() function? Does it uses argc as for upto where it should read options?

In my observation argc is there to write simple code and the argv NULL to write defensive code.
argv and argc has been in main's signature since the very beginning of C, so has the NULL at the end of the argv list. I've looked at many C programs since then and almost none of them depend on that NULL. Rather they depend on argc to control the array depth as it is simpler and more reliable. However, the defensive programmer will also look for that NULL as well as using argc and getopt() should use argc to complain if it's called too many times.
Also, I've seen code that plays games to reuse getopt() to parse secondary "command lines" for commands given to the application. Not all of those put a NULL on the end of the list (mine did, though).

The C standard does guarantee that argv[argc] is a NULL pointer:
C Standard, §5.1.2.2.1.2:
If they are declared, the parameters to the main function shall obey the
following constraints:
...
— argv[argc] shall be a null pointer.
Technically, all you (and the function getopt) really need is argv - something like this will process all arguments:
int i;
for(i = 0; argv[i]; i++)
{
puts(argv[i]);
}
However, there is nothing stopping you (or the author of getopt) from using argc as a loop guard instead. This is equally valid:
int i;
for(i = 0; i < argc; i++)
{
puts(argv[i]);
}
So, if the function says it requires argc to be passed, then pass argc to it, because it probably uses it to form that type of loop.

Related

finding the size of an string array that saves integers C

I am currently working on a project where I am manipulating command line data, but I can't seem to get it work if I initialize the size of the array before.
char* len2[50]; // will store "1","2","3" from command line args
int size_arr = sizeof(len2) / sizeof(len2[0]);
printf("%d", size_arr);
this will input 50 when I am looking for it to input 3. How would I be able to find the size?
int size_arr = sizeof(len2) / sizeof(len2[0]);
sizeof(len2) asks for the total allocated size of len2 in bytes. This only works because C knows how many you allocated at compile time and turns it into a constant. It doesn't tell you which ones you've filled in. C does not keep track of that; you have to.
Because len2 is an array of pointers, you can mark the end with a null pointer. The term for this is a sentinel value. First, be sure to initialize the array to null.
// This will initialize the entire array to NULL
char* len2[50] = {NULL};
Now you can find how many elements are in the array by looking for the first null, or by hitting the allocated size.
size_t len2_size = sizeof(len2) / sizeof(len2[0]);
int size = 0;
for( ; len2[size] != NULL && size < len2_size; size++ );
printf("size: %d\n", size);
This is, incidentally, basically how C strings work. The end of the string is marked with a 0.
Alternatively, you can store the allocated size and number of elements in a struct and keep track, but that's another question.
Finally, if you're just reading command line arguments, use argc and argv. argc is the size of argv. argv[0] is the name of the program, and the rest are the command line arguments.
int main( const int argc, const char **argv) {
printf("%d arguments in argv\n", argc-1);
}
And argv is also terminated with a NULL pointer so it's easy to iterate through.
// Because argv[0] is the name of the program,
// start at 1 and read until you hit a null pointer.
for( int i = 1; argv[i] != NULL; i++ ) {
printf("argv[%d] = %s\n", i, argv[i]);
}
From the comments:
I guess what I'm trying to find is the number of items. Since there are 3 numbers I'll be getting from the command line, I want to be able to manipulate the array using 3 for a for or while loop for example.
According to the standard you have two versions of main function available (while the implementation defining further ones is legal):
int main();
int main(int, char**);
The second form gets the command line parameters passed to directly while the first form can be used if command line parameters are irrelevant.
Typically (but not necessarily) these two arguments get named argc and argv with argc containing the total number of command line arguments and argv a null-terminated array to the actual arguments. First one of is always the name that has been used to call the programme (which can differ in some cases from the actual executable name, e.g. if symbolic links are involved) which you might want to skip.
So a programme simply iterating over all arguments and printing them back to console might look like this:
int main(int argc, char* argv[])
{
for(++argv; *argv; ++argv)
{
printf("%s\n", *argv);
}
return 0;
}
with first ++argv skipping the programme name, *argv profiting from and testing for the null-terminator of the array and second ++argv being the normal loop post operation.
If you want to see the programme name as well you might just skip very first pointer increment:
for(;*argv;++argv)
Alternative variants might use an integer to count up to argc – just a matter of personal taste...

How to add "int argc and char *argv[]" to my main function and impliment into my code?

I am working on creating an uppercase function. I want to implement argc and argv arguments in to my code but I don't know how to do it.
Here is my code;
Main.c:
#include <stdio.h>
#include <stdlib.h>
#include "upperc.h"
int main(int argc, char *argv[])
{
char s[] = "HellO2 world3!";
printf("%s \n", s);
printf("%s \n", uppercase(s));
return 0;
}
upper.c:
/*
Parsing the string, then making the letters to uppercase.
*/
#include <stdio.h>
#include "upperc.h"
char * uppercase(char *s) {
for(char *p = s; *p; ++p) {
if ('a' <= *p && *p <= 'z')
*p = *p & ~' ';
}
return s;
}
upper.h:
#ifndef UPPERC_H_INCLUDED
#define UPPERC_H_INCLUDED
char * uppercase(char *s);
#endif // UPPERC_H_INCLUDED
As this looks like some kind of homework, I don't give a full answer.
argc is the number of arguments including the program name that was executed. That means argc is 1 if no arguments were specified, 2 if one argument was specified etc.
Don't pass argv[1] unconditionally to your uppercase function. This would be undefined behavior if argc is 1 or even 0. (see below for details)
Depending on your requirements, you should check argc and process either only argv[1] if available, which would be the first argument, or process argv[1], argv[2] ... in a loop as necessary.
Additional details (for experts, because my original wording was not exact):
If your program is called in a normal way, the value of argc should be at least 1 and argv[0] will be the program name. The value of argv[argc] is a NULL pointer. Of course you can access the pointer value in this case, but you cannot dereference it, i.e. you cannot access a value where the pointer would be pointing to.
It is possible to call your program in a way that results in an argc value 0. In this case argv[0] will be a NULL pointer, and the array element argv[1] (and all following it) will be undefined.
See https://en.cppreference.com/w/c/language/main_function

What arguments does a c application like snmpget take?

I want to call snmpget.c from another c program in the same project. For that reason I have changed the main() into a function say get_func() which takes the same arguments. But i an not sure how to give the arguments namely argv[0]
My arguments look something like this:
char *argstr[]=
{
"v",
"1",
"c",
"public",
"-Ovq",
"192.168.1.1",
"ifInOctets.7",
"ifOutOctets.7",
NULL
};
And then
i = get_func(10, argstr);
1.Should argv[0] be the app name or path?
2.Is using char *argstr[] correct for c?
3.snmpget is not taking these arguments correctly. What could the reason be?
It works correctly with the same args in command.
Your get_func expects the arguments starting at argv[1], so your argstr argument should not start with "v" but with something else (e.g. the programme name or just an empty string if get_func doesn’t use it).
Yes. But be aware that your argstr contains non-modifiable strings, if get_func wants to modify them, you can use compound literals
char *argstr[]=
{
(char []){ "v" },
(char []){ "1" },
/* etc */
NULL
};
See 1. and 2. Additionally, argc is incorrect (must be sizeof argstr/sizeof *argstr - 1, which is 8 in your case, not 10).
Not directly an answer to your question, but consider redesigning this (depends on what exactly you’re currently doing, however). For example, write a function accepting a structure where the different options are stored (already parsed and validated) and change the old main from snmpget.c to a function only scanning and validating arguments, initializing such a structure object, and calling this function. And then, perhaps split your files into snmpget.c, snmpget_main.c, another_c_file.c (with better names, of course) and link both user interface implementations against the object file of snmpget.c.
Yes, if your main uses it. If not, just pass NULL is enough >o<
Sure, it's array of pointers. char *argstr[9] is equal to
typedef char *pchar;
pchar argstr[9];
Well, I assume you don't give appropriate argc and don't pass the app name by argv[0] because the argc is 10, but the number of content of argv is 8. (I've counted excluding NULL, but the NULL is required yet - argv[argc] should be NULL.)
To reduce mistakes, I suggest to use sizeof(argstr) / sizeof(argstr[0]) - 1 instead of calculating argc yourself.
See live example. Code:
#include <stdio.h>
int test(int argc, char *argv[]);
int main()
{
char *argstr[] = {
"test.exe",
"--opt-1",
"--output",
"test.txt",
NULL
};
int argcount = sizeof(argstr) / sizeof(argstr[0]) - 1;
return test(argcount, argstr);
}
int test(int argc, char *argv[])
{
int i;
printf("argc: %d\n", argc);
printf("program name: %s\n", argv[0]);
for (i = 1; argv[i] != NULL; i++)
{
printf("argument %d is: %s\n", i, argv[i]);
}
return 0;
}
Output:
argc: 4
program name: test.exe
argument 1 is: --opt-1
argument 2 is: --output
argument 3 is: test.txt

String compare function properly

I am writing a program that has to use the strcmp function using a pointer in the main. There cannot be any user input. There is no menu, it must execute the arguments as parameters in the main function. my question is am I calling the strcmp function proper?
int main(int n, char **p, char **choice)
{
int i, x, A[100];
if (strcmp(*choice, "mode")==0){
Your code will compile and is grammatically correct, but I'm not certain that the logic is what you want it to be.
Typically main has 2 or 3 arguments, usually written as int argc, char **argv, char ** envp (if there are only 2, it's the first 2). It's ok to rename them as you did, to n, p, and choice, but you need to know what each of them mean.
argc ("n") is the number of strings in the argv array, 0 indexed. There will always be at least 1 argument - the name of the program. Arguments passed on the command line start at argv[1].
argv is all of the arguments, including the program name. The array will go from 0 to argc - 1
envp is an array of strings listing all of the environment settings. It is terminated with a NULL entry as its final one.
If you're tasked with executing the arguments as parameters, you're likely to be interested in looping through the strings in argv. You'll want something like this:
int i = 1;
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "mode") == 0) {
Of course, if you want to keep your variable names, just replace them:
int i = 1;
for (i = 1; i < n; ++i) {
if (strcmp(p[i], "mode") == 0) {
So, yes. Your use of strcmp was syntactically acceptable. But it likely doesn't do what you want.
Good luck!
Incidentally, if you ever need to loop through envp, you'd do so as follows:
int i = 0;
while (envp[i] != NULL) {
if (strcmp(envp[i], "mode") == 0) { // or whatever else you needed to do.

Input from the execution line in the terminal in c

The problem that i have is that i have to write a hanois tower game in c and the input for the number of the rings must not be in the programm but the code must read the number of rings in the execution.
Example: ./hanoistower 3
And the code should get the 3 as the input. How can i do that?
Command line arguments are propagated as strings through the main() function of your C program.
In int main(int argc, char *argv[]) argc is the number of arguments, and argv is an array of strings containing the arguments. Note that the program name itself is always the first "argument".
As the arguments are passed as strings, you likely need to convert your 3 to an integer, which can be done with the atoi function. Here's a start:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int rings;
if(argc != 2) {
printf("Usage: %s number-of-rings\n",argv[0]);
return 1;
}
rings = atoi(argv[1]);
printf("Using number-of-rings = %d\n", rings);
...
return 0;
}
I strongly suggest reading a good C programming book (in 2020, Modern C).
It will be much faster than asking questions here. Don't forget to also read the documentation of your C compiler (perhaps GCC), your build automation tool (e.g. GNU make or ninja), and debugger (perhaps GDB). If you code on and for Linux, read also Advanced Linux Programming and syscalls(2), and the documentation of GNU glibc (or of musl-libc, if you use it).
Hovever, the program arguments is given as a null terminated array of strings to the main function, which is usually declared as
int main (int argc, char**argv) { /*...*/ }
if you run your program with ./hanoistower 3 and if your hanoistower.c is your source code (which you need to compile with debugging and warning enabled, i.e. gcc -Wall -g hanoistower.c -o hanoistower on Linux) then you have one extra argument, so
argc == 2
argv[0] is the "./hanoistower" string
argv[1] is the "2" string (use atoi to convert it to an int)
argv[2] is NULL
Please, please learn to use the debugger (gdb on Linux).
Just add, argc and argv to the list of main method parameters, as shown below:
int main ( int argc, char *argv[] )
Then use argv as the variable to specify number of rings inside your code.

Resources