0

Mi problema es el siguiente:

void read () {
        string name, ciudad;
        int cont = 0;
        ifstream read;
        reader.open ("usuarios.txt", ios::out | ios::in);
        if (lectura.is_open())
        {    
            while (!reader.eof())
            {
                reader >> name;
                reader >> ciudad;
                usuarios[cont].name = name;
                usuarios[cont].ciudad = ciudad;
                cont ++;
            }
        }
        else
        {
            cout << "¡Error! El archivo no pudo ser abierto." << endl;
        }
        lectura.close();
    }

Por ejemplo si el archivo de texto es:

Carlos Juan Griego

John San Antonio

las variables quedarían así:

usuario1 = carlos juan

usuario2 = john san

Porque cada vez que encuentra un espacio lo interpreta como pasar a la siguiente variable o lee la siguiente variable.

Lo ideal para esto es usar una bandera y el archivo de texto sería así:

Carlos#Juan Griego

John#San Antonio

Así cada vez que consiga un "#" asigna a una la variable indicada para evitar el problema de los espacios.

Un ejemplo de ello en JAVA:

public void reader(people personas[]) {
    try {
        File f = new File("agenda.txt");
        if (f.exists()) {
            FileReader fr = new FileReader(f);
            BufferedReader br = new BufferedReader(fr);
            String linea;
            int i = 0;
            while (((linea = br.readLine()) != null) && (i < 10)) {
                String[] contacto = linea.split("%"); //Se crea un array de string y se signa a cada posición al encontrar la bandera.
                personas[i] = new people(contacto[0], contacto[1], contacto[2], Integer.parseInt(contacto[3]));
                i++;
            }
        } else {
        }
    } catch (Exception e) {
        System.out.println(e);
        System.out.println("Agenda no existente.");
    }
}

En el ejemplo anterior la bandera usada es el "%".

Otro ejemplo de mi pregunta:

Supongamos que el archivo de texto es el siguiente:

carlos guevara 28 san antonio

jesús snow 88 cuerna vaca

Las variables se leen así:

nombre: carlos

edad: guevara

ciudad: 28

(en este ejemplo carlos guevara es el nombre, 28 la edad, san antonio la ciudad) Así está escrito el archivo de texto. EL problema es que cuando el programa lee la cadena cada espacio es una variable ese es el problema.

Una solución sería:

carlos guevara#28#san antonio

jesús snow#88#cuerna vaca

La manera que se debe guardar en cada variable es:

nombre: carlos guevara

edad: 28

ciudad: san antonio

(nótese que para eso son las bandera para separar cada variable)

Así se separa cada variable a momento de leer, (son las llamadas banderas).

Como ya veran mi problema es que no hayo la manera de hacerlo en C++(estoy aprendiendo el lenguaje), de hacerlo así con las banderas que divida el string al encontrar la bandera y asignarlo a cada variable.Espero que me comprendan mi pregunta.Necesito que me ayuden en esta duda que tengo, porfavor. :D

Cookie Rabbit
  • 151
  • 2
  • 4
  • 19
  • Lo que podrías hacer es crear un objeto llamado persona, por ejemplo, y que este objeto contenga nombre y apellido así los cambios en tu código serían mínimos y conseguirías lo que pretendes. – santigamo Apr 19 '17 at 22:53
  • No te comprendo lo que me quieres decir. Lo que busco que lea el archivo de texto y que asigne a cada variable al encontrar la bandera("#").Gracias por comentar. :D – Cookie Rabbit Apr 19 '17 at 22:58

2 Answers2

1

veo que tratas de itemizar una cadena respecto al espacio o un separador {#, %, etc}. Mi ejemplo funciona bajo espacios.

Te recomiendo usar: strtok

http://www.cplusplus.com/reference/cstring/strtok/

El código de modo muy basico quedaria así:

void read () {
    char ln[500], ciudad;
    int cont = 0;
    ifstream read;
    char *info[] = {"Nombre: ", "Apellido: ", "Edad: "};
    int pt = 0; 
    char * pch;

    read.open ("usuarios.txt", ios::out | ios::in);

    if (read.is_open())
    {    
        while (!read.eof())
        {
            // Obtiene linea del archivo
            read.getline(ln, 500);

            // Itemize la cadena para obtener cada uno de los elementos necesarios
            pch = strtok (ln," ");
            pt = 0;
            while (pch != NULL)
            {
                // Muestro el contenido de info para ver que los campos se obtiene de modo adecuado
                // pero tu deberias hacer el casteo correspondiente y asignar a variables.
                cout<< info[pt] << pch << endl;
                pch = strtok (NULL, " ");

                pt ++;
                if(pt > 2)
                {
                    // En caso de que la cadena contengas mas campos de los que puedo procesar
                    break;
                }
            }

            cont ++;
        }
    }
    else
    {
        cout << "¡Error! El archivo no pudo ser abierto." << endl;
    }

    read.close();
}

Espero te sea de ayuda.

Saludos.

n-angel
  • 21
  • 2
0

Desconozco como podrías hacer lo que muestras de java en C++, pero como solución a tu problema, como te comente, es crear un objeto llamado de la forma que desees.Este objeto contendrá el nombre y apellido, y luego devolverlo a la variable name como deseas.

Como resultado tu código quedaría tal que:

void read () {
    string name, ciudad;
    int cont = 0;
    ifstream read;
    reader.open ("usuarios.txt", ios::out | ios::in);
    if (lectura.is_open())
    {    
        while (!reader.eof())
        {
            reader >> objeto.nombre;
            reader >> objeto.apellido;
            reader >> ciudad;
            name= objeto.nombre+" "+objeto.apellido;
            usuarios[cont].name = name;
            usuarios[cont].ciudad = ciudad;
            cont ++;
        }
    }
    else
    {
        cout << "¡Error! El archivo no pudo ser abierto." << endl;
    }
    lectura.close();
}

El único requisito es que las 3 variables sean string.

santigamo
  • 455
  • 1
  • 4
  • 14