Leer de la entrada estandar linea por linea

Iniciado por Delraich, 5 Julio 2010, 23:57 PM

0 Miembros y 1 Visitante están viendo este tema.

Delraich

Primero q nada hola a todos, empece hace poco a programar en C.. Lo q mas me interesa es programar algoritmos de matematica discreta, y tengo problemas con uno q calcula MaxFlow en un grafo.. con el algoritmo en si no, sino con la entrada estandar.. Quiero q lea desde la entrada estandar, cosas de la siguiente manera:
a b c
donde a, b y c son enteros... Pero quiero q lea mientras una linea sea de ese tipo.. cuando llega algo q no es de ese formato, deberia dejar de leer en la entrada estandar.. entonces para q quede claro, deberia poder poner por ejemplo:
1 2 3
3 2 5
4 5 2
3

En este ejemplo, quiero q tome el 1 2 3, el 3 2 5, el 4 5 2 y q deje de leer cuando vea q la 4ta linea tiene un solo numero...

Otro ejemplo seria
1 2 3
4 5 6
2 4 5 6

Aqui deberia leer 2 lineas, y cortar cuando llega la 3ra porq tiene un entero de mas..
Y tambien tiene q cortar si llega algo asi:

1 2 3
3 4 5
hola

Lee 2 lineas, y luego corta porq llega algo q no tiene nada q ver con el formato...

Probe con scanf pero no logro q corte cuando la linea tiene caracteres de menos.. ya q el scanf se queda esperando a q se completen sus parametros...\
Por otro lado tampoco logro q corte cuando llegan caracteres de mas, ya q los guarda en el buffer para el siguiente scanf...

Asi q si me pueden ayudar, desde ya les agradezco

nicolas_cof

Delraich, bienvenido! te recomendaria leer las Reglas del subforo

Si pones algo del avance que llevas hecho seria mas facil para nosotros poder ayudarte.

Te invito a que pases por estos temas...

https://foro.elhacker.net/programacion_cc/librospapers_c_and_c-t296234.0.html

https://foro.elhacker.net/programacion_cc/lo_que_no_hay_que_hacer_en_cc_nivel_basico-t277729.0.html

Salu10.

Littlehorse

Podrías hacer un arreglo de cadenas e ir leyendo linea a linea, luego convertir los datos relevantes para poder operarlos. Podrías también leer una cadena con toda la expresión, para luego poder tomar los datos relevantes de dicha expresión, convertirlos y operarlos.

Pon el código que llevas hecho a ver si podemos partir de ahí para ayudarte.

Saludos
An expert is a man who has made all the mistakes which can be made, in a very narrow field.

ghastlyX

Puedes leer una línea entera usando
Código (cpp) [Seleccionar]
getline(cin,s);
Donde s es una string.

Luego para parsear la entrada, si sabes que siempre serán números, puedes usar stringstream e ir leyendo desde s y añadiendo en un vector los números. Si no, deberías picar alguna función que compruebe que si es número o no.

En referencia al algoritmo, ¿cuál usas para calcular el Maxflow?

Delraich

Antes q nada, muchas gracias por responder tan rapido...

El programa la verdad es bastante extenso, sobre todo la parte del algoritmo en si.. pero la parte q lee desde la entrada estandar seria algo asi :

Ya cree la estructura donde voy a guardar el network (grafo).. y ahora tengo q agregar lado por lado... esta funcion está en un ciclo.. el ciclo corta cuando el valor de esta funcion es 0.. por eso, esta funcion debe devolver 1 mientras la entrada estandar sea del formato q quiero, y 0 cuando no sea..
La funcion CargarLado se encarga de tomar los 3 enteros (q serian vertice 1 del lado, vertice 2 del lado y capacidad de ese lado) y los introduce en la esctructura del grafo.. si puede cargarlos bien, devuelve 1.. sino, devuelve 0.. El problema aca es q cuando introduzco algo por entrada estandar q tiene caracteres, pero menos de 3 o mas de 3, el programa no corta.. sino q se queda esperando.. yo necesitaria que tome la linea entera como dice Littlehorse, pero la verdad no se como hacerlo


int LeerLado (EstadoNetwork n) {

   res = scanf(" %u %u %u", &c1, &c2, &c3);

 if (res == 3)
 {
   res = CargarLado(n->network,c1,c2,c3);
 }
 else
 {
   res = 0;
 }
 return res;
}


Recien leo la respuesta de ghastlyx, voy a intentar hacerlo asi, pasa q no siempre van a ser numeros, asi q voy a tener q primero ver si son numeros, y si lo son ver si son la cantidad q necesito..
Estoy implementando el algoritmo de Dinic, con el paso bloqueante tambien de dinic..
Luego quizas intente wave, pero necesito poder ingresar los datos del grafo bien primero


Littlehorse

El problema es que lo te menciono ghastlyX  es C++, y según mencionas vos en el post inicial, estas codificando el algoritmo en C.

Declara una cadena, y léela con fgets, luego puedes parsear los datos y operarlos previa validación.

Saludos
An expert is a man who has made all the mistakes which can be made, in a very narrow field.

ghastlyX

No me había fijado que había puesto C, sin STL lo que he dicho como que no xDD.

Por si te sirve de ayuda, te dejo un código del algoritmo de Dinic que tenía hecho, sigue el formato de entrada y salida de este problema:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=10&page=show_problem&problem=761

Código (cpp) [Seleccionar]
/****************************************************************************************/
/* Algoritmo Dinic (usa blocking flows en lugar de caminos aumentativos) Coste: O(V^2E) */
/****************************************************************************************/

#include <iostream>
#include <string.h>
using namespace std;

//Cambiar constantes si es necesario
#define NODOS 100
const int INF = 1000000000;

int adj[NODOS][NODOS], deg[NODOS], cap[NODOS][NODOS], padre[NODOS], f[NODOS][NODOS], MC[NODOS], visto[NODOS];
int n, m; // n = |V|, m = |E|

int Q[NODOS]; //cola
int ebp, esp;

bool bfs(int s, int t) {
    esp = ebp = 0;
    memset(padre, -1, sizeof(padre));
    memset(visto, 0, sizeof(visto));
    visto[s] = 1;
    padre[s] = -2;
    Q[esp++] = s;
    while (ebp != esp) {
        int u = Q[ebp++];
        for (int i = 0; i < deg[u]; ++i) {
            int v = adj[u][i];
            if (cap[u][v] - f[u][v] > 0 and not visto[v]) {
                visto[v] = 1;
                padre[v] = u;
                Q[esp++] = v;
            }
        }
    }
    return visto[t];
}

void mincut(int s) {
    ebp = esp = 0;
    Q[esp++] = s;
    MC[s] = 1;
    while (ebp != esp) {
        int u = Q[ebp++];
        for (int i = 0; i < deg[u]; ++i) {
            int v = adj[u][i];
            if (cap[u][v] - f[u][v] > 0 and not MC[v]) {
                MC[v] = 1;
                Q[esp++] = v;
            }
        }
    }
}

int maxflow(int s, int t) {
    int flow = 0;
    memset(MC, 0, sizeof(MC));
    memset(f, 0, sizeof(f));
    while (bfs(s, t)) {
        for (int i = 0; i < n; ++i) {
            if (cap[i][t] - f[i][t] > 0 and padre[i] != -1) {
                int bot = cap[i][t] - f[i][t];
                for (int v = i, u = padre[i]; u >= 0; v = u, u = padre[u])
                    bot = min(bot, cap[u][v] - f[u][v]);
                if (bot == 0) continue;
                f[i][t] += bot;
                f[t][i] -= bot;
                for (int v = i, u = padre[i]; u >= 0; v = u, u = padre[u]) {
                    f[u][v] += bot;
                    f[v][u] -= bot;
                }
                flow += bot;
            }
        }
    }
    mincut(s); //MC[u] == 1 <=> u esta en la particion de s
    return flow;
}

int main() {
    int net = 1;
    while (cin >> n and n > 0) {
        memset(deg, 0, sizeof(deg));
        memset(cap, 0, sizeof(cap));
        int s, t;
        cin >> s >> t >> m;
        s--; t--;
        for (int i = 0; i < m; ++i) {
            int a, b, c;
            cin >> a >> b >> c;
            --a; --b;
            if (cap[a][b] == 0) {
                adj[a][deg[a]++] = b;
                adj[b][deg[b]++] = a;
            }
            cap[a][b] += c;
            cap[b][a] += c;
        }
        cout << "Network " << net++ << endl;
        cout << "The bandwidth is " << maxflow(s,t) << "." << endl << endl;
    }
}

do-while

#7
¡Buenas!

para poder leer linea por linea puedes declarar una vector de caracteres de dimension "algo grande", y leerlo con fgtes:

#define LINEA_MAX 256

char linea[LINEA_MAX];

/* leemos mientras quede informacion -> mientras linea[strlen(linea)]!='\n'
ya que fgets obtiene informacion hasta (MAX_LINEA - 1) o hasta que encuentra un salto de
linea (lo almacena como ultimo caracter de la cadena) o hasta que encuentra un EOF */
do{
   fgets(linea,LINEA_MAX,stdin);
   /* y ahora con la informacion haces lo que quieras.
   RECOMENDACION: usa strtok para obtener las distintas partes separadas por espacios */
}while(linea[strlen(linea) - 1] != '\n'); /* Al ser '\n' el ultimo caracter, ya no queda nada en la entrada */


El resto te lo dejo a ti. Tendras que estudiar las funciones de manejo de cadenas de stringh, de stdlibh, y seguramente tambien las de stdio.h.

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

Delraich

De nuevo gracias por la ayuda, ya me voy a tomar un tiempo y leer el algoritmo q posteaste ghasltyx, ahora voy a intentar tomar linea por linea como me recomendaron, y ver como parseo la info... luego les cuento q tal me fue

MIG80

#9
Bueno...talvez esto te solucione el problema con la entrada...


int leer3ent(int *c1,int *c2,int *c3)
{
 int res;
 char remanente[1000],lineaentrada[1000];
 
 fgets(lineaentrada,1000,stdin);
 fflush(stdin);
 res=sscanf(lineaentrada,"%u %u %u%s",c1,c2,c3,remanente);
 return (res==3)?1:0;
}

int LeerLado(EstadoNetwork n)
{
 res=leer3ent(&c1,&c2,&c3);
 if(res)
   res=CargarLado(n->network,c1,c2,c3);
 return res;
}


Saludos.