Программирование на языке C в Microsoft Visual Studio 2010

Использование аргументов командной строки в С

Разбить на страницы
Показывать лекцию целиком

Теоретическая часть

Аргумент командной строки – это информация, которая вводится в командной строке операционной системы вслед за именем программы [21.1].

В системных средах, поддерживающих язык программирования С, существует способ передавать в программу аргументы или параметры командной строки при запуске программы на выполнение [21.2]. Для этого в главную функцию main() включают два аргумента, обычно argc и argv. Первый (от argument count – счетчик аргументов) содержит количество аргументов командной строки, с которыми была запущена программа. Второй (от argument vector – вектор аргументов) указывает на массив символьных строк, содержащих сами аргументы, – по одному в строке. В общем случае имена аргументов могут быть произвольными.

Формально можно определить следующий прототип функции main() с параметрами:

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

Второй параметр функции main() выражает собой многоуровневую систему указателей. В связи с этим можно определить другой способ задания параметров функции main(), а именно

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

Каждый указатель на значение типа char ссылается на одну из строк командной строки, при этом argv[0] указывает на имя команды (исполняемой программы), argv[1] – на первый аргумент командной строки, argv[2] – на второй аргумент и так далее [21.3].

В качестве принимаемых аргументов командной строки могут быть исполняемые файлы. Можно из программы запустить на выполнение другую программу, запустить новый процесс. Для этого существуют специальные функции библиотеки "C Run–Time Library Reference" системы Visual Studio (которую используем в качестве компилятора языка С ).

Командная оболочка операционной системы Windows использует интерпретатор команд cmd.exe, который загружает приложения и направляет поток данных между приложениями, для перевода введенной команды в понятный системе код. Консоль командной строки присутствует во всех версиях операционных систем Windows.

В среде разработки MS Visual Studio 2010 аргументы командной строки можно задать в самой среде, для чего следует произвести соответствующую настройку. Например, предположим, что мы хотим создать проект под именем tcmd, чтобы он принимал аргументы командной строки, например, "Example 1" и E:\forma.exe. Для этого после (или во время) создания проекта обратиться к закладке, показанной на рис 21.1.

(рис 21.1) Пример настройки и задания аргументов командной строки

Параметры или аргументы командной строки должны вводиться через пробелы. В случае, если параметр представляет собой строку с пробелами, то его следует взять в двойные кавычки.

Использование указанной возможности интегрированной среды разработки позволяет произвести отладку программы с аргументами командной строки. В дальнейшем задание параметров в соответствии с рис 21.1 не обязательно. Программа должна сама подхватывать аргументы командной строки, определенные с помощью утилиты cmd.exe (просто cmd) операционной системы.

Командную строку операционной системы Windows можно запустить следующими способами:

  • Пуск $$\to$$ Программы (все программы) $$\to$$ Стандартные $$\to$$ Командная строка
  • Пуск $$\to$$ Выполнить $$\to$$ (ввести) cmd
  • Параметры, представленные на рис 21.1, можно ввести из командной строки операционной системы Windows, как показано на рис 21.2.

    (рис 21.2) Пример ввода аргументов командной строки Windows

    Если подготовлена программа, в которой функция main() принимает два аргумента, то из командной строки можно передать, например, некоторые исполняемые файлы, такие как notepad.exe, winword.exe, чтобы можно было открыть "Блокнот" или документ "Word".

    Практическая часть

    Пример 1. Напишите программу с аргументами командной строки, в которую передайте строки "Hello, world", "D:\forma.exe", "MS Visual Studio 2010", "D:\knapsack.exe", "команда cmd", где исполняемый файл "forma.exe" обеспечивает форматированный вывод случайных чисел, распределенных по нормальному закону, исполняемый файл "E:\knapsack.exe" решает задачу о рюкзаке (см.Тему 18).

    Аргументы командной строки определите в среде MS Visual Studio 2010. Прежде чем реализовать программный код решения примера, приведем программный код для исполняемого файла "forma.exe". Программный код форматированного вывода случайных чисел:

    // Файл main.c программы forma (forma.exe)
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <time.h>
    #include <locale.h>
    #include <string.h>
    
    #include <math.h>
    #include <float.h>
    #include <limits.h>
    
    int main (void) {
    	int i, j;
    
    	double nd, md, fd, posd;
    	double factor = 1.23;
    	int n, m, f, pos; // row, column, floor point, distance
    	int in = 0;
    	double **A = NULL;
    	double S = 0.0;
    	double V1, V2, R1, R2;
    	double tmax, tmin;
    	char *smax, *smin;
    	FILE *fid;
    	errno_t err;
    	time_t t;
    
    	setlocale(LC_ALL, "rus");
    	setlocale(LC_NUMERIC, "uk");
         
         srand((unsigned)time(t)); // рандомизация случайных чисел
    
    	printf("\n Введите количество строк двумерного массива: ");
    	in = scanf_s("%lf", nd);
    	 if (in != 1) {
    		printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	}
    
    	 if ( nd < 1.0 || floor(nd) != nd ) {
    printf("\n Ошибка! Количество строк массива должно быть\
     натуральным числом.\n \
    Нажмите любуюу клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    	 
    	 if (nd > (double)(INT_MAX/10000) ) {
    	 printf("\n Слишком большое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    	 
    printf(" Введите количество столбцов двумерного массива: ");
    	in = scanf_s("%lf", md);
    	 
         if (in != 1)
        {
    		printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_
              getch();
    		exit(1);
    	}
    
    	  if ( md < 1.0 || floor(md) != md )
         {
    		 printf("\n Ошибка! Количество столбцов массива должно быть натуральным числом.\n \
    Нажмите любуюу клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    
    	   if (md > (double)(INT_MAX/10000) )
         {
    printf("\n Слишком большое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    
    	 printf(" Введите произвольное действительное число: ");
    	in = scanf_s("%lf", factor);
    	 if (in != 1)
        {
    		printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	}
    	 if ( factor > (double)(INT_MAX/1000) || factor < (double)(INT_MIN/1000)) {
    printf("\n Слишком большое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    
    	 }
    	 if ( factor < (10000.0*DBL_EPSILON )  factor > -(10000.0*DBL_EPSILON ) )
    	 {
    printf("\n Слишком малое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    	
    printf(" Введите количество цифр после десятичной точки: ");
    	 in = scanf_s("%lf", fd);
    
    	 if (in != 1) {
    printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	 }
    	
    	 if ( fd < 0.0 || fd > 14){
    printf("\n Количество цифр должно лежать в диапазоне [0; 14].\
    \n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	 }
    
    	 if ( floor(fd) != fd )
        {
    printf("\n Количество цифр должно быть целым числом \
    в диапазоне  [0; 14].\n Нажмите любую клавишу: ");
    _getch();
    exit(1);
    	 }
    	 
    printf(" Введите минимальное количество позиций \
    между столбцами массива: ");
    	 in = scanf_s("%lf", posd);
    
    	 if (in != 1)
         {
    printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	 }
    	
     if ( floor(posd) != posd )
         {
    printf("\n Количество позиций должно быть целым числом \
    в диапазоне  [1; 10].\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	 }
    
    	 if ( posd < 0.0 || posd > 10.0)
         {
    printf("\n Количество позиций должно лежать в диапазоне \
      [1; 10].\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	 }
    
    f = (int)fd;
    pos = (int)posd;
    n = (int)nd;
    m = (int)md;
    
    	A = (double **)malloc(n*sizeof(double *));
    
    	for (i = 0; i < n; i++)
    		A[i] = (double *)malloc(m*sizeof(double));
    
    	// Заполнение матрицы по нормальному закону
    	// метод Марсальи-Брея
    S = 1.0;
    for (i = 0; i < n; i++) {
    	for (j = 0; j < m; j++) {
    		while (S >= 1.0) {
    R1 = (double) rand()/RAND_MAX;
      R2 = (double) rand()/RAND_MAX;
      V1 = 2.0*R1 - 1.0;
      V2 = 2.0*R2 - 1.0;
      S = (V1*V1 + V2*V2); 
    
    		}
    			A[i][j] = factor * V1 * sqrt(-2.0*log(S)/S);
    			S = 1.0;
    		}
    	}
    
    tmax = tmin = A[0][0];
    
    for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
    if (tmax < A[i][j])
    tmax = A[i][j];
    
    for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
    if (tmin > A[i][j])
    tmin = A[i][j];
    
    smax = (char *)malloc((pos+f+(int)INT_MAX/10000 )*sizeof(char));
    sprintf_s(smax, (pos+f+(int)INT_MAX/10000 - 1),"%0.*f",f,tmax);
    
    smin = (char *)malloc((pos+f+(int)INT_MAX/10000 )*sizeof(char));
    sprintf_s(smin, (pos+f+(int)INT_MAX/10000 - 1),"%0.*f",f,tmin);
    	
    // int n, m, f, pos; // row, column, floor point, distance
    in = (strlen(smin) > strlen(smax)? strlen(smin): strlen(smax));
     
    if ((in+pos)*m < 80)
       {
    	puts("\n Пример форматированного вывода числовой матрицы:");
    for (i = 0; i < n; i++) {
    puts("");
    for (j = 0; j < m; j++)
    printf("%*.*f", in + pos, f, A[i][j]);
    	}
    
    	puts("");
    }
    
    else if ((in+pos)*m < 1000)
        {
    	if ( (err = fopen_s(fid, "format.txt", "w")) != 0 ) {
    printf("\n Файл для записи \"format.txt\" не может \
    быть открыт.\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	}
    
    fprintf(fid, "\r\n\t Пример форматированного вывода \
    числовой матрицы: \r\n");
    fprintf(fid, "\r\n Матрица размера %dx%d из нормально \
    распределенных случайных чисел,\r\n \
    умноженных на число %g. Количество цифр после \
    десятичной точки: %d\r\n \
    Количество позиций между числами: %d\r\n",n,m,factor,f,pos);
    	for (i = 0; i < n; i++)
        {
    fprintf(fid, "\r\n");
    for (j = 0; j < m; j++)
    fprintf(fid, "%*.*f", in + pos, f, A[i][j]);
    	}
    	fprintf(fid, "\r\n");
    	
    printf("\n Результат смотрите в файле \"format.txt\"\n" );
    	fclose(fid);
    }
    
    else 
    {
    printf("\n Результат не может быть форматированно выведен\n \
    в текстовый документ или на консоль для заданного\n \
    количества столбцов, величины поля между числами\n \
    и количеством знаков после десятичной точки.\n"); 
    printf("\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    }
    
    	printf("\n\n ... Нажмите любую клавишу: ");
    	_getch();
    	return 0;
    }

    Исполняемый файл этой программы разместим на одном из жестких дисков, например, на диске D, т. е. D:\forma.exe. Также и файл "knapsack.exe" разместим на диске D, т. е. D:\knapsack.exe. Для запуска исполняемых приложений используем функцию _spawnl(), для которой подключим заголовочный файл <process.h>. Основной программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <locale.h>
    #include <process.h>
    #include <ctype.h>
    #include <string.h>
    
    int main (int argc, char *argv[])
    {
    	int count, p, i;
    	int j;
    	int N[20]; // массив для индексов исполняемых приложений
    
    count = p = i = 0; 		
    
    // На случай, когда командная строка содержит русские шрифты
    	setlocale(LC_ALL, "rus");
    
    	printf("\n Общее количество аргументов: %d\n\n", argc);
    
    if (argc == 1)
    	printf(" Имя аргумента и путь к нему:\n%4d) %s\n", count+1, argv[count]);
    
    else
     {
    		for (count = 0; count < argc; count++) {
    		printf(" %3d) %s\n", count+1, argv[count]);
    		
    if ( (strstr(argv[count], ".exe")) != NULL)
    N[i++] = count;
    
    	}
    }
    			if (i > 1) 
                {	
    			if (i == 2)
    printf("\n Для запуска исполняемого приложения \n \
    можно ввести число ");
    			
                   else
    printf("\n Для запуска исполняемого приложения \n \
    можно ввести числа ");
    
    			for (j = 1; j < i; j++)
    			{
    				if (j < i-1) 
    printf("\"%d\", ", N[j]+1);
    				else 
    printf("\"%d\": ", N[j]+1);
    			}
    
       scanf_s("%d", p);
    		
    _spawnl(_P_WAIT, argv[p-1], argv[p-1], NULL);
    
    }
    		else
    printf("\n Исполняемых приложений нет.\n");
    			
    	printf("\n Завершение проекта tcmd ... Press any key: ");
    	_getch();
    	return 0;
    }

    В программе используется функция strstr() для поиска заданной подстроки (.ехе) в заданной строке символов. Для этой функции подключен заголовочный файл <string.h>. В общем случае исполняемые файлы могут быть заданы без расширения .ехе. Можно также имена исполняемых файлов передавать в функцию как строки, определенные в самой программе без использования командной строки.

    Пример выполнения программы показан на рис 21.3.

    (рис 21.3) Пример вызова исполняемого файла

    Задание 1

  • Внесите изменения в программу, чтобы исполняемые файлы выполнялись без указания расширения .ехе.
  • В программу внесите изменения для определения номера (номеров) индексов первого символа подстроки (подстрок) ".ехе".
  • В командную строку (с помощью закладки Alt+F7) введите номер компьютера, на котором выполняется лабораторная работа. Проверьте работу программы.
  • Проверьте работоспособность программы, когда в качестве второго аргумента функции main() будет использоваться char **argv.
  • Внесите в программу изменения для посимвольного вывода аргументов командной строки.
  • В программе предусмотрите защиту от неправильного ввода данных с клавиатуры.
  • Пример 2. Напишите программу с аргументами командной строки, которые вводятся с помощью интерпретатора cmd. В качестве аргументов примите исполняемый файл forma.exe (см. предыдущий пример), notepad.exe, winword.exe.

    Файлы notepad.exe, winword.exe расположены в директориях "C:\WINDOWS\system32" и "C:\Program Files\Microsoft Office\OFFICE12" (последний путь зависит от версии Microsoft Office). Расположим указанные исполняемые файлы на диске С:.

    Программный код решения примера 2 можно оставить таким же, что и для примера 1.

    Начало выполнения программы показано на рис 21.4.

    (рис 21.4) Пример ввода аргументов командной строки операционной системы

    В соответствии с введенным номером аргумента командной строки открывается "Блокнот", который показан на рис 21.5.

    (рис 21.5) Форма текстового документа, вызванная из программы

    После закрытия блокнота (Безымянный - Блокнот) произойдет завершение программы tcmd.

    Задание 2

  • Проверьте работу программы при расположении указанных исполнимых приложений на разных жестких дисках.
  • Проверьте работу программы по всем номерам исполняемых приложений.
  • В программу внесите операцию чтения текстового файла (из блокнота, который откроется после выбора notepad.exe), в котором записать номер компьютера, за которым выполняется лабораторная работа, специальность обучения (например, АСОИУ) и номер учебной группы
  • В качестве аргумента командной строки введите команду ping.exe (путь к ней: C:\WINDOWS\system32). Скриншот полученного результата вставьте в отчет лабораторной работы.
  • В качестве аргумента командной строки введите команду qprocess.exe (путь к ней: C:\WINDOWS\system32). Скриншот полученного результата вставьте в отчет лабораторной работы.
  • Контрольные вопросы

  • Какой тип имеют аргументы командной строки?
  • Какое основное назначение имеют аргументы командной строки?
  • Каким образом разделяются аргументы командной строки?
  • К чему приводит инкрементирование второго аргумента функции main() в программе, в которой происходит обращение к этому аргументу?
  • Каким образом можно вставить содержимое буфера памяти (например, полный путь к команде notepad.exe или строку из текстового документа) в командную строку операционной системы Windows?
  • Страницы:

    Теоретическая часть

    Аргумент командной строки – это информация, которая вводится в командной строке операционной системы вслед за именем программы [21.1].

    В системных средах, поддерживающих язык программирования С, существует способ передавать в программу аргументы или параметры командной строки при запуске программы на выполнение [21.2]. Для этого в главную функцию main() включают два аргумента, обычно argc и argv. Первый (от argument count – счетчик аргументов) содержит количество аргументов командной строки, с которыми была запущена программа. Второй (от argument vector – вектор аргументов) указывает на массив символьных строк, содержащих сами аргументы, – по одному в строке. В общем случае имена аргументов могут быть произвольными.

    Формально можно определить следующий прототип функции main() с параметрами:

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

    Второй параметр функции main() выражает собой многоуровневую систему указателей. В связи с этим можно определить другой способ задания параметров функции main(), а именно

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

    Каждый указатель на значение типа char ссылается на одну из строк командной строки, при этом argv[0] указывает на имя команды (исполняемой программы), argv[1] – на первый аргумент командной строки, argv[2] – на второй аргумент и так далее [21.3].

    В качестве принимаемых аргументов командной строки могут быть исполняемые файлы. Можно из программы запустить на выполнение другую программу, запустить новый процесс. Для этого существуют специальные функции библиотеки "C Run–Time Library Reference" системы Visual Studio (которую используем в качестве компилятора языка С ).

    Командная оболочка операционной системы Windows использует интерпретатор команд cmd.exe, который загружает приложения и направляет поток данных между приложениями, для перевода введенной команды в понятный системе код. Консоль командной строки присутствует во всех версиях операционных систем Windows.

    В среде разработки MS Visual Studio 2010 аргументы командной строки можно задать в самой среде, для чего следует произвести соответствующую настройку. Например, предположим, что мы хотим создать проект под именем tcmd, чтобы он принимал аргументы командной строки, например, "Example 1" и E:\forma.exe. Для этого после (или во время) создания проекта обратиться к закладке, показанной на рис 21.1.

    (рис 21.1) Пример настройки и задания аргументов командной строки

    Параметры или аргументы командной строки должны вводиться через пробелы. В случае, если параметр представляет собой строку с пробелами, то его следует взять в двойные кавычки.

    Использование указанной возможности интегрированной среды разработки позволяет произвести отладку программы с аргументами командной строки. В дальнейшем задание параметров в соответствии с рис 21.1 не обязательно. Программа должна сама подхватывать аргументы командной строки, определенные с помощью утилиты cmd.exe (просто cmd) операционной системы.

    Командную строку операционной системы Windows можно запустить следующими способами:

  • Пуск $$\to$$ Программы (все программы) $$\to$$ Стандартные $$\to$$ Командная строка
  • Пуск $$\to$$ Выполнить $$\to$$ (ввести) cmd
  • Параметры, представленные на рис 21.1, можно ввести из командной строки операционной системы Windows, как показано на рис 21.2.

    (рис 21.2) Пример ввода аргументов командной строки Windows

    Если подготовлена программа, в которой функция main() принимает два аргумента, то из командной строки можно передать, например, некоторые исполняемые файлы, такие как notepad.exe, winword.exe, чтобы можно было открыть "Блокнот" или документ "Word".

    Практическая часть

    Пример 1. Напишите программу с аргументами командной строки, в которую передайте строки "Hello, world", "D:\forma.exe", "MS Visual Studio 2010", "D:\knapsack.exe", "команда cmd", где исполняемый файл "forma.exe" обеспечивает форматированный вывод случайных чисел, распределенных по нормальному закону, исполняемый файл "E:\knapsack.exe" решает задачу о рюкзаке (см.Тему 18).

    Аргументы командной строки определите в среде MS Visual Studio 2010. Прежде чем реализовать программный код решения примера, приведем программный код для исполняемого файла "forma.exe". Программный код форматированного вывода случайных чисел:

    // Файл main.c программы forma (forma.exe)
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <time.h>
    #include <locale.h>
    #include <string.h>
    
    #include <math.h>
    #include <float.h>
    #include <limits.h>
    
    int main (void) {
    	int i, j;
    
    	double nd, md, fd, posd;
    	double factor = 1.23;
    	int n, m, f, pos; // row, column, floor point, distance
    	int in = 0;
    	double **A = NULL;
    	double S = 0.0;
    	double V1, V2, R1, R2;
    	double tmax, tmin;
    	char *smax, *smin;
    	FILE *fid;
    	errno_t err;
    	time_t t;
    
    	setlocale(LC_ALL, "rus");
    	setlocale(LC_NUMERIC, "uk");
         
         srand((unsigned)time(t)); // рандомизация случайных чисел
    
    	printf("\n Введите количество строк двумерного массива: ");
    	in = scanf_s("%lf", nd);
    	 if (in != 1) {
    		printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	}
    
    	 if ( nd < 1.0 || floor(nd) != nd ) {
    printf("\n Ошибка! Количество строк массива должно быть\
     натуральным числом.\n \
    Нажмите любуюу клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    	 
    	 if (nd > (double)(INT_MAX/10000) ) {
    	 printf("\n Слишком большое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    	 
    printf(" Введите количество столбцов двумерного массива: ");
    	in = scanf_s("%lf", md);
    	 
         if (in != 1)
        {
    		printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_
              getch();
    		exit(1);
    	}
    
    	  if ( md < 1.0 || floor(md) != md )
         {
    		 printf("\n Ошибка! Количество столбцов массива должно быть натуральным числом.\n \
    Нажмите любуюу клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    
    	   if (md > (double)(INT_MAX/10000) )
         {
    printf("\n Слишком большое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    
    	 printf(" Введите произвольное действительное число: ");
    	in = scanf_s("%lf", factor);
    	 if (in != 1)
        {
    		printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	}
    	 if ( factor > (double)(INT_MAX/1000) || factor < (double)(INT_MIN/1000)) {
    printf("\n Слишком большое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    
    	 }
    	 if ( factor < (10000.0*DBL_EPSILON )  factor > -(10000.0*DBL_EPSILON ) )
    	 {
    printf("\n Слишком малое число. Нажмите любую клавишу: ");
    		 _getch();
    		 exit(1);
    	 }
    	
    printf(" Введите количество цифр после десятичной точки: ");
    	 in = scanf_s("%lf", fd);
    
    	 if (in != 1) {
    printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	 }
    	
    	 if ( fd < 0.0 || fd > 14){
    printf("\n Количество цифр должно лежать в диапазоне [0; 14].\
    \n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	 }
    
    	 if ( floor(fd) != fd )
        {
    printf("\n Количество цифр должно быть целым числом \
    в диапазоне  [0; 14].\n Нажмите любую клавишу: ");
    _getch();
    exit(1);
    	 }
    	 
    printf(" Введите минимальное количество позиций \
    между столбцами массива: ");
    	 in = scanf_s("%lf", posd);
    
    	 if (in != 1)
         {
    printf("\n Ошибка ввода. Нажмите любую клавишу: ");
    		_getch();
    		exit(1);
    	 }
    	
     if ( floor(posd) != posd )
         {
    printf("\n Количество позиций должно быть целым числом \
    в диапазоне  [1; 10].\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	 }
    
    	 if ( posd < 0.0 || posd > 10.0)
         {
    printf("\n Количество позиций должно лежать в диапазоне \
      [1; 10].\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	 }
    
    f = (int)fd;
    pos = (int)posd;
    n = (int)nd;
    m = (int)md;
    
    	A = (double **)malloc(n*sizeof(double *));
    
    	for (i = 0; i < n; i++)
    		A[i] = (double *)malloc(m*sizeof(double));
    
    	// Заполнение матрицы по нормальному закону
    	// метод Марсальи-Брея
    S = 1.0;
    for (i = 0; i < n; i++) {
    	for (j = 0; j < m; j++) {
    		while (S >= 1.0) {
    R1 = (double) rand()/RAND_MAX;
      R2 = (double) rand()/RAND_MAX;
      V1 = 2.0*R1 - 1.0;
      V2 = 2.0*R2 - 1.0;
      S = (V1*V1 + V2*V2); 
    
    		}
    			A[i][j] = factor * V1 * sqrt(-2.0*log(S)/S);
    			S = 1.0;
    		}
    	}
    
    tmax = tmin = A[0][0];
    
    for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
    if (tmax < A[i][j])
    tmax = A[i][j];
    
    for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
    if (tmin > A[i][j])
    tmin = A[i][j];
    
    smax = (char *)malloc((pos+f+(int)INT_MAX/10000 )*sizeof(char));
    sprintf_s(smax, (pos+f+(int)INT_MAX/10000 - 1),"%0.*f",f,tmax);
    
    smin = (char *)malloc((pos+f+(int)INT_MAX/10000 )*sizeof(char));
    sprintf_s(smin, (pos+f+(int)INT_MAX/10000 - 1),"%0.*f",f,tmin);
    	
    // int n, m, f, pos; // row, column, floor point, distance
    in = (strlen(smin) > strlen(smax)? strlen(smin): strlen(smax));
     
    if ((in+pos)*m < 80)
       {
    	puts("\n Пример форматированного вывода числовой матрицы:");
    for (i = 0; i < n; i++) {
    puts("");
    for (j = 0; j < m; j++)
    printf("%*.*f", in + pos, f, A[i][j]);
    	}
    
    	puts("");
    }
    
    else if ((in+pos)*m < 1000)
        {
    	if ( (err = fopen_s(fid, "format.txt", "w")) != 0 ) {
    printf("\n Файл для записи \"format.txt\" не может \
    быть открыт.\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    	}
    
    fprintf(fid, "\r\n\t Пример форматированного вывода \
    числовой матрицы: \r\n");
    fprintf(fid, "\r\n Матрица размера %dx%d из нормально \
    распределенных случайных чисел,\r\n \
    умноженных на число %g. Количество цифр после \
    десятичной точки: %d\r\n \
    Количество позиций между числами: %d\r\n",n,m,factor,f,pos);
    	for (i = 0; i < n; i++)
        {
    fprintf(fid, "\r\n");
    for (j = 0; j < m; j++)
    fprintf(fid, "%*.*f", in + pos, f, A[i][j]);
    	}
    	fprintf(fid, "\r\n");
    	
    printf("\n Результат смотрите в файле \"format.txt\"\n" );
    	fclose(fid);
    }
    
    else 
    {
    printf("\n Результат не может быть форматированно выведен\n \
    в текстовый документ или на консоль для заданного\n \
    количества столбцов, величины поля между числами\n \
    и количеством знаков после десятичной точки.\n"); 
    printf("\n Нажмите любую клавишу: ");
    
    _getch();
    exit(1);
    }
    
    	printf("\n\n ... Нажмите любую клавишу: ");
    	_getch();
    	return 0;
    }

    Исполняемый файл этой программы разместим на одном из жестких дисков, например, на диске D, т. е. D:\forma.exe. Также и файл "knapsack.exe" разместим на диске D, т. е. D:\knapsack.exe. Для запуска исполняемых приложений используем функцию _spawnl(), для которой подключим заголовочный файл <process.h>. Основной программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <locale.h>
    #include <process.h>
    #include <ctype.h>
    #include <string.h>
    
    int main (int argc, char *argv[])
    {
    	int count, p, i;
    	int j;
    	int N[20]; // массив для индексов исполняемых приложений
    
    count = p = i = 0; 		
    
    // На случай, когда командная строка содержит русские шрифты
    	setlocale(LC_ALL, "rus");
    
    	printf("\n Общее количество аргументов: %d\n\n", argc);
    
    if (argc == 1)
    	printf(" Имя аргумента и путь к нему:\n%4d) %s\n", count+1, argv[count]);
    
    else
     {
    		for (count = 0; count < argc; count++) {
    		printf(" %3d) %s\n", count+1, argv[count]);
    		
    if ( (strstr(argv[count], ".exe")) != NULL)
    N[i++] = count;
    
    	}
    }
    			if (i > 1) 
                {	
    			if (i == 2)
    printf("\n Для запуска исполняемого приложения \n \
    можно ввести число ");
    			
                   else
    printf("\n Для запуска исполняемого приложения \n \
    можно ввести числа ");
    
    			for (j = 1; j < i; j++)
    			{
    				if (j < i-1) 
    printf("\"%d\", ", N[j]+1);
    				else 
    printf("\"%d\": ", N[j]+1);
    			}
    
       scanf_s("%d", p);
    		
    _spawnl(_P_WAIT, argv[p-1], argv[p-1], NULL);
    
    }
    		else
    printf("\n Исполняемых приложений нет.\n");
    			
    	printf("\n Завершение проекта tcmd ... Press any key: ");
    	_getch();
    	return 0;
    }

    В программе используется функция strstr() для поиска заданной подстроки (.ехе) в заданной строке символов. Для этой функции подключен заголовочный файл <string.h>. В общем случае исполняемые файлы могут быть заданы без расширения .ехе. Можно также имена исполняемых файлов передавать в функцию как строки, определенные в самой программе без использования командной строки.

    Пример выполнения программы показан на рис 21.3.

    (рис 21.3) Пример вызова исполняемого файла

    Задание 1

  • Внесите изменения в программу, чтобы исполняемые файлы выполнялись без указания расширения .ехе.
  • В программу внесите изменения для определения номера (номеров) индексов первого символа подстроки (подстрок) ".ехе".
  • В командную строку (с помощью закладки Alt+F7) введите номер компьютера, на котором выполняется лабораторная работа. Проверьте работу программы.
  • Проверьте работоспособность программы, когда в качестве второго аргумента функции main() будет использоваться char **argv.
  • Внесите в программу изменения для посимвольного вывода аргументов командной строки.
  • В программе предусмотрите защиту от неправильного ввода данных с клавиатуры.
  • Пример 2. Напишите программу с аргументами командной строки, которые вводятся с помощью интерпретатора cmd. В качестве аргументов примите исполняемый файл forma.exe (см. предыдущий пример), notepad.exe, winword.exe.

    Файлы notepad.exe, winword.exe расположены в директориях "C:\WINDOWS\system32" и "C:\Program Files\Microsoft Office\OFFICE12" (последний путь зависит от версии Microsoft Office). Расположим указанные исполняемые файлы на диске С:.

    Программный код решения примера 2 можно оставить таким же, что и для примера 1.

    Начало выполнения программы показано на рис 21.4.

    (рис 21.4) Пример ввода аргументов командной строки операционной системы

    В соответствии с введенным номером аргумента командной строки открывается "Блокнот", который показан на рис 21.5.

    (рис 21.5) Форма текстового документа, вызванная из программы

    После закрытия блокнота (Безымянный - Блокнот) произойдет завершение программы tcmd.

    Задание 2

  • Проверьте работу программы при расположении указанных исполнимых приложений на разных жестких дисках.
  • Проверьте работу программы по всем номерам исполняемых приложений.
  • В программу внесите операцию чтения текстового файла (из блокнота, который откроется после выбора notepad.exe), в котором записать номер компьютера, за которым выполняется лабораторная работа, специальность обучения (например, АСОИУ) и номер учебной группы
  • В качестве аргумента командной строки введите команду ping.exe (путь к ней: C:\WINDOWS\system32). Скриншот полученного результата вставьте в отчет лабораторной работы.
  • В качестве аргумента командной строки введите команду qprocess.exe (путь к ней: C:\WINDOWS\system32). Скриншот полученного результата вставьте в отчет лабораторной работы.
  • Контрольные вопросы

  • Какой тип имеют аргументы командной строки?
  • Какое основное назначение имеют аргументы командной строки?
  • Каким образом разделяются аргументы командной строки?
  • К чему приводит инкрементирование второго аргумента функции main() в программе, в которой происходит обращение к этому аргументу?
  • Каким образом можно вставить содержимое буфера памяти (например, полный путь к команде notepad.exe или строку из текстового документа) в командную строку операционной системы Windows?
  • Вернуться к учебному плану