Wednesday, December 30, 2015

Limbajul C++. Capitalizarea literelor sau o problema stil K & R


Un exemplu de cod care numara cuvintele intr-un sir de caractere este prezentat in cartea scrisa de Kernighan si Ritchie.

Enuntul urmator, "Write a program which takes input string and capitalizes the first character of each word in a string, and does not affect the others"  este de pe site-ul programmr.com, dar cu siguranta poate fi intalnit in multe alte locuri/lucrari.

Rezolvarea problemei se bazeaza pe acelasi mecanism descris in lucrarea lui K & R:

- definirea unui cuvant ca o succesiune de caractere non-space care sunt bordate de spaces. Desigur, pe baza acestei definitii, ,,,#@sg-abcd,, este un cuvant, ceea ce poate parea derutant in raport cu bunul simt. Desigur, asd_g def este, conform aceleiasi definitii, o succesiune de doua cuvinte, asd_g si def.

- declararea si setarea unei variabile inword  care "tine cont" daca la un moment oarecare (la o iteratie oarecare) ne aflam sau nu in interiorul unui cuvant.

Daca s este un sir de caractere introdus de la tastatura, a carui lungime length o vom determina, atunci algoritmul implementat poate fi urmatorul:

1) la inceputul unui sir de caractere ne aflam "in afara" unui cuvant, inword = 0;

2) daca la iteratia curenta i avem inword == 0, atunci

2)a) daca s[i] este litera, atunci inword = 1 si

2)a)1) daca s[i] este litera mica, s[i] = s[i] - 32 (si devine litera mare);

2)b) daca s[i] nu este litera, inword ramane zero si se continua cu urmatoarea iteratie;

3) daca la iteratia curenta inword == 1 atunci

3)a) daca s[i] este spatiu, inword = 0 (am ajuns "in exteriorul" unui cuvant)

3)b) daca s[i] nu este spatiu, continua cu urmatoarea iteratie.

Obs: desigur, delimitatorul unui cuvant poate sa nu fie limitat la spatiu si sa fie, de asemenea, tab, '\t', sau enter, '\r'.

Codul urmator foloseste doar spatiul, cod ASCII 32, ca delimitator de cuvinte.

O alta observatie este ca, in mod uzual, dupa ultimul cuvand dintr-o propozitie urmeaza punct, nu spatiu. Insa acest caz este acoperit de limitarea numarului de iteratii la lungimea length  a sirului de caractere.

Codul si printscreen-ul:

// capitalisation of the first letter

#include <iostream>

using namespace std;

void Capitalisation (char *);

bool IsSmallLetter(char x)
{
     unsigned y = (int)x;
     if(y >= 97 && y <= 122) return true;
     else return false;
}

bool IsLetter(char x)
{
     unsigned y = (int)x;
     if((y >= 97 && y <= 122) || (y >= 65 && y <= 90)) return true;
     else return false;
}

int main()
{
    char s[500];
    cout <<"Enter a string of characters:\n";
    gets(s);
    //cout <<"You have entered \"" << s <<"\".";
    Capitalisation(s);
    cout <<"\n" << s <<"\n";
    return 0;
}

void Capitalisation (char * s)
{
     int length = 0, i;
     while(s[length]) length++;
     //cout << length;
     int inword = 0;
     for(i = 0; i < length; i++)
     {
           if(!inword)
           {
             if(IsLetter(s[i]))
               {
                 inword = 1;
                 if(IsSmallLetter(s[i])) s[i] -= 32;
               }
             else continue;
           }
           else if(s[i] != 32) continue;
           else inword = 0;
     }

}


No comments:

Post a Comment