Пример 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++) {
if (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);
}
free(smax);
free(smin);
for (i = 0; i < n; i++)
free(A[i]);
free(A);
printf("\n\n... Нажмите любую клавишу: ");
getch();
return 0;
}
|
Исполняемый файл программы разместим на одном из жестких дисков, например на диске D D:\forma.exe, сюда же добавим файл «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, j;
int N[20]; // массив для индексов исполняемых приложений
count = p = i = 0;
// На случай, когда командная строка содержит русские шрифты
setlocale(LC_ALL, "rus");
printf("\n Общее количество аргументов: %d\n\n", argc);
if (argc == 1)
printf(" Имя аргумента и путь к нему:\n%4d) %c\n", count+1, argv[count]);
else
{
for (count = 0; count < argc; count++) {
printf(" %3d) %c\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
1. Внесите изменения в программу, чтобы исполняемые файлы выполнялись без указания расширения.ехе.
2. В программу внесите изменения для определения номера (номеров) индексов первого символа подстроки (подстрок).ехе.
3. В командную строку (с помощью закладки Alt + F7) введите номер компьютера, на котором выполняется лабораторная работа. Проверьте работу программы.
4. Проверьте работоспособность программы, когда в качестве второго аргумента функции main() будет использоваться char***argv.
5. Внесите в программу изменения для посимвольного вывода аргументов командной строки.
6. В программе предусмотрите защиту от неправильного ввода данных с клавиатуры.
Пример 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
1. Проверьте работу программы при расположении указанных исполнимых приложений на разных жестких дисках.
2. Проверьте работу программы по всем номерам исполняемых приложений.
3. В программу внесите операцию чтения текстового файла (из блокнота, который откроется после выбора notepad.exe), в нем запишите номер компьютера, на котором выполняется лабораторная работа, специальность обучения (например, АСОИУ) и номер учебной группы.
4. В качестве аргумента командной строки введите команду ping.exe (путь к ней: C:\WINDOWS\system32). Скриншот полученного результата вставьте в отчет лабораторной работы.
5. В качестве аргумента командной строки введите команду qprocess.exe (путь к ней: C:\WINDOWS\system32). Скриншот полученного результата вставьте в отчет лабораторной работы.
Контрольные вопросы
- Какой тип имеют аргументы командной строки?
- Каково основное назначение аргументов командной строки?
- Каким образом разделяются аргументы командной строки?
- К чему приводит инкрементирование второго аргумента функции main() в программе, в которой происходит обращение к этому аргументу?
- Каким образом можно вставить содержимое буфера памяти (например, полный путь к команде notepad.exe или строку из текстового документа) в командную строку операционной системы Windows?