Con mi insufrible manía de hacer la cosas lo mas dificil posible he montado
una demo de este asunto de los strings mediante un "monitor rs232".
Quiero decir que he hecho un programa que se comunica con el PC mediante
la rs232 y que acepta comandos y argumentos de estos comandos para los
ejemplos de algunas funciones ...
Pero para poder hacer esto de los comandos, que en el fondo no es mas que
procesar strings, he necesitado hacer uso de la mayoria de las funciones que
estamos tratando de ejemplificar.
El resultado ha sido plenamente satisfactorio ya que funciona perfectamente
y a la vez ha salido, perdonen la inmodestia, muy pedagógico. Aparecen la
mayoría de las funciones de tratamiento de strings y las que no lo hacen se
manejan de forma absolutamente análogas a las que sí.
Mas abajo os posteo el código completo del <a href="
http://picmania.garcia-cuervo.com/recursos/_strings_demo.c" target="_blank">Strings_Demo.c[/url]
<span class="texto_mini">Codigo:</span>[hr /
]
/////////////////////////////////////////////////////////////////////////////////////////
//
// Strings_Demo v.1.0
//
// © 28.02.2006 By RedRaven (RedPic)
//
// Para Foro Todo Pic
//
// Idioma: CCS PICC v.3.242
//
/////////////////////////////////////////////////////////////////////////////////////////
#include <16f876a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include <stdlib.h>
// Constantes y definiciones ////////////////////////////////////////////////////////////
int const MAXLENBUFF=42; // Maxima longitud del buffer de recepción RS232
int const MAXLENCOMMAND=10; // Maxima longitud de un comando (sin argumentos)
int const MAXLENARG=8; // Maxima longitud de cada uno de los argumentos s1 y s2
// Variables Globales ///////////////////////////////////////////////////////////////////
char buffrec[MAXLENBUFF]; // Buffer de Recepcion
int xbuffrec=0x00; // índice del Buffer de Recepcion
int1 new_command=0; // Flag para indicar comando disponible
int1 pdte_send_prompt=0; // Flags para enviar echos fuera de la int_rda
int1 pdte_send_tmp_prompt=0;
char s1[MAXLENARG]; // Argumento 1
char s2[MAXLENARG]; // Argumento 2
char sr[MAXLENBUFF]; // Resultado de nuestras manipulaciones de Strings
// Declaracion de Funciones /////////////////////////////////////////////////////////////
void On_reset(void); // Tras RESET del Micro
void Send_listen(void); // Monitoriza RS232 : Comienzo
void Send_opts(void); // Monitoriza RS232 : Presenta opciones
void Send_prompt(void); // Monitoriza RS232 : Presenta el Cursor
void Send_tmp_prompt(void); // Monitoriza RS232 : Presenta el Cursor y el comando actual
void Ini_buffrec(void); // Borra el buffer de recepción
void Add_buffrec(char c); // Añade un caracter al buffer de recepción
void Procesa_comando(void); // Procesado de comandos
// INTERRUPCIONES ///////////////////////////////////////////////////////////////////////
// INTERRUPCION RDA - Recepción USART -
#int_rda
void serial_isr() {
if(kbhit()){ // Si hay algo pendiente de recibir ...
Add_buffrec(getc()); // lo recibo y lo añado al Buffer de Recepcion
}
}
// Control del Buffer de recepcion ---------------------------------------
void Ini_buff_rec(void){ // Inicia a "�" el Buffer de Recepcion
int i;
for(i=0;i<MAXLENBUFF;i++){ // Bucle que pone a 0 todos los
buffrec[ i ]=0x00; // caracteres en el Buffer de Recepcion
}
xbuffrec=0x00; // Inicializo el indice de siguiente caracter recibido
}
void Add_buffrec(char c){ // Añade caracter al Buffer de Recepcion
switch(c){
case 0x0D: // [Enter] -> Habilita Flag para procesar comando en Main
buffrec[xbuffrec++]=" "; // Añade un espacio en blanco al final y ...
new_command=1; // Habilita Flag para procesar comando en Main
break;
case 0x08: // [Del] -> Borra último caracter del Buffer
if(xbuffrec>0){ // Si hay algo en el buffer
buffrec[--xbuffrec]=0x00; // decremento el índice, escribo un cero y ...
pdte_send_tmp_prompt=1; // habilito flag para refrescar el prompt
}
break;
case 0x01B: // [Esc] -> Borra el Buffer completamente y ...
Ini_buff_rec(); // habilito flag para refrescar el prompt
pdte_send_prompt=1;
break;
case 0x009: // [Tab] -> Refresca el prompt y el comando tal como esté
pdte_send_tmp_prompt=1;
break;
default:
buffrec[xbuffrec++]=c; // Añade caracter recibido al Buffer
putc(c); // y lo monitorizo
}
}
// Rutinas y Funciones de RROS ///////////////////////////////////////////
void On_reset(void){ // Inicializacion del Micro tras RESET
disable_interrupts(GLOBAL); // todas las interrupciones desactivadas
delay_ms(100);
Ini_buff_rec(); // Inicializo Buffer de recepcion
new_command=0; // Desactivo flag de comando pendiente.
pdte_send_prompt=0; // Desactivo Flags para enviar echo fuera de la int_rda
pdte_send_tmp_prompt=0;
enable_interrupts(int_rda); // interrupcion RDA habilitada
enable_interrupts(global); // todas las interrupciones activadas
Send_listen(); // Presenta Comienzo
Send_prompt(); // Presenta el Cursor
}
void Send_listen(void){ // Presenta Comienzo
printf("
Strings Demo v1.0" );
Send_opts();
}
void Send_opts(void){ // Relación de comandos válidos
printf("
" );
printf("[?] ver comandos válidos
" );
printf("[strcat ABC abc] añade s2=abc a s1=ABC
" );
printf("[strlwr ABC] convierte ABC a minúsculas
" );
printf("[strstr ABC abc] busca s2=abc dentro de s1=ABC
" );
}
void Send_prompt(void){ // Presenta el cursor
printf("
>" );
}
void Send_tmp_prompt(void){ // Presenta el cursor con el comando actual
printf("
>%s",buffrec);
}
// MAIN Programa Principal ///////////////////////////////////////////////
void main(void)
{
On_reset();
do {
// Deteccion de la necesidad de procesar comandos pendientes ///////
if(new_command==1){ // Si hay un nuevo comando ...
new_command=0; // deshabilito el aviso y ...
Procesa_comando(); // Procesado de comandos
Ini_buff_rec(); // inicializo todo para nuevo comando y ...
pdte_send_prompt=1; // mando prompt.
}
// Deteccion de la necesidad de enviar echos ///////////////////////
if(pdte_send_prompt==1){ // Si esta pendiente de enviar prompt ...
pdte_send_prompt=0; // marco que ya no lo está y ...
Send_prompt(); // lo envío.
}
if(pdte_send_tmp_prompt==1){ // Si esta pendiente de enviar prompt temporal ...
pdte_send_tmp_prompt=0; // marco que ya no lo está y ...
Send_tmp_prompt(); // lo envío.
}
} while(TRUE);
}
// Funciones necesarias ... //////////////////////////////////////////////
int extrae_argumentos(int cuantos){
int i,c;
int error=0; // Para devolver código de error si se da el caso
char *ptri;
char *ptrf;
for(i=0;i<MAXLENARG;i++){ // Bucle que pone a 0 todos los
s1[ i ]="�"; // caracteres en s1 y s2 antes de extraer
s2[ i ]="�";
}
c=1;
for(i=0;i<MAXLENBUFF;i++){ // Bucle que marca los separadores " " (espacios)
if(buffrec[ i ]==" "){ // en el buffer de recepción
buffrec[ i ]=c++; // escribiendo 0x01 en el primero, 0x02 en el segundo ... etc.
} // con lo que s1 estará entre 0x01 y 0x02 y ...
} // s2 estará entre 0x02 y 0x03.
if(cuantos==1){ // Si necesito dos argumentos y ...
if(c!=3){ // Error: tengo menos o mas de un argumento
error=1; // ya que hemos puesto un numero distinto a 2 de marcas
goto retorno; // observa que para 2 marcas c vale 3
}
}
if(cuantos==2){ // Si necesito dos argumentos y ...
if(c!=4){ // Error: tengo menos o mas de dos argumentos
error=1; // ya que hemos puesto un numero distinto a 3 de marcas
goto retorno; // observa que para 3 marcas c vale 4
}
}
ptri=strchr(buffrec,0x01); // obtengo el puntero donde aparece 0x01
ptrf=strchr(buffrec,0x02); // obtengo el puntero donde aparece 0x02
if(ptri!=0 && ptrf!=0){ // Si he encontrado 0x01 y 0x02
ptri+=1; // avanzo 1 ptri para saltarme 0x01
strncpy(s1,ptri,ptrf-ptri); // Luego s1 lo extraigo entre ptri y ptrf
}
if(cuantos==1){ // Si solo necesito un argumento he terminado
goto retorno;
}
ptri=strchr(buffrec,0x02); // obtengo el puntero donde aparece 0x02
ptrf=strchr(buffrec,0x03); // obtengo el puntero donde aparece 0x03
if(ptri!=0 && ptrf!=0){ // Si he encontrado 0x01 y 0x02
ptri+=1; // avanzo 1 ptri para saltarme 0x02
strncpy(s2,ptri,ptrf-ptri); // Luego s2 lo extraigo entre ptri y ptrf
}
retorno:
return(error);
}
// Procesa_comando: Hace cosas o manda hacerlas ... //////////////////////
void Procesa_comando(void){
int1 procesado_ok=0; // Flag para comprobar si he procesado algo válido
char xcommand[MAXLENCOMMAND]; // Comprobador de comando recibido
int error;
char *ptrx;
// COMANDO = "" intro en blanco ---------------------------------------
strcpy(xcommand,"" );
if(!strcmp(buffrec,xcommand)){
procesado_ok=1;
goto fin_procesa;
}
// COMANDO = "?" ------------------------------------------------------
strcpy(xcommand,"?" );
if(!strncmp(buffrec,xcommand,strlen(xcommand))){
Send_opts();
procesado_ok=1;
goto fin_procesa;
}
// COMANDO = "strcat" -------------------------------------------------
strcpy(xcommand,"strcat" );
if(!strncmp(buffrec,xcommand,strlen(xcommand))){
error=extrae_argumentos(2);
if(error!=0){
printf("
Error: numero erróneo de argumentos" );
}
else{
strcpy(sr,s1);
strcat(sr,s2);
printf("
%s + %s = %s
",s1,s2,sr);
}
procesado_ok=1;
goto fin_procesa;
}
// COMANDO = "strlwr" -------------------------------------------------
strcpy(xcommand,"strlwr" );
if(!strncmp(buffrec,xcommand,strlen(xcommand))){
error=extrae_argumentos(1);
if(error!=0){
printf("
Error: numero erróneo de argumentos" );
}
else{
strcpy(sr,s1);
strlwr(sr);
printf("
%s -> %s
",s1,sr);
}
procesado_ok=1;
goto fin_procesa;
}
// COMANDO = "strstr" -------------------------------------------------
strcpy(xcommand,"strstr" );
if(!strncmp(buffrec,xcommand,strlen(xcommand))){
error=extrae_argumentos(2);
if(error!=0){
printf("
Error: numero erróneo de argumentos" );
}
else{
strcpy(sr,s1);
ptrx=strstr(sr,s2);
if(ptrx==0){
printf("
%s no está en %s
",s2,s1);
}
else{
printf("
%s empieza en el caracter %uº de %s
",s2,(ptrx-&sr[0])+1,s1);
}
}
procesado_ok=1;
goto fin_procesa;
}
fin_procesa:
// COMANDO ERRÓNEO - ¿ezo qué é lo que é ?-----------------------------
if(procesado_ok==0){
printf("
?%s",buffrec);
}
}