Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Ricerca personalizzata
4
voti

Estrarre parole (simboli) da una stringa

Antefatto

Mi squilla il telefono
"Oh! Ciao caro, tutto bene?"
"Si, tutto bene."
"Dimmi"
"Ma niente, non è che hai un programmino in C già scritto per fare una cosa su di una stringa?"
"Cosa ci devi fare?"
"Io ho questa stringa che contiene parole e numeri separati da una virgola, dovrei isolare questi numeri e parole ad una ad una. Di solito non scrivo queste cose, e quindi ho pensato a te."
"Ce l'ho già fatto. Facciamo così: invece di mandartelo lo scrivo in un articolo sul forum. Così se c'è qualcuno che ha bisogno della stessa cosa lo può trovare e lo può utilizzare anche lui. Va bene?"
"Si, perfetto! Ti ringrazio!"
"Figurati, è un piacere, ciao!"


Il software

Per prima cosa bisogna avere a disposizione una funzione che riconosca se un carattere è da considerarsi come separatore o no. E' necessaria.

// Verifica se un carattere è un separatore
uint8_t isChSep(uint8_t ch)
{
  if ((ch <= ' ') ||
      ('\n' == ch) || 
      ('\r' == ch) ||         
      (',' == ch) ||
      (127 == ch)) return 1;
  return 0;
}

Ho scritto le varie condizioni del "if" incolonnate in modo da poter aggiungere, o togliere, i caratteri che devono essere interpretati come separatori. Per questo esempio ho considerato separatori lo spazio, il carattere di (LF), il carattere (CR), la virgola, ed il carattere (DEL) (codice ASCII 127). Se ne possono aggiungere altri o altre condizioni. La funzione ritorna 0 se il carattere non è un separatore, 1 se è un separatore.
Nota: la prima condizione (ch <= ' ') include già le due seguenti. L'ho lasciata come esempio.

La nostra stringa può avere caratteri separatori fra le parole, all'inizio come primi caratteri ed alla fine. Quindi per isolare il primo simbolo dobbiamo accertarci di aver saltato tutti gli eventuali separatori. Nel momento in cui si incontra un carattere che non è separatore si incomincia a comporre un altra stringa che rappresenterà il simbolo letto.
In buona sostanza il parametro della funzione è un puntatore ad un carattere (della stringa) e viene incrementato se il carattere puntato è un separatore. Esce quando incontra un carattere che non è un separatore o ovviamente, se è il terminatore della stringa, cioè 0.

// Skippa tutti i caratteri separatori che incontra
static char* strSkipSep(char* pt)
{
  while((*pt != 0) && isChSep(*pt)) pt++;
  return pt;
}


Quindi ora è sufficiente un altra funzione alla quale passeremo due puntatori: uno che punta al carattere della stringa sorgente, e l'altro che punta ad una stringa di destinazione dove verrà copiato il simbolo letto.

// Ottiene una parola (simbolo) in una stringa con simboli separati da 
// uno o più caratteri separatori
// Ritorna la posizione immediatamente successiva al simbolo ottenuto
char* strGetSymbol(char* source, char* dest)
{
  source = strSkipSep(source);
  while(!isChSep(*source))
  {
    if (!*source) break;
    *dest++ = *source++;
  }
  // Scrive il terminatore della stringa
  *dest = 0;
  return source;
}

Il puntatore di ritorno è utile per la ricerca della parola successiva.

A questo punto un piccolo "main" di prova per vedere come funziona tutto l'ambaradan. Evito di scrivere ingressi da tastiera o altre cose in modo da rendere il programma più semplice possibile. Nelle operazioni di output ho messo degli asterischi in modo da vedere se ci sono caratteri invisibili ancora presenti. Le stringhe saranno così racchiuse fra asterischi, ma solo per la visualizzazione.

// Main di prova
int main(int argc, char** argv)
{
  char s[] = "Pippo ,274,Wh_kp,-3478\n,parola1 \n,, parola2 parola3 ,,,,";
  char* pt = s;
  char simb[50];
  printf("== Stringa iniziale ==\n");
  printf("*%s*\n", s);
  printf("== Estrazione simboli ==\n");
  while(*pt)
  {
    pt = strGetSymbol(pt, simb);
    printf("*%s*\n", simb);
  }
  return (EXIT_SUCCESS);
}

L'output del programma è questo

== Stringa iniziale ==
*Pippo ,274,Wh_kp,-3478
,parola1 
,, parola2 parola3 ,,,,*
== Estrazione simboli ==
*Pippo*
*274*
*Wh_kp*
*-3478*
*parola1*
*parola2*
*parola3*
**

Il programmino completo

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

// Verifica se un carattere è un separatore
uint8_t isChSep(uint8_t ch)
{
  if ((ch <= ' ') ||
  ('\n' == ch) || 
  ('\r' == ch) ||         
  (',' == ch) ||
  (127 == ch)) return 1;
  return 0;
}

// Skippa tutti i caratteri separatori che incontra
static char* strSkipSep(char* pt)
{
  while((*pt != 0) && isChSep(*pt)) pt++;
  return pt;
}

// Ottiene una parola (simbolo) in una stringa con simboli separati da 
// uno o più caratteri separatori
// Ritorna la posizione immediatamente successiva al simbolo ottenuto
char* strGetSymbol(char* source, char* dest)
{
  source = strSkipSep(source);
  while(!isChSep(*source))
  {
    if (!*source) break;
    *dest++ = *source++;
  }
  // Scrive il terminatore della stringa
  *dest = 0;
  return source;
}

// Main di prova
int main(int argc, char** argv)
{
  char s[] = "Pippo ,274,Wh_kp,-3478\n,parola1 \n,, parola2 parola3 ,,,,";
  char* pt = s;
  char simb[50];
  printf("== Stringa iniziale ==\n");
  printf("*%s*\n", s);
  printf("== Estrazione simboli ==\n");
  while(*pt)
  {
    pt = strGetSymbol(pt, simb);
    printf("*%s*\n", simb);
  }
  return (EXIT_SUCCESS);
}
1

Commenti e note

Inserisci un commento

di ,

Davvero utilissimo grazie mille per questo splendido supporto

Rispondi

Inserisci un commento

Per inserire commenti è necessario iscriversi ad ElectroYou. Se sei già iscritto, effettua il login.