(C ++) Preguntas muy básicas sobre la sintaxis

Principiante de C ++ aquí. Tengo algunas preguntas básicas. En int main( int argc, char *argv[] )

  1. ¿Cómo es char *argv[] se supone que debe ser leído (o hablado a los humanos)?
  2. ¿Es posible borrar / borrar contenido (s) específico (s), carácter (s) en este caso, de dicha matriz? Si es así, ¿cómo?
  3. ¿Se puede cambiar el tamaño de las matrices? Si es así, ¿cómo?
  4. ¿Cómo puedo copiar todo el contenido de argv[] a un solo std::string ¿variable?
  5. ¿Hay otras formas de determinar el número de palabras / parámetros in argv[] sin argc? Si es así, ¿cómo? (*)

Agradecería explicaciones (no código) para los números 2-5. Descubriré el código yo mismo (aprendo más rápido de esta manera).

Gracias de antemano.

(*) Yo sé eso main(char *argv[]) es ilegal. Lo que quiero decir es si hay al menos una forma que no implique argcen absoluto, como en las siguientes expresiones:

for( int i = 0; i < argc; ++i ) {
    std::cout << argv[i] << std::endl;
}

y

int i = 0;    
while( i < argc ) {
    std::cout << argv[i] << std::endl;
    ++i;
}

Or

int i = 0;
do { 
     std::cout << argv[i] << std::endl;
     ++i; } while( i < argc );

preguntado el 10 de mayo de 11 a las 13:05

debe ser char * argv [], no char ** argv []. Se lee como "argv es una matriz de punteros a char" -

Quiere decir int main( int argc, char *argv[] ) -

Si, lo siento. Está arreglado ahora. Es posible que la pregunta n. ° 1 ya no sea válida. Pero me voy de ahí. -

Es bien *argv[] or **argv pero no la mezcla que le diste. Empiece por intentar averiguar cuál es la diferencia exacta y por qué es importante.

7 Respuestas

1) Se supone que es char **argv or char *argv[] cual es a pointer to an array of characters más comúnmente conocido como an array of strings

2) Cuerda C es la biblioteca estándar para manipular cadenas C (matrices de caracteres). No puede cambiar el tamaño de una matriz sin reasignar, pero puede cambiar el contenido de los elementos haciendo referencia a ellos por índice:

for(int i = 0; i < argc; ++i)
{
   //set all the strings to have a null character in the
   //first slot so all Cstring operations on this array, 
   //will consider it a null (empty) string
   argv[i] = 0;
}


3) Técnicamente no, sin embargo, se pueden eliminar y luego reasignar:

int *array = new int[15]; //array of size 15
delete[] array;
array = new int[50]; //array of size 50

4) Esta es una forma:

string *myString;
if(argc > 0)
{
   myString = new string(argv[0]);
   for(int i = 1; i < argc; ++i)
      myString->append(argv[i]);
}

5) Sí, según Cubbi:

POSIX especifica el puntero nulo final para argv; consulte, por ejemplo, "La aplicación debe asegurarse de que el último miembro de esta matriz sea un puntero nulo". a pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html

Lo que significa que puedes hacer:

char *val = NULL;
int i = 0;
do
{
   val = argv[i++]; //access argv[i], store it in val, then increment i
   //do something with val
} while(val != NULL); //loop until end of argv array

contestado el 10 de mayo de 11 a las 18:05

En realidad, no es solo POSIX, el estándar C ++ exige que: "El valor de argv [argc] sea 0". en 3.6.1 [basic.start.main] / 2 - Cubbi

Gracias. Aunque desearía que no incluyeras códigos. Has arruinado la diversión de resolver los acertijos de un nuevo idioma (nuevo para mí, por cierto). :) - Corellis

@Corellis Lo siento, me gusta dar ejemplos en caso de que lo que digo no sea claro, pero prometo que no les dije todo lo que se puede hacer para responder a todas sus preguntas. Hay muchas formas de resolver diferentes problemas. - Chad

  1. Es una serie de sugerencias para char.

  2. Más o menos, puedes sobrescribirlos.

  3. Solo copiando a una nueva matriz.

  4. Escriba un bucle y agregue cada argv [i] a una cadena de C ++.

  5. La mayoría de las implementaciones terminan la matriz con un puntero NULL. No recuerdo si esto es estándar o no.

contestado el 10 de mayo de 11 a las 18:05

las cadenas terminan con un puntero NULL, pero las matrices no. - Chad

¡Buena velocidad de escritura! POSIX especifica el puntero nulo final para argv; consulte, por ejemplo, "La aplicación debe asegurarse de que el último miembro de esta matriz sea un puntero nulo". a pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html - Cubbi

@Chad Lo son si alguien (en este caso los implementadores del compilador) les pone un NULL. - usuario2100815

@unapersson Obviamente, si alguien pone uno ahí, entonces hay uno. Lo que estoy diciendo es que no puede asumir que hay uno. (excepto en el caso de argv) - Chad

En realidad, no es solo POSIX, el estándar C ++ también lo exige: "El valor de argv [argc] será 0". en 3.6.1 [basic.start.main] / 2 - Cubbi

char **argv[]

Está Mal. Debería ser char **argv or char *argv[], no una mezcla de ambos. Y luego se convierte en un puntero a puntero a caracteres, o más bien un puntero a c-strings, es decir, una matriz de c-strings. :) cdecl.org también es muy útil en cosas como esta.
Entonces, para el acceso, claro. Solo, bueno, accede a él. :) argv[0] sería la primera cadena, argv[3] sería la cuarta cuerda. Pero no recomendaría totalmente reemplazar cosas en una matriz que no sea suya o que conozca las partes internas.
En el cambio de tamaño de la matriz, ya que está escribiendo C ++, use std::vector, que hace todas las cosas complicadas de asignación por usted y es realmente seguro. Generalmente, depende del tipo de matriz. Matrices asignadas dinámicamente (int* int_arr = new int[20]) lata, matrices estáticas (int int_arr[20]) no puedo.
Para copiar todo en argv en una sola std::string, recorra la matriz y agregue cada cadena c a su std::string. Sin embargo, no lo recomendaría, prefiero tener un std::vector<std::string>, es decir, una matriz de std::strings, cada uno con uno de los argumentos.

std::vector<std::string> args;
for(int i=0; i < argc; ++i){
  args.push_back(argv[i]);
}

En su último punto, ya que la norma exige argv ser terminado por un NULL puntero, es bastante fácil.

int myargc = 0;
char** argv_copy = argv;
while(++argv_copy)
  ++myargc;

La while(++argv_copy) primero incrementará el puntero de la matriz, dejándolo apuntar al siguiente elemento (por ejemplo, después de la primera iteración apuntará a c-string # 2 (argv[1])). Después de eso, si el puntero se evalúa como falso (si es NULL), luego el bucle frena y tienes tu myargc. :)

contestado el 10 de mayo de 11 a las 18:05

Gracias por tu respuesta detallada. Lástima que no se me permita aceptar más de una respuesta. - Corellis

  1. Varias opciones: matriz de puntero a char O matriz de C-string.

  2. Puede asignar caracteres particulares para borrarlos, o puede desplazar el resto de la matriz hacia adelante para "borrar" caracteres / elementos.

  3. No se puede cambiar el tamaño de las matrices de estilo C normales. Si necesita una matriz de tamaño variable en C ++, debe usar std::vector.

  4. Tendrá que iterar sobre cada uno de los elementos y agregarlos a una cadena. Esto se puede lograr con algoritmos C ++ como copy junto con un ostream_iterator usado en un ostringstream.

  5. No. Si hay sí estaba de tal manera, no habría necesidad de argc. EDITAR: Aparentemente para argv solamente el elemento final de la matriz es un puntero nulo.

contestado el 10 de mayo de 11 a las 19:05

  1. Se dice como "matriz de punteros a punteros a carácter" (tenga en cuenta que esta no es la firma de la función principal, que es int argc, char **argv or int argc, char *argv[] - que es equivalente).
  2. La matriz argv es modificable (falta de constante). Sin embargo, es ilegal escribir más allá del final de una de las cadenas o extender la matriz; si necesita extender una cadena, cree una copia de ella y almacene un puntero en la matriz; si necesita extender la matriz, cree una copia de la matriz.
  3. No se pueden cambiar de tamaño per se, sino que se pueden reinterpretar como una matriz más pequeña (lo que explica la respuesta a la última pregunta).
  4. Perderá información de esta manera: argv es una matriz de matrices, porque los argumentos individuales ya se han separado para usted. Puede crear una lista de cadenas usando std::list<std::string> args(&argv[1], &argv[argc]);.
  5. Realmente no. La mayoría de los sistemas tienen argv NULL rescindido, pero eso no es una garantía.

contestado el 10 de mayo de 11 a las 18:05

  1. char *argv[] se puede leer como: "una matriz de punteros a char"

    char **argv se puede leer como: "un puntero a un puntero a char"

  2. Sí, puede modificar el argv formación. Por ejemplo, argv[0][0] = 'H' modificará el primer carácter del primer parámetro. Si por "borrar / borrar" te refieres a eliminar un carácter de la matriz y todo cambia automáticamente: no hay una forma automática de hacerlo, tendrás que copiar todos los caracteres uno por uno hacia la izquierda (incluido el Terminación NULA)

  3. No, no se puede cambiar el tamaño de las matrices. Deberá crear uno nuevo y copiar el contenido

  4. ¿Cómo quiere representar TODAS las cadenas de parámetros como 1 std :: cadena? Tendría más sentido copiarlo en una matriz de std :: strings

  5. No, no hay ninguna indicación especial de la última entrada en la matriz. necesitas usar argc

Respondido el 20 de junio de 20 a las 12:06

Me gusta tu respuesta a la pregunta no. 2. Wish SO me permitió aceptar varias respuestas. - Corellis

Array en C / C ++ no es un objeto, sino solo un puntero al primer elemento de la matriz, por lo que no puede simplemente eliminar o insertar valores.

Contestando tus preguntas:

  1. char *argv[] se puede leer como 'matriz de punteros a char'
  2. Es posible, pero implica manipulaciones directas con datos en la memoria, como copiar y / o mover bytes.
  3. No. Pero puede asignar una nueva matriz y copiar los datos necesarios
  4. Copiando manualmente cada elemento en std::string objeto
  5. No.

Como resumen: C ++ es un lenguaje de nivel mucho más bajo de lo que piensas.

contestado el 10 de mayo de 11 a las 18:05

No hay lenguaje C / C ++, aunque las matrices son esencialmente las mismas tanto en C como en C ++. En ninguno de los dos idiomas una matriz es solo un puntero, aunque tienden a descomponerse en punteros con el uso. Tanto en C99 como en C ++, argv[argc] se garantiza que es el puntero nulo, por lo que puede usarlo para indicar el número de miembros de argv. C ++ tiene elementos de bajo nivel, en su mayoría tomados de C, pero los programas modernos de C ++ tienden a no usarlos. - David Thornley

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.