Digamos que tengo esta parte del código. Si el usuario no ingresa los nombres de los archivos como argumentos de línea de comando, quiero preguntarle nuevamente para ingresarlos ahora, pero parece que no puedo tener acceso en argv [1] y argv [2]. Por ejemplo, cuando se ejecuta el primer scanf, se produce un error de segmentación. Pero en este caso, ¿cómo puedo leer los argumentos y colocarlos en argv [1] y argv [2]? ¡Gracias de antemano por tu ayuda!

int main (int argc, char **argv)
{
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", argv[1]);
        printf("file 2: ");
        scanf("%s ", argv[2]);
    }

    printf("%s\n", argv[1]);
    printf("%s\n", argv[2]);

    FILE *file1 = fopen(argv[1], "r");
    FILE *file2 = fopen(argv[2], "r");
}
0
Παναγιώτης Αλημίσης 28 may. 2020 a las 19:24

6 respuestas

La mejor respuesta

Se produce un error de segmentación porque la longitud de la matriz argv se determina cuando el usuario ejecuta el programa. Si ejecuta un programa como este:

./programName

Argv tiene solo 1 elemento de longitud. Es imposible acceder a argv [1] o argv [2] después de eso. Aún así, puede obtener los datos necesarios y guardarlos en variables regulares.

1
Gribek 28 may. 2020 a las 16:40

Colocarlos en argv es el enfoque equivocado. Mucho mejor hacer algo como esto:

int main (int argc, char **argv)
{
    char f1[255];
    char f2[255];
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", f1);
        printf("file 2: ");
        scanf("%s ", f2);
    } else {
        strcpy(f1, argv[1]);
        strcpy(f2, argv[2]);
    }
    FILE *file1 = fopen(f1, "r");
    FILE *file2 = fopen(f2, "r");
}

Debe evitar escribir en argv. Eso es en general una mala idea.

1
klutt 28 may. 2020 a las 16:36

Usted no Como dice la frase popular, cada problema en ciencias de la computación puede resolverse mediante una capa adicional de indirección. En este caso, la indirección es que usted defina una interfaz limpia para abrir un archivo y pasarle un char const*. Pero este puntero no tiene que ser argv[1].

Tienes que colocar mal tu propio búfer (porque ninguno existe) y escribir en él. Usar scanf("%s",...) para este propósito probablemente creará un desbordamiento del búfer, ya que no puede saber de antemano qué tan grande debe ser su búfer.

Editar : cada respuesta que se le dé sugiriendo utilizar char buffer[NUMBER] como el búfer para scanf explotará en su cara .

3
bitmask 28 may. 2020 a las 16:33

Tenga en cuenta que argv[1] y argv[2] solo son válidos si argc >= 3. Por lo tanto, acceder a ellos es, por supuesto, incorrecto.

Luego, si desea leer los argumentos de stdin, debe asegurarse de tener memoria donde se guardan esas cadenas. Puedes usar algo como

char filename1[20], filename2[20];
char *f1, *f2;
if (argc == 3) {
  f1 = argv[1];
  f2 = argv[2];
} else {
  f1 = filename1;
  f2 = filename2;
  /* add code to read into filename1 and filename2 */
}
/* use f1 and f2 */

Puedes ver que solo reservé 20 bytes para cada nombre de archivo, que elegí arbitrariamente. Aquí es crítico no escribir más de 20 bytes en esas matrices (incluido el carácter NUL de terminación), por lo que no debe usar scanf como este.

Puede ver que esto no es realmente sencillo en C, por lo que tampoco hay una respuesta que satisfaga todos los propósitos.

Editar: también asegúrese de no escribir nunca en ninguna memoria argc[...], ya que se suministra desde el sistema. Aunque no está marcado const, preferiría considerarlo como tal.

0
mrksngl 28 may. 2020 a las 16:34

No puede hacer esto porque argv[1] y argv[2] son punteros NULOS (si incluso existen en la matriz), por lo que no puede acceder a ellos.

Necesita abordar el problema de una manera diferente.

En lugar de intentar cambiar los miembros de argv, asígnelos a otras variables que contengan los nombres de los archivos.

int main (int argc, char **argv)
{
    char file1[100], file2[100];
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", file1);
        printf("file 2: ");
        scanf("%s ", file2);
    } else {
        strcpy(file1, argv[1]);
        strcpy(file2, argv[2]);
    }

    printf("%s\n", file1);
    printf("%s\n", file2);

    FILE *file1 = fopen(file1, "r");
    FILE *file2 = fopen(file2, "r");
}

Tenga en cuenta que hice algunas suposiciones sobre la longitud de un nombre de archivo. Ajuste según sea necesario.

1
dbush 28 may. 2020 a las 16:35

Argv se pasa de la consola y usted lo pasa mientras ejecuta su programa.

Primero, debes compilarlo, por ejemplo:

gcc program.c -o program

Y luego ejecutarlo con argumentos, por ejemplo:

./program arg1 arg2

Si desea esperar a que un usuario ingrese parámetros para su programa a través de la consola, debe usar variables regulares.

0
wkkuna 28 may. 2020 a las 16:30