ARGUMENTOS EN LA LÍNEA DE COMANDOS
Sin embargo, estos programas pueden cambiar el modo en que se ejecutan si es que permiten colocar parámetros en la línea de comandos. Este es el caso de la orden "dir", que permite colocarlos; por ejemplo, la orden puede darse como "dir x*" o "dir x* /oe". En el primer caso aparecerán sólo los archivos cuyos nombres empiecen con la letra "x" y en el segundo los archivos que empiecen con "x" pero ordenados por su extensión. Las firguras siguientes muestran este concepto:
ARGUMENTOS DE LA FUNCIÓN main
Para que un programa pueda comportarse de ese modo, su módulo principal debe ser capaz de recibir parámetros. En el caso del C/C++, es la función main la que puede recibir estos parámetros a través de la línea de comandos del sistema operativo.
Para poder ingresar parámetros a un programa en C/C++ se debe modificar el encabezado de la función main. La sintaxis que se debe seguir es rigurosa, la cantida de parámetros y el tipo de éstas estás ya está dado y no se puede modificar. Esto quiere decir que no se puede elegir el tipo y cantidad de parámetros que tendrá.
A continuación se muetra la forma cómo se debe seguir esta sintaxis:
int main(int numArg, char *arg[]) | ó, | int main(int numArg, char **arg) |
{ ... | { ... | |
} | } |
La función main sólo puede terner dos parámetros, el primero es un parámetro por valor de tipo entero, en este caso numArg, y el segundo es un doble puntero char (o si lo prefiere un arreglo de punteros a char), en este caso arg, que también es un parámetor por valor.
Cuando se ejecute el programa desde la línea de comandos del sistema operativo, si se quiere introducir información al programa por medio de los parámetros, se debe colocar el nombre del programa seguido de una serie de palabras separadas por espacios en blanco. Por ejemplo:
Cada una de las palabras que se colocan en la línea de comandos, incuyendo el nombre del programa (en algunos compiladores el nombre del programa incluye su ruta de acceso), son tomados por el mismo programa y con ellas se arma una estructura como la que se muestra a continuación:
La estructura de datos que se forma es un arreglo de punteros, cuyos elementos apuntan a espacios de memoria en donde se han colocado las palabras que ingresaron a través de la línea de comandos del sistema operativo, este arreglo es referenciado por el argumento agr.
Luego, el sistema cuenta la cantidad de elementos que se crearon en el arreglo y coloca ese valor en el argumento numArg.
Finalmente, el número de elementos del arreglo y la direecón de éste; son recibidos por la función main, para emplearlos como mejor le convenga.
El siguiente programa muestra, de manera muy simple, como se pueden emplear los parámertos ingresados desde la línea de comandos del sistema operativo (el programa se guardará con el nombre de paramMain.cpp):
#include <stdio.h>
int main (int numArg, char ** arg) {
// En este punto los argumentos ya tienen la información que viene de la línea de comandos
int n;
// Imprimimos el contenido de la estructura
printf("Lista de parametros ingresados: \n");
for ( n = 0; n < numArg; n++)
printf("%2d) %s\n", n, argv[n]);
return 0;
}
Cuando se ejecute este programa desde la línea de comandos, se obtendrá un resultado similar al que se muestra a continuación:
En el ejemplo se pudo apreciar la manera como fue posible capturar las palabras colocadas a continuación del nombre del programa en el momento que lo ejecutamos. Una vez capturadas estas palabras, el programa pudo manipularlas a su antojo, en este caso sólo se les volvió a imprimir de una manera ordenada.
En el siguiente ejemplo se tratará de mostrar esta propiedad de los programas en C/C++ de una manera más interesante, se trata de escribir un programa que permita evaluar una expresión postfija o polaca. Una expresión postfija es de la forma: 34.57 56.83 -23.67 + x 10.9 /, esta expresión es equivalente a expresión entrefija 34.57 x (56.83 + -23.67) / 10.9 . Dicho en otras palabras, las expresiones postfijas colocan primero los operandos y luego el operador, este tipo de expresión tiene como característica que no requiere de paréntesis para indicar la precedencia de las operacioens y por lo tanto es más simple su implementación en un programa.
La idea, para este ejemplo es que la expresión sea ingresada através de la línea de comandos. Entonces, la ejecución del programa deberá verse como se muestra a continuación:
La solución para este problema se centra en el uso de una pila de datos. Se analiza la expresión de izquierda a derecha y cada vez que se encuentre un operando, éste se apila; cuando se encuentre un operador entonces se desapilan dos valores y se evalua la opración con los dos valores desapilados y el operador encontrado. El resultado se vuelve a apilar. Cuando se termine de evaluar la expresión, el resultado se encontrará en la cima de la pila.
A continuación se presenta el código que resuelve este problema:
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
int esOperando(char **, int);
enum Logico {NO, SI}; //NO = 0, SI = 1
int main(int argc, char** argv) {
float pila[20], *top, num1, num2;
Logico seguir = SI; //Verifica si la expresión es correcta
int i = 1;
top = pila;
// analizamos uno a uno los argumentos de la línea de comandos
while (--argc > 0 && seguir) {
if (esOperando(argv, i))
*top++ = atof(argv[i]); // apilamos el argunmento
// el ++ se aplica a top, y no a *top
else { // si es un operador, desapilamos dos operandos y los evaluamos
if (top != pila) { // si la pila no está vacía
num2 = *--top; // el -- se aplica a top, y no a *top
if(top != pila)
num1 = *--top;
else // hubo un error en la expresión
seguir = NO;
}
else // hubo un error en la expresión
seguir = NO;
if (seguir) { // si no hubo error en la expresión
switch (argv[i][0]) { // apilamos el resultado
case '+': *top++ = num1 + num2;
break;
case '-': *top++ = num1 - num2;
break;
case 'x': *top++ = num1 * num2;
break;
case '/': *top++ = num1 / num2;
break;
default: seguir = NO;
}
}
}
i++;
}
if(seguir)
printf("Resultado= %f\n", pila[0]);
else
printf("Error en los datos\n");
return (EXIT_SUCCESS);
}
int esOperando(char **argv, int i) {
// un operando es un número real positivo o negativo
if (isdigit(argv[i][0]) || (argv[i][0] == '-' && isdigit(argv[i][1])))
return 1;
return 0;
}