Discussion:
entrada de datos
(demasiado antiguo para responder)
josgalo
2003-12-01 20:24:52 UTC
Permalink
Hola a ***@s

Estoy haciendo una práctica en C para el instituto. Trata de mejorar el
cmd de windows con algunas funcionalidades que tiene el shell de linux.
Para mi es complicadísimo aunque algo he conseguido; pero el caso es que
una función del programa no hace lo que quiero (mejor dicho no sé cómo
hacerlo ) . Utilizando _getche() y un vector que recogerá los caracteres
me gustaría poder borrarlos y sobreescribirlos si hiciera falta. Lo que
me he hecho borra y sobreescribre todo menos el elemento 0 y lo que
imprime por pantalla tampoco sé como borrarlo.
Os copio el código:

#include <stdio.h>
#include <conio.h>

void main()
{
int i=0, f=0;
char car;
char frase[100];
do {
car=_getche();
/***********para borrar pero no consigo
que borre el elemento[0]*******/
if (car==8 && i!=0) frase[i-1]=NULL;
else if (car==8 && i==0) frase[0]=NULL;
if (car!=13) frase[i]=car;
else frase[i]='\0'; //si pulsa ENTER
i++;
}
while (car!=13);
//if (frase[0]=='\0') //frase[0]=NULL; //printf("Hay solo un
//enter\n");

printf("\n\n");
for (f=0; f<i-1; f++)
/************muestra el valor decimal del carácter introducido*********/
printf("%d\n", frase[f]);
printf("%s\n", frase);
}


Ah, también me sería de ayuda saber el valor decimal de la tecla Ins, no
lo encuentro en la tabla ASCII.

Gracias por la ayuda que me podais dar.

P.D: Tendría que a ver ido más a clase :-(
Showtime
2003-12-02 11:59:56 UTC
Permalink
Hola.
Post by josgalo
Estoy haciendo una práctica en C para el instituto. Trata de mejorar el
cmd de windows con algunas funcionalidades que tiene el shell de linux.
Para mi es complicadísimo aunque algo he conseguido; pero el caso es que
...
Yo he tenido que hacer algo parecido para que el usuario pudiera introducir
su nombre en modo gráfico usando la BGI de Borland. Te pego el código, igual
te sirve de algo. A las variables alto, ancho y las constantes MAXX, MAXY no
les hagas caso, son sólo para dibujar un rectángulo alrededor del texto:

//--------
int acabado=0,contador=0;
char buffer[18],concatenado[30];

while (acabado == 0)
{
switch (c = getch())
{
case 13:
//si el usuario pulsa intro, se termina el bucle
acabado = 1;
break;
case '\b':
//si el usuario pulsa retroceso, se actualiza la cadena donde se
almacena el texto y se redibuja
if (strlen(buffer) > 0)
{
buffer[--contador] = '\0';
strcpy(concatenado, "Nombre: ");
strcat(concatenado, buffer);
setcolor(WHITE);
setfillstyle(SOLID_FILL, BLUE);
bar3d(MAXX / 2 - ancho / 2 - 1, MAXY / 2 - alto / 2 - 1,
MAXX / 2 + ancho / 2 + 1, MAXY / 2 + alto / 2 + 1, 0, 1);
outtextxy((MAXX / 2 - ancho / 2), MAXY / 2 - alto / 2,
concatenado);
}
break;
default:
if ((isalnum(c)) && (strlen(buffer) < 18))
{
//si la tecla pulsada es un carácter alfanumérico y no se ha llenado aún
la cadena, se le añade el carácter y se redibuja
buffer[contador++] = c;
buffer[contador] = '\0';
strcpy(concatenado, "Nombre: ");
strcat(concatenado, buffer);
setcolor(WHITE);
setfillstyle(SOLID_FILL, BLUE);
bar3d(MAXX / 2 - ancho / 2 - 1, MAXY / 2 - alto / 2 - 1,
MAXX / 2 + ancho / 2 + 1, MAXY / 2 + alto / 2 + 1, 0, 1);
outtextxy((MAXX / 2 - ancho / 2), MAXY / 2 - alto / 2,
concatenado);
}
break;
}
}
//--------

El valor de la tecla insert según un archivo que tengo es 0x5200.

saludos
Fernando Arbeiza
2003-12-02 15:51:18 UTC
Permalink
Post by josgalo
Estoy haciendo una práctica en C para el instituto. Trata de mejorar el
cmd de windows con algunas funcionalidades que tiene el shell de linux.
Para mi es complicadísimo aunque algo he conseguido; pero el caso es que
una función del programa no hace lo que quiero (mejor dicho no sé cómo
hacerlo ) . Utilizando _getche() y un vector que recogerá los caracteres
me gustaría poder borrarlos y sobreescribirlos si hiciera falta. Lo que
me he hecho borra y sobreescribre todo menos el elemento 0 y lo que
imprime por pantalla tampoco sé como borrarlo.
¿Seguro que necesitas complicarte tanto y utilizar librerías no
portables? Mira a ver si algo tan sencillo como esto te sirve:

/*****************/

#include <stdlib.h>
#include <stdio.h>

/* Evita los números mágicos. Ponles un nombre, y así evitas problemas si
* tienes que cambiarlos por cualquier cosa. */
#define FRASE_MAX 100

/* Lo mejor es que main devuelva un int. Es la única forma portable */
int main(void) {
/* Si vas a recorrer un array (o manejar tamaños de memoria) lo
* mejor es utilizar una variable size_t */
size_t i;

char frase[FRASE_MAX];

if (fgets(frase, FRASE_MAX, stdin) == NULL) {
/* Comprueba si fgets devuelve NULL por un error o por haber
* llegado al final del fichero */
if (ferror(stdin)) {
fputs("Error en fgets\n", stderr);
exit(EXIT_FAILURE);
}
puts("Fin de fichero");
exit(EXIT_SUCCESS);
}

/* Utiliza la familia printf para salida formateada. Para imprimir
* cadenas de caracteres tienes puts y compañía */
fputs("\n\n", stdout);
for (i = 0; i < strlen(frase); i++) { printf("%d\n", frase[i]); }

puts(frase);

exit(EXIT_SUCCESS);
}

/*****************/
Post by josgalo
Ah, también me sería de ayuda saber el valor decimal de la tecla Ins, no
lo encuentro en la tabla ASCII.
Tú mismo lo has dicho, Ins es una tecla, y ASCII es una codificación de
caracteres. La forma de detectar la pulsación de Ins depende de cómo lo
trate la consola de tu sistema. Mi consejo es que preguntes en el grupo
es.comp.os.ms-windows.programacion que sabrán aconsejarte mejor.

<OT>
De todas formas, tengo entendido que getch() devuelve 0 cuando se
pulsa alguna de las teclas especiales, y puede saberse cuál en la
siguiente llamada de getch. Puedes hacerte un programita para
conocer el valor que devolverá getch() en ese caso.
</OT>

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Martin J. Sanchez
2003-12-03 01:30:13 UTC
Permalink
Post by Fernando Arbeiza
Post by josgalo
Estoy haciendo una práctica en C para el instituto. Trata de mejorar el
cmd de windows con algunas funcionalidades que tiene el shell de linux.
Para mi es complicadísimo aunque algo he conseguido; pero el caso es que
una función del programa no hace lo que quiero (mejor dicho no sé cómo
hacerlo ) . Utilizando _getche() y un vector que recogerá los caracteres
me gustaría poder borrarlos y sobreescribirlos si hiciera falta. Lo que
me he hecho borra y sobreescribre todo menos el elemento 0 y lo que
imprime por pantalla tampoco sé como borrarlo.
¿Seguro que necesitas complicarte tanto y utilizar librerías no
Voy a insistir un poco mas ;-)

C se usa sobre todo en programacion de sistemas de bajo/medio nivel.
Por tanto es logico usar librerias no estandar, y como ves no hay
forma de hacer un simple editor usando exclusivamente la libreria
estandar
Post by Fernando Arbeiza
...
/* Si vas a recorrer un array (o manejar tamaños de memoria) lo
* mejor es utilizar una variable size_t */
size_t i;
Esta regla no me parece aconsejable para utilizarla sistematicamente.

En particular los recorridos hacia atras se complican innecesariamente
y obtendras sorpresas desagradables en expresiones como:
for( i=n; i>=0; i--)
...
}

Un saludo,
Martin.
Fernando Arbeiza
2003-12-03 09:25:00 UTC
Permalink
On Wed, 03 Dec 2003 02:30:13 +0100, Martin J Sanchez
Post by Martin J. Sanchez
Post by Fernando Arbeiza
¿Seguro que necesitas complicarte tanto y utilizar librerías no
Voy a insistir un poco mas ;-)
Insiste, insiste, el debate es enriquecedor.
Post by Martin J. Sanchez
C se usa sobre todo en programacion de sistemas de bajo/medio nivel.
Por tanto es logico usar librerias no estandar, y como ves no hay
forma de hacer un simple editor usando exclusivamente la libreria
estandar
Yo creo que ha dicho que quiere hacer un intérprete de comandos y, para
hacer uno sencillo, puede hacerse perfectamente con funciones estándar.
Además, meter la conio librería esa :-P en un curso de introducción a C
no creo que sea lo más apropiado.

Si quiere hacer en editor, tienes razón que sólo con las funciones
estándar quedaría muy poco intuitivo. Pero no digas que no hay forma,
que ed, sed y ex pueden hacerse con funciones estándar (vale, es un poco
de trampa, no es lo que tenías en mente cuando dijiste editor ;-)
Post by Martin J. Sanchez
Post by Fernando Arbeiza
/* Si vas a recorrer un array (o manejar tamaños de memoria) lo
* mejor es utilizar una variable size_t */
size_t i;
Esta regla no me parece aconsejable para utilizarla sistematicamente.
Mi intención no era postular una regla, ni mucho menos ;-) Pero sigo
pensando que es lo mejor (en cada caso se verá, pero en este seguro).
Sabes que tienes todo el rango cubierto, algo que no tiene por qué
suceder con otros tipos enteros.
Post by Martin J. Sanchez
En particular los recorridos hacia atras se complican innecesariamente
for( i=n; i>=0; i--)
...
}
Hombre, sorpresa, sorpresa, estoy seguro que a ti no te sorprende :-)
Pero después de algo tan desagradable como eso, seguro que tienes
cuidado con los rangos de las variables, que lo que aprendes a las duras
se queda mejor.

De todas formas, la sorpresa te la puedes llevar utilizando enteros.
Supongamos INT_MAX == 32767 y SIZE_MAX == 65535:

int i;
#define SIZE 34000
int array[SIZE]

/* ... */

for (i = 0; i < SIZE; i++) { /* ... */ }

Te puedes llevar tantas sorpresas que tienes razón que sólo existe lo
mejor en cada caso particular.

Saludos.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
josgalo
2003-12-05 23:54:12 UTC
Permalink
Gracias a todos por contestar. No puedo aprovechar como debiera vuestra
ayuda y opiniones porque soy bastante novato pero me ha servido de
mucho. Os lo agradezco.

Contesto con lo que buenamente sé
Post by Showtime
Post by josgalo
Estoy haciendo una práctica en C para el instituto. Trata de mejorar el
cmd de windows con algunas funcionalidades que tiene el shell de linux.
Para mi es complicadísimo aunque algo he conseguido; pero el caso es que
una función del programa no hace lo que quiero (mejor dicho no sé cómo
hacerlo ) . Utilizando _getche() y un vector que recogerá los caracteres
me gustaría poder borrarlos y sobreescribirlos si hiciera falta. Lo que
me he hecho borra y sobreescribre todo menos el elemento 0 y lo que
imprime por pantalla tampoco sé como borrarlo.
Yo he tenido que hacer algo parecido para que el usuario pudiera
introducir su nombre en modo gráfico usando la BGI de Borland. Te pego
el código, igual te sirve de algo.
Gracias, tu código me ha hecho pensar en usar una sentencia switch
similar para manejar todas las opciones (sobretodo comandos del shell)
que tendré que tratar.
Post by Showtime
¿Seguro que necesitas complicarte tanto y utilizar librerías no
portables?
No necesito nada complicado pero utilizo las librerías conio, string y
demás porque son las que me han enseñado (tampoco sabía que no fueran
portables), por ahora no conozco funciones de otras librerías.
Post by Showtime
/* Lo mejor es que main devuelva un int. Es la única forma portable */
int main(void) {
No lo sabía, me lo apunto. ;-)
Post by Showtime
/* Utiliza la familia printf para salida formateada. Para imprimir
* cadenas de caracteres tienes puts y compañía */
fputs("\n\n", stdout);
for (i = 0; i < strlen(frase); i++) { printf("%d\n", frase[i]); }
puts(frase);
exit(EXIT_SUCCESS);
}
Lo de antes. No las he visto aún en el instituto pero buscaré
información, gracias.

-------------
Salu2
Fernando Arbeiza
2003-12-06 00:15:51 UTC
Permalink
Post by josgalo
Post by Fernando Arbeiza
¿Seguro que necesitas complicarte tanto y utilizar librerías no
portables?
No necesito nada complicado pero utilizo las librerías conio, string y
demás porque son las que me han enseñado (tampoco sabía que no fueran
portables), por ahora no conozco funciones de otras librerías.
Siento no haber especificado más. La librería conio (junto con su
cabecera, conio.h) es la parte que no es portable.

Las cabeceras stdlib.h, stdio.h y string.h (entre otras), están
definidas en la norma de C, luego sí son portables.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Martin J. Sanchez
2003-12-06 10:14:18 UTC
Permalink
On Sat, 06 Dec 2003 00:54:12 +0100, josgalo
Post by josgalo
Gracias a todos por contestar. No puedo aprovechar como debiera vuestra
ayuda y opiniones porque soy bastante novato pero me ha servido de
mucho. Os lo agradezco.
...
No necesito nada complicado pero utilizo las librerías conio, string y
...
Bien, ya que pareces perdido posteo algo que te servira. Espero que te
lo empolles para que te sirva de algo.


#include <conio.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

// definicion de codigos de tecla
#define BS 0x0008U
#define CR 0x000dU
#define INS 0x5200U
#define ESC 0x001bU
#define LEFT 0x4b00U
#define RIGHT 0x4d00U


unsigned int getkey()
{
unsigned int key;
/*
Las teclas especiales devuelven 0
y debemos obtener el siguiente codigo para
identificarlas
*/
key= getch();
if(!key)
key= getch() << 8;
return key;
}

/*
Esta funcion te permite obtener los codigos del teclado
Para terminar su ejecucion pulsas ESC
*/
void prukeys(void)
{
unsigned k;
do {
k= getkey();
printf( "0x%0.4XU\n", k);
} while ( k!= ESC);
}

/* presenta datos en buf en posicion actual de cursor y
permite edicion de campo. El parametro sizbuf es el tamaño
maximo de buf (contando el nul final).
Devuelve: longitud de buf (sin contar nul).
-1 si edicion cancelada
*/
int edit( char *buf, int sizbuf)
{
int key;
int len;
int ox,oy; /* posicion original de cursor. */
int dx=0; /* indice en cadena */
int modoIns=1;

if(!buf || sizbuf<=0)
return -1;

len=strlen(buf);
if(len)
dx= len; /* tras ultimo caracter */

/* guardamos posicion original de cursor */
ox= wherex();
oy= wherey();

cputs( buf );

do {
key= getkey();
switch(key) {
case LEFT :
/* desplazamiento a la izda */
if( dx>0 ) {
dx--;
break;
}
continue;

case RIGHT:
/* desplazamiento a la dcha */
if( dx<len && dx<sizbuf ) {
dx++;
break;
}
continue;

case BS :
/* borrado de caracter izdo */
if( dx>0 ) {
memmove( buf+dx-1, buf+dx, strlen(buf+dx) );
dx--;
buf[--len]='\0';

/* borrar ultimo caracter en pantalla */
gotoxy(ox+len,oy);
cputs(" ");
break;
}
continue;

case INS :
/* cambio en modo insertar */
modoIns= !modoIns;
break;

case ESC :
case CR :
continue;

default :
if( isprint(key) && dx<sizbuf-1 ) {
if( modoIns )
memmove( buf+dx+1, buf+dx, strlen(buf+dx) );
if( len<sizbuf-1 && (modoIns || dx==len) )
++len;
buf[dx]= key;
if( dx<len )
dx++;
buf[len]= '\0';
break;
}
continue;
}

/* presentar cadena */
gotoxy(ox, oy);
cputs(buf);
gotoxy(ox+dx,oy); /* ir a punto de edicion */

} while( key!=CR && key!=ESC );

buf[len]='\0';

if( key==CR ) /* edicion aceptada ? */
return len;

return -1; /* edicion cancelada */
}


int main()
{
char buf[11];
int i;

prukeys();

/* para editar algo, tenemos que inicializar el buffer
con una string y pasarla a edit */
strcpy( buf, "hola");

printf("\n ");
i= edit(buf,sizeof(buf));
printf("\n%s, %d", buf, i);

return 0;
}

Deberias testear el codigo.

Un saludo,
Martin.

Loading...