Borland C++ supports three main() arguments. The first two are traditional argc and argv. These are the only arguments main functions(), defined by the ANSI C standard. They allow command-line arguments to be passed to the program. The command line arguments are the information following the program name in command line operating system. For example, when a program is compiled with the Borland inline compiler, bcc is typically typed program_name

Where program_name is the program to be compiled. The program name is passed to the compiler as an argument.

The argc parameter contains the number of command line arguments and is an integer. It is always at least 1 because the program name is qualified as the first argument. The argv parameter is a pointer to an array of character pointers. Each element of this array points to a command line argument. All command line arguments are strings. All numbers are converted by the program into an internal format. The following program prints "Hello" followed by the username if typed right after the program name:

#include

{
if(argc!=2)
{
printf("You forgot to type your name\n");
return 1;
}
printf("Hello %s", argv);
return 0;
}

If called this program name, and the username is Sergey, then to run the program you should type:
name Sergei.
As a result of the program will appear:
Hello Sergei.

Command line arguments must be separated by spaces or tabs. Commas, semicolons, and similar characters are not considered separators. For example:

Consists of three lines, while

Herb,Rick,Fred

This is one line - commas are not delimiters.

If you want to pass a string containing spaces or tabs as a single argument, enclose it in double quotes. For example, this is one argument:

"this is a test"

It is important to correctly declare argv. The most typical method is:

The empty parentheses indicate that the array does not have a fixed length. You can access individual elements using argv indexing. For example, argv points to the first line, which always contains the name of the program. argv points to the next line, and so on.

Below is a small example of using command line arguments. It counts down from the value specified on the command line and emits a signal when zero is reached. Note that the first argument contains a number converted to an integer using the standard atoi() function. If the string "display" is present as the second argument, then the counter itself will be displayed on the screen.

/* counting program */

#include
#include
#include
int main(int argc, char *argv)
{
int disp, count;
if(argc<2)
{
printf("You must enter the length of the count\n");
printf("on the command line. Try again.\n");
return 1;
}
if (argc==3 && !strcmp(argv,"display")) disp = 1;
else disp = 0;
for(count=atoi(argv); count; -count)
if (disp) printf("%d", count);
printf("%c", "\a"); /* on most computers this is a call */
return 0;
}

Note that if no arguments are specified, an error message appears. This is most typical of programs that use command line arguments to issue instructions if an attempt was made to run the program without the correct information.

To access individual command line characters, add a second index to argv. For example, the following program prints all the arguments it was called with, one character at a time:

#include
int main(int argc, char *argv)
{
int t, i;
for(t=0; t {
i = 0;
while(argv[t][i])
{
printf("%c", argv[t][i]);
}
printf(");
}
return 0;
}

It must be remembered that the first index is for accessing the string, and the second is for accessing the character of the string.

Typically argc and argv are used to get source commands. Theoretically, you can have up to 32767 arguments, but most operating systems don't even allow you to get close to that. Typically, these arguments are used to specify a filename or options. Using command line arguments gives the program a professional look and allows the program to be used in batch files.

If you include the WILDARGS.OBJ file supplied with Borland C++, you can use wildcards in *.EXE type arguments. (Borland C++ handles patterns automatically and increments argc accordingly.) For example, if you connect WILDARGS.OBJ to the following program, it will print out how many files match the name of the file specified on the command line:

/* Link this program with WILDARGS.OBJ */

#include
int main(int argc, char *argv)
{
register int i;
printf("%d files match specified name\n", argc-1);
printf("They are: ");
for(i=1; i printf("%s", argv[i]);
return 0;
}

If we call this program WA, then run it as follows, we get the number of files that have the EXE extension, and a list of the names of these files:

In addition to argc and argv, Borland C++ also provides a third command line argument -env. The env parameter allows the program to access information about the operating system environment. The env parameter must follow argc and argv and is declared like this:

As you can see, env is declared in the same way as argv. Just like argv, this is a pointer to an array of strings. Each line is an environment string as defined by the operating system. The env parameter has no counterpart to the argc parameter, which tells how many environment lines there are. Instead, the last line of the environment is null. The following program prints all the environment strings currently defined in the operating system:

/* this program prints all environment lines */

#include
int main(int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]/ t++)
printf("%s\n", env[t]);
return 0;
}

Note that although argc and argv are not used by the program, they must be present in the parameter list. C does not know the parameter names. Instead, their use is determined by the order in which the parameters are declared. In fact, you can call the parameter whatever you like. Because argc, argv, and env are traditional names, it's best to keep using them so that anyone reading the program can instantly recognize that these are arguments to the main() function.

For programs, a typical task is to find the value defined in the environment string. For example, the contents of the PATH string allow programs to use search paths. The following program demonstrates how to find strings that declare standard search paths. It uses the standard library function strstr(), which has the following prototype:

Char *strstr(const char *str1, const char *str2);

The strstr() function looks for the string pointed to by str1 in the string pointed to by str2. If such a string is found, then a pointer to the first position is returned. If no match is found, the function returns NULL.

/* the program searches the environment strings for a string containing PATH */

#include
#include
int main (int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]; t++)
{
if(strstr(env[t], "PATH"))
printf("%s\n", env[t]);
}
return 0;
}

When creating a console application in the C++ programming language, a line very similar to this is automatically created:

int main(int argc, char* argv) // main() function parameters

This line is the header of the main function main() , the parameters argс and argv are declared in brackets. So, if the program is run through the command line, then it is possible to transfer any information to this program, for this there are argc and argv parameters. The argc parameter is of data type int , and contains the number of parameters passed to the main function. Moreover, argc is always at least 1, even when we do not pass any information, since the name of the function is considered the first parameter. The argv parameter is an array of pointers to strings. Only string type data can be passed through the command line. Pointers and strings are two big topics for which separate sections have been created. So, it is through the argv parameter that any information is transmitted. Let's develop a program that we will run through the Windows command line and pass some information to it.

// argc_argv.cpp: Specifies the entry point for the console application. #include "stdafx.h" #include using namespace std; int main(int argc, char* argv) ( if (argc ><< argv<

// code Code::Blocks

// Dev-C++ code

// argc_argv.cpp: Specifies the entry point for the console application. #include using namespace std; int main(int argc, char* argv) ( if (argc > 1)// if we pass arguments, then argc will be greater than 1 (depending on the number of arguments) ( cout<< argv<

After debugging the program, open the Windows command line and drag the executable of our program into the command line window, the full path to the program will be displayed on the command line (but you can write the path to the program manually), after that you can press ENTER and the program will start (see Figure 1).

Figure 1 - Parameters of the main function

Since we just ran the program and did not pass any arguments to it, the message Not arguments appeared. Figure 2 shows the launch of the same program through the command line, but with the Open argument passed to it.

Figure 2 - Parameters of the main function

The argument is the word Open , as you can see from the figure, this word appeared on the screen. You can pass several parameters at once, separating them with a comma. If it is necessary to pass a parameter consisting of several words, then they must be enclosed in double quotes, and then these words will be considered as one parameter. For example, the figure shows the launch of the program, passing it an argument consisting of two words - It work .

Figure 3 - Parameters of the main function

And if you remove the quotes. Then we will see only the word It. If you do not plan to pass any information when starting the program, then you can remove the arguments in the main() function, you can also change the names of these arguments. Sometimes there are modifications of the argc and argv parameters, but it all depends on the type of application being created or on the development environment.

When automatically creating a console application in the C++ programming language, a main function is automatically created that is very similar to this one:

int main(int argc, char * argv)
{…}

The function header contains the signature of the main function main() with arguments argc and argv .
If the program is run through the command line, then it is possible to transfer any information to this program. There are command line arguments argc and argv for this.
The argc parameter is of type int , and contains the number of parameters passed to the main function. Moreover, argc is always at least 1, even when no information is passed to the main function, since the name of the application is considered the first parameter.
The argv parameter is an array of pointers to strings. Only string type data can be passed through the command line.

When you run a program through the Windows command line, you can pass some information to it. In this case, the command line will look like:
Drive:\path\name.exe argument1 argument2 ...

Command line arguments are separated by one or more spaces.

The argv argument contains the fully qualified application name:

#include
using namespace std;

cout<< argv << endl;

return 0;
}

Execution result

Example : calculating the product of two integers
The program uses the string to integer conversion function StrToInt() from here .

#include
using namespace std;
int StrToInt(char*s) (…)
int main(int argc, char * argv) (

Int a = 0, b=0;

If (argc > 1)

a = StrToInt(argv);

If (argc > 2)

b = StrToInt(argv);

cout<< a <<«*» << b << «= « << a*b << endl;

return 0;
}

The program is launched as

Execution result

Debugging a Program with Command Line Arguments

To pass command line arguments when debugging a program, you need to access the menu Properties project.


On the tab Configuration Properties ->Debug choose Command arguments and set their values.

When you run the program in debug mode, the entered arguments will be treated by the program as command line arguments.

You can pass certain arguments to C programs. When main() is called at the beginning of the computation, three parameters are passed to it. The first of them determines the number of command arguments when accessing the program. The second one is an array of pointers to character strings containing these arguments (one argument per string). The third one is also an array of pointers to character strings, it is used to access operating system parameters (environment variables).

Any such line is represented as:

variable = value\0

The last line can be found by two trailing zeros.

Let's name the main() function arguments respectively: argc, argv and env (any other names are possible). Then the following descriptions are allowed:

main(int argc, char *argv)

main(int argc, char *argv, char *env)

Suppose there is some program prog.exe on drive A:. Let's address it like this:

A:\>prog.exe file1 file2 file3

Then argv is a pointer to the string A:\prog.exe, argv is a pointer to the string file1, and so on. The first actual argument is pointed to by argv and the last by argv. If argc=1, then there are no parameters after the program name on the command line. In our example, argc=4.

recursion

Recursion is a method of calling in which a function calls itself.

An important point in compiling a recursive program is the organization of the exit. It is easy to make the mistake here that the function will consistently call itself indefinitely. Therefore, the recursive process must, step by step, simplify the problem so that in the end a non-recursive solution appears for it. Using recursion is not always desirable as it can lead to a stack overflow.

Library Functions

In programming systems, subroutines for solving common problems are combined into libraries. These tasks include: calculation of mathematical functions, data input/output, string processing, interaction with operating system tools, etc. The use of library routines saves the user from the need to develop appropriate tools and provides him with an additional service. The functions included in the libraries are supplied with the programming system. Their declarations are given in *.h files (these are the so-called include or header files). Therefore, as mentioned above, at the beginning of the program with library functions, there should be lines like:

#include<включаемый_файл_типа_h>

For example:

#include

There are also facilities for extending and creating new libraries with user programs.

Global variables are assigned a fixed place in memory for the duration of the program. Local variables are stored on the stack. Between them is a memory area for dynamic allocation.

The malloc() and free() functions are used to allocate free memory dynamically. The malloc() function allocates memory, the free() function frees it. The prototypes of these functions are stored in the stdlib.h header file and look like this:

void *malloc(size_t size);

void *free(void *p);

The malloc() function returns a pointer of type void; for proper use, the function value must be converted to a pointer to the appropriate type. On success, the function returns a pointer to the first byte of free memory of size size. If there is not enough memory, the value 0 is returned. The sizeof() operation is used to determine the number of bytes needed for a variable.

An example of using these functions:

#include

#include

p = (int *) malloc(100 * sizeof(int)); /* Allocate memory for 100

integers */

printf("Out of memory\n");

for (i = 0; i< 100; ++i) *(p+i) = i; /* Использование памяти */

for (i = 0; i< 100; ++i) printf("%d", *(p++));

free(p); /* Free memory */

Before using the pointer returned by malloc(), you need to make sure that there is enough memory (the pointer is not null).

Preprocessor

A C preprocessor is a program that processes input to a compiler. The preprocessor looks at the source program and performs the following actions: connects the given files to it, performs substitutions, and also manages compilation conditions. The preprocessor is intended for program lines that begin with the # symbol. Only one command (preprocessor directive) is allowed per line.

Directive

#define identifier substitution

causes the following program text to replace the named identifier with the substitution text (note the lack of a semicolon at the end of this command). Essentially, this directive introduces a macro definition (macro), where "identifier" is the name of the macro definition, and "substitution" is the sequence of characters that the preprocessor replaces the specified name with when it finds it in the program text. The name of a macro is usually capitalized.

Consider examples:

The first line causes the program to replace the identifier MAX with the constant 25. The second allows you to use in the text instead of the opening curly brace (() the word BEGIN.

Note that since the preprocessor does not check the compatibility between the symbolic names of macro definitions and the context in which they are used, it is recommended that such identifiers be defined not with the #define directive, but with the const keyword with an explicit type indication (this is more true for C + +):

const int MAX = 25;

(the type int can be omitted, as it is set by default).

If the #define directive looks like:

#define identifier(identifier, ..., identifier) ​​substitution

and there is no space between the first identifier and the opening parenthesis, then this is a macro substitution definition with arguments. For example, after the appearance of a line like:

#define READ(val) scanf("%d", &val)

statement READ(y); is treated the same as scanf("%d",&y);. Here val is an argument and macro substitution is performed with the argument.

If there are long definitions in the substitution that continue on the next line, a \ character is placed at the end of the next continued line.

You can place objects separated by ## characters in a macro definition, for example:

#define PR(x, y) x##y

After that, PR(a, 3) will call the substitution a3. Or, for example, a macro definition

#define z(a, b, c, d) a(b##c##d)

will change z(sin, x, +, y) to sin(x+y).

The # character placed before a macro argument indicates that it is converted to a string. For example, after the directive

#define PRIM(var) printf(#var"= %d", var)

the following fragment of the program text

is converted like this:

printf("year""= %d", year);

Let's describe other preprocessor directives. The #include directive has been seen before. It can be used in two forms:

#include "file name"

#include<имя файла>

The effect of both commands is to include files with the specified name in the program. The first one loads a file from the current directory or the directory specified as a prefix. The second command searches for the file in standard locations defined in the programming system. If the file whose name is written in double quotes is not found in the specified directory, then the search will continue in the subdirectories specified for the #include command<...>. #include directives can be nested within each other.

The next group of directives allows you to selectively compile parts of the program. This process is called conditional compilation. This group includes the directives #if, #else, #elif, #endif, #ifdef, #ifndef. The basic form of the #if directive is:

#if constant_expression statement_sequence

Here the value of the constant expression is checked. If it is true, then the given sequence of statements is executed, and if it is false, then this sequence of statements is skipped.

The action of the #else directive is similar to the action of the else command in the C language, for example:

#if constant_expression

statement_sequence_2

Here, if the constant expression is true, then sequence_of_operators_1 is executed, and if it is false, sequence_of_operators_2 is executed.

The #elif directive means an "else if" type action. The main form of its use is as follows:

#if constant_expression

statement_sequence

#elif constant_expression_1

statement_sequence_1

#elif constant_expression_n

sequence_of_statements_n

This form is similar to the C language construct of the form: if...else if...else if...

Directive

#ifdef identifier

sets whether the specified identifier is currently defined, i.e. whether it was included in directives of the form #define. View line

#ifndef identifier

checks whether the specified identifier is currently undefined. Any of these directives can be followed by an arbitrary number of lines of text, possibly containing an #else statement (#elif cannot be used) and ending with the line #endif. If the condition being checked is true, then all lines between #else and #endif are ignored, and if false, then the lines between the check and #else (if there is no #else word, then #endif). The #if and #ifndef directives can be nested one inside the other.

View directive

#undef identifier

causes the specified identifier to be considered undefined, i.e. not replaceable.

Consider examples. The three directives are:

check if the identifier WRITE is defined (i.e. was a command of the form #define WRITE...), and if so, then the WRITE name is considered undefined, i.e. not replaceable.

directives

#define WRITE fprintf

check if the WRITE identifier is undefined, and if so, then the WRITE identifier is determined instead of the fprintf name.

The #error directive is written in the following form:

#error error_message

If it occurs in the program text, then compilation stops and an error message is displayed on the display screen. This command is mainly used during the debug phase. Note that the error message does not need to be enclosed in double quotes.

The #line directive is intended to change the values ​​of the _LINE_ and _FILE_ variables defined in the C programming system. The _LINE_ variable contains the line number of the program currently being executed. The _FILE_ identifier is a pointer to a string with the name of the program being compiled. The #line directive is written as follows:

#line number "filename"

Here number is any positive integer that will be assigned to the _LINE_ variable, filename is an optional parameter that overrides the value of _FILE_.

The #pragma directive allows you to pass some instructions to the compiler. For example, the line

indicates that there are assembly language strings in a C program. For example:

Consider some global identifiers or macro names (names of macro definitions). Five such names are defined: _LINE_, _FILE_, _DATE_, _TIME_, _STDC_. Two of them (_LINE_ and _FILE_) have already been described above. The _DATE_ identifier specifies a string that stores the date the source file was translated into object code. The _TIME_ identifier specifies a string that stores the time the source file was translated into object code. The _STDC_ macro has a value of 1 if standard-defined macro names are used. Otherwise, this variable will not be defined.

It happens that data is transferred to the program from the command line when it is called. Such data is called command line arguments. It looks like this, for example:

./a.out test.txt ls -lt /home/peter/

This calls the programs a.out (from the current directory) and ls (from the same directory specified in the PATH environment variable). The first program from the command line receives one word - test.txt, the second - two: -lt and /home/peter/.

If the program is written in C, then when it starts, control is immediately transferred to the main() function, therefore, it is she who receives the command line arguments that are assigned to her variable parameters.

So far, we've defined the main() function as if it doesn't take any parameters and doesn't return anything. In fact, in C, any function by default (if nothing else is defined) returns an integer. This can be verified. If you write the code like this:

main() ( printf("Hi \n") ; return 0 ; )

Then no warning or error will occur during compilation. The same will happen if we write int main() . This proves that the default function returns an integer and not nothing (void). Although what the function returns can always be "overridden", for example, voidmain() or float main() .

When a program is called from the command line, a pair of data is always passed to it:

  1. integer, denoting the number of words (elements separated by spaces) on the command line when called,
  2. pointer to array of strings, where each line is a single word from the command line.

Note that the program name itself is also considered. For example, if the call looks like this:

./a.out 12 theme 2

Then the first argument of the program is 4, and the array of strings is defined as ("./a.out", "12", "theme", "2").

Pay attention to the terminology, there are only two program arguments (a number and an array), but as many command line arguments as you like. Command line arguments are "translated" into program arguments (into arguments to the main() function).
This data (number and pointer) is passed to the program even when it is simply called by name without passing anything to it: ./a.out. In this case, the first argument is 1, and the second argument points to an array of just one string (""./a.out").

The fact that data is passed to the program does not mean that the main() function should receive it. If the main() function is defined without parameters, then the command line arguments cannot be accessed. Although nothing prevents you from sending them. No error will occur.

To get access to the data passed to the program, they must be assigned to variables. Since the arguments are immediately passed to main() , its header should look like this:
main (int n, char *arr)

The first variable (n) contains the number of words, and the second variable contains a pointer to an array of strings. Often the second parameter is written as **arr . However, it is the same. Recall that the array of strings itself contains pointers to strings as its elements. And in the function we pass a pointer to the first element of the array. It turns out that we are passing a pointer to a pointer, i.e. **arr.

Exercise
Write a program like this:

#include int main(int argc, char ** argv) ( int i; printf ("%d \n", argc) ; for (i= 0 ; i< argc; i++ ) puts (argv[ i] ) ; }

It prints the number of words on the command line when it is called, and each word on a new line. Call it without command line arguments and with arguments.

In the program, we used the variable parameters argc and argv. It is customary to use just such names, but in fact they can be anything. It is better to adhere to this standard so that your programs are more understandable not only to you, but also to other programmers.

The Practical Importance of Passing Data to a Program

If you have experience with the GNU/Linux command line, you know that most commands have switches and arguments. For example, when viewing the contents of directories, copying, moving, the file system objects on which the command is executed are specified as arguments. Features of its implementation are determined using keys. For example, in the command

Cp -r ../les_1 ../les_101

cp is the name of the command, -r is the switch, and ../les_1 and ../les_101 are the command arguments.

In general, most often, when programs are launched, file addresses and "modifiers" (these are keys) of the program execution process are transferred.

Let's write a program that opens the files specified by the user on the command line for writing or appending and writes (adds) there the same information that the user enters from the keyboard during the program execution:

#include #include main (int argc, char ** argv) ( int i, ch; FILE * f[ 5 ] ; if (argc< 3 || argc >7 ) ( puts ( "Invalid number of parameters") ; return 1 ; ) if (strcmp (argv[ 1 ] , "-w" ) != 0 && strcmp (argv[ 1 ] , "-a" ) != 0 ) ( puts ( "The first parameter can be either -w or -a") ; return 2 ; ) for (i= 0 ; i< argc- 2 ; i++ ) { f[ i] = fopen (argv[ i+ 2 ] , argv[ 1 ] + 1 ) ; if (f[ i] == NULL) { printf ("File %s cannot be opened\n ", argv[ i+ 2 ] ) ; return 3 ; ) ) while ((ch = getchar () ) != EOF) for (i= 0 ; i< argc- 2 ; i++ ) putc (ch, f[ i] ) ; for (i= 0 ; i < argc- 2 ; i++ ) fclose (f[ i] ) ; return 0 ; }

Explanations for the code:

  1. An array of five file pointers is created. Therefore, no more than five files can be opened at the same time. The file pointer of the first file will be stored in the array element f, the second - in f, and so on.
  2. The number of command line arguments is checked. There must be at least three of them, because. the first is the name of the program, the second is the file open mode, the third is the first or only file to be written to. Since the program only allows you to open five files, the total number of command line arguments cannot exceed seven. Therefore, if the number of arguments is less than 3 or more than 7, then the program ends, because The return statement causes the function to exit, even if there is more code after it. A function return value that is not equal to 0 can be interpreted by the parent process as a message that the program terminated with an error.
  3. The correctness of the second command line argument is checked. If it is neither "-w" nor "-a", then the conditional expression in the second if returns 1 (true). The strcmp() function allows you to compare strings and returns 0 if they are equal.
  4. The for loop opens files at the specified addresses that start at the third element of the argv array. That is why 2 is added to i to get the elements of the argv array, starting from the third. The expression argc-2 indicates the number of filenames passed; because argc stores the total number of command line arguments, the first two of which are not filenames.
  5. The expression argv+1 allows you to "cut" the substring "w" (or "a") from the string "-w" (or "-a"), because argv is essentially a pointer to the first element of the string. By adding one to the pointer, we shift it to the next element in the array.
  6. If the file cannot be opened, the fopen() function returns NULL. In this case, the program ends.
  7. Each character entered by the user from the keyboard is written to all open files.
  8. At the end, the files are closed.