» »

[C++] Ponavljanje črk v stringu

[C++] Ponavljanje črk v stringu

xtrEeme ::

Lep pozdrav.

Ukvarjam se z funkcijo ki sprejme string in v njem poišče katere črke se ponavljajo in koliko krat. Ustavil se mi je nekje tukaj:

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


int main()
{
    struct letter
    {
        char letter;
        int count;
    };

    string x;
    char Alphabet[] = {'a','b','c','d','e','f','g','h','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    getline(cin, x);
    char c[x.length()];
    int length = x.length();
    int countC=0;

    for(int  i=0;i<length;i++)
        {
            c[i] = x[i];
        }

    for(unsigned int b=0;b<25;b++)
    {
        for(unsigned int e=0; e<x.length(); e++)
        {
            
        }
    }
return 0;
}


Torej vsak znak v podanem stringu sem shranil v polje char c, v drugem polju char Alphabet imam črke angleške abecede. Sedaj nevem kako bi z zanko preveril ujemanja v teh dveh poljih in izpisal tiste ki se ponavljajo več kot enkrat. Ustvaril sem tudi strukturo v katero nameravam shraniti rezultate, vendar mi ne uspe. Kak predlog?

p.s. Ne gre za nobeno nalogo za faks, programiram preprosto zaradi hobija in osebnega interesa

b00mer ::

Em
Gres skozi tabelo Alphabet, vzames prvo crko in preverjas kolikokrat se pojavi v nizu in vsakic povecas stevec.
Izpises..stevec na nulo.

boogie_xlr ::

Abecede ne potrebuješ: poglej si ASCII kodiranje; vsak znak ima svojo vrednost.
Potrebuješ pa polje, v katerega bos shranjeval števce za vsako črko.
Potem lahko v eni while zanki prešteješ črke za celoten vhod.

xtrEeme ::

Kako shranjujem števce za vsako črko posebej to mi ni jasno. Mi lahko en malo nakaže praktično?

Zgodovina sprememb…

  • spremenil: xtrEeme ()

boogie_xlr ::

Narediš polje integerjev
int stevci[25];
in inicializiraš celotno polje na 0
ker ima 'a' po ascii tabeli vrednost 97, enostavno odstejes 97 in dobis 0
na tem mestu v polju stevcev stejes a-je, zato ga povecas za 1
znak = 'a';
stevci[znak - 97]++;

xtrEeme ::

Hvala, zdaj mi je jasno za kaj se gre.
Ali lahko celotno polje inicializiram na 0 z memset funkcijo?
npr. tako ?

int stevci[25];
memset(stevci,0,25);

boogie_xlr ::

lahko
memset(stevci,0,sizeof(stevci));

vendar pazi, sizeof(stevci) ni 25! ampak 25 * sizeof(int)

xtrEeme ::

Aja točno, to so spominski bloki če se ne motim. Hvala, mislim da mi bo zdaj uspelo. :)

mallard ::

Mal bi tvojo kodo pokomentiral:
#include <iostream>
#include <string>
using namespace std;

int main()
{
    // Razen če veš, da jih rabiš, se izogibaj lokalno definiranim tipom.
    // Tak tip ni viden in ni uporaben zunaj funkcije main. Definiraj ga
    // globalno.
    struct letter
    {
        char letter;
        int count;
    };

    string x;
    // Namesto polja bi jaz uporabil string literal.
    //char Alphabet[] = {'a','b','c','d','e','f','g','h','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    const char* Alphabet = "abcdefghijklmnopqrstuvwxyz";
    // String literal je v bistvu tudi polje, je pa razliko od lokalnega polja statično initiliziran (ob zagonu programa,
    // še preden se zažene main). Kazalec Alphabet kaže nanj, indeksiranje pa ostane enake. Pa če ne drugega, je manj za 
    // pisat: 

    getline(cin, x);

    // To pa v standardnem C++ ni dovoljeno. Dimenzija polja mora bit znana med prevajanjem. Sledeča vrstica se prevede
    // ker ima tvoj prevajalnik nestandardno razširitev jezika.
    char c[x.length()];
    // Poleg tega pa nima smisla alocirat polje samo zato, da prekopiraš vsebino string objekta vanj.
    // Lahko preprosto delaš na x objektu, saj podpira indeksiranje z [].

    int length = x.length();
    int countC=0;

    for(int  i=0;i<length;i++)
        {
            c[i] = x[i];
        }

    for(unsigned int b=0;b<25;b++)
    {
        for(unsigned int e=0; e<x.length(); e++)
        {
            
        }
    }
return 0;
}


Tudi ni nobene potrebe po memset-u. Polje se napolni z ničlami če uporabiš prazen initializer:
char arr[42] = {};


Jaz bi na tvojem mestu za števec uporabil polje, ki je dovolj veliko, da zajame vse možne vrednosti tipa char - 256 znakov, torej. Tako ti ni treba gledat in skrbet kaj točno imaš v stringu (vejice, pike, številke), ampak se preprosto sprehodiš čez in prištevaš vrednosti za vsak znak posebej. En haklc - char je bodisi predznačen ali ne-predznačen tip, odvisno od implementacije jezika, zato ga ne moreš meni nič tebi nič uporabit za indeksiranje v polje, ampak ga cast-aš v unsigned char, recimo. Nekej takega bi jaz napisal:

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

const char* abc = "abcdefghijklmnopqrstuvwxyz";

int main()
{
    string s;
    getline(cin, s);

    int counters[256] = {};
    for (char c : s) {
        unsigned char uc = c;
        ++counters[uc];
    }

    // Izpiši znake, ki se pojavijo več kot enkrat
    // zanimajo nas samo črke

    for (int i = 0; i < 26; ++i) {
        unsigned char uc = abc[i];
        int n = counters[uc];
        if ( n > 1)
            cout << char(uc) << ": " << n << '\n';
    }
}


To seveda preverja samo male črke, velike imajo drugo vrednost. To pa lahko nardiš za vajo.

Pa še - ne se navadit na using namespace std;. Za take vaje je v redu, pri kakšenm resnem delu se pa uporablja kvalificirana imena. Srečno.

xtrEeme ::

Hvala za poglobljeno razlago! Bom definitivno preštudiral tvojo kodo in nasvete.

Lp

Mavrik ::

Nič od tega kar pišete tu sicer ni C++.
The truth is rarely pure and never simple.

xtrEeme ::

Mavrik je izjavil:

Nič od tega kar pišete tu sicer ni C++.


Predvidevam da misliš na kodo ki jo je spisal mallard

JanK ::

Ce se ze gremo c++, bi uporabil dinamicno strukturo "map" in iteratorje:

#include <iostream>
#include <string>
#include <map>

int main()
{
    std::string s;
    std::getline(std::cin, s);

    std::map<char, unsigned> count;
    for( std::string::const_iterator p = s.begin(); p != s.end(); ++count[*p++] );

    for( std::map<char, unsigned>::const_iterator p = count.begin(); p != count.end(); ++p ){
      if( p->second > 1 ){
        std::cout << p->first << ": " << p->second << std::endl;
      }
    }
}
"Think about how stupid the average person is,
then realize that 50% are stupider than that"
-George Carlin

mallard ::

Mavrik je izjavil:

Nič od tega kar pišete tu sicer ni C++.

Ker...?

darkkk ::

Mah ne znam brat. Drgač pa sortiraj niz pa preštej :)

Zgodovina sprememb…

  • spremenil: darkkk ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

python-pomoč pri nalogi z nizi

Oddelek: Programiranje
181456 (1154) galu
»

[javaScript] Preverjanje formata zapisa EMŠO

Oddelek: Programiranje
132827 (2447) win64
»

java mali problem (začetnik)

Oddelek: Programiranje
192264 (2007) ozbolt
»

C++ in števke

Oddelek: Programiranje
111229 (1036) Tutankhamun
»

malo pomoči

Oddelek: Programiranje
91017 (851) ERGY

Več podobnih tem