[ C++ ] string splitsen

Pagina: 1
Acties:
  • 275 views sinds 30-01-2008
  • Reageer

  • codeweb
  • Registratie: Juni 2002
  • Nu online
Laat ik allereerst even vertellen dat ik een beginner ben in C++ en dat ik al gezocht heb op internet (wellicht met verkeerder zoektermen maargoed) maar niets gevonden heb...

Ik moet de volgende functie schrijven

int telCijfer(int getal, int cijfer)

voorbeeld:

telCijfer(123434, 4) --> 2
telCijfer(3332, 5) --> 0
telCijfer(1111111, 1) --> 7

Nu is mijn vraag; hoe kan ik het gedeelte wat aan getal word meegegeven splitsen zodat ik kan gaan tellen... Of is hier misschien een functie voor? ik hoop dat jullie mij even een "zetje" kunnen geven zodat ik weer verder kan gaan B) :9

Verwijderd

er is een standaard functie voor als je het zou converteren naar een string object, iets als substring(begin, einde) waarbij begin de letter vanaf 0 is en einde de laatste in te scannen letter - 1.

dit is trouwens interesting want het gaat van voren naar achteren, als ik me niet vergis heb ik dit een keer moeten doen tijdens een werkgroep toetsje en recursief ook :(..

je moet idd modulo 10 gebruiken...

[ Voor 46% gewijzigd door Verwijderd op 07-09-2003 16:18 . Reden: het brein denkt ]


  • mmedia
  • Registratie: Januari 2002
  • Laatst online: 17-12-2021
Ik zou het doen met "modulo 10" en iteratie.

  • codeweb
  • Registratie: Juni 2002
  • Nu online
jah, bedankt :D

ik kan weer verder (moet dus met substr) :)

dank je wel :P

edit:

Trouwens wel leuk dit :/

ik heb net even wat geprobeerd met substr, maar het blijkt dat het met getallen (int dus) niet wil werken :?

krijg deze error terug:

error C2228: left of '.substr' must have class/struct/union type

en heb dit staan: getal.substr(0,2);

iemand nog een idtje?

[edit2]
ik zag in de voorgaande posts "modulo 10" genoemd, mag ik vragen wat dat inhoud?
[/edit2]

[ Voor 80% gewijzigd door codeweb op 07-09-2003 16:48 . Reden: update ]


Verwijderd

Zo moet het er ongeveer uit gaan zien denk ik, het zal niet zo 123 gelijk werken... heb hoofdpijn en eigenlijk helemaal geen zin hierin :)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
int telCijfer (int iCijferReeks, int iVergelijkGetal)
{
  String sCijferReeks = iCijferreeks;
  int iBevat = 0;

  for (int i=1; i <= sCijferReeks.Length(); i++){

    if sCijferReeks[i] == iVergelijkgetal{
      iBevat = iBevat++;
}
return iBevat;
}

[ Voor 9% gewijzigd door Verwijderd op 07-09-2003 17:02 ]


Verwijderd

Huiswerkopdracht? Lijkt me niet echt een functie die je in real life nodig zult hebben...

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op 07 September 2003 @ 17:00:
Zo moet het er ongeveer uit gaan zien denk ik, het zal niet zo 123 gelijk werken... heb hoofdpijn en eigenlijk helemaal geen zin hierin :)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
int telCijfer (int iCijferReeks, int iVergelijkGetal)
{
  String sCijferReeks = iCijferreeks;
  int iBevat = 0;

  for (int i=1; i <= sCijferReeks.Length(); i++){

    if sCijferReeks[i] == iVergelijkgetal{
      iBevat = iBevat++;
}
return iBevat;
}
Dit gaat natuurlijk nooit zo werken. Je kunt niet zomaar een int aan een string assignen. En ik zie ook niet echt in waarom je er een string van zou moeten maken. Dat is totaal niet efficient.

kan je beter zoiets doen
C++:
1
2
3
4
5
6
int divideBy = 1;
while( divideBy < getal )
{
    int singlePos = (getal / divideBy ) % 10;
    divideBy *= 10;
}

[ Voor 5% gewijzigd door Woy op 07-09-2003 17:13 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Soultaker's how-to-program les 1: bedenk eerst hoe je het probleem handmatig zou oplossen!

Waarschijnlijk wil je alle cijfers in het getal afgaan (itereren over de cijfers in het getal) en ze één voor één vergelijken met het gezochte cijfer. Je kunt zo vrij makkelijk het aantal gezochte cijfers tellen.

Zoals drago al aangeeft is dat vrij makkelijk als je het getal omzet naar een string, zodat het getal feitelijk gerepresenteerd wordt door een reeks van karakters. Die afzonderlijke karakters zijn weer als cijfers te interpreteren en dan kun je ze vergelijken. Een implementatie van dat algoritme zou er als volgt uitzien:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
        int getal    = 123434;
        int cijfer   = 4;
        int gevonden = 0;

        ostringstream ss;
        ss << getal;
        const string str = ss.str();
        for(string::const_iterator i = str.begin(); i != str.end(); ++i)
                if((*i - '0') == cijfer)        
                        ++gevonden;

        cout << gevonden << std::endl;
}

Op zich is dit een correcte implementatie, maar het is nogal een gedoe, omdat je zowel met int's, strings en characters werkt. De expressie (*i - '0') is bijvoorbeeld nodig om een character (zoals '1') om te zetten naar een int (zoals 1). De getalwaarde van character '1' is namelijk iets heel anders dan 1.

Het is dus waarschijnlijk handig om iets verder door te denken, zodat je die strings en characters niet nodig hebt. Je implementatie wordt dan veel efficiënter omdat je geen conversies meer hoeft uit te voeren en het wordt er ook nog leesbaarder op.

Wat je wilt bereiken, is dat je alle cijfers in je invoergetal één voor één kunt beschouwen. In welke volgorde je ze beschouwt maakt echter niet uit! En daar komt het verhaal met "modulo 10" om de hoek kijken. Als je een geheel getal als "12345" deelt door 10, dan is het resultaat een geheel getal "1234" (er wordt altijd omlaag afgerond!) en de rest "5" (basisschoolkennis). De modulus operator levert je de rest op; dat is het hele verhaal. 12345/10 is dus 1234, en 12345%10 is 5. Hier valt direct op, dat (x%10) het laatste cijfer van het getal oplevert, en (x/10) het getal dat bestaat uit de overige cijfers! Als je dus steeds met de modulus het laatste cijfer bekijkt en met de deling het laatste cijfer van het overgebleven getal afhaalt, dan kun je alle cijfers dus een voor een langsgaan.

De implementatie hiervan mag je zelf verzinnen; als het goed is wordt het een simpele for- of while-lus van een regel of 3. Denk eraan dat je moet stoppen wanneer het resterende getal 0 is geworden.

edit:
Hmm, ik zie dat er al allerlei voorgekauwde uitwerkingen staan. Beetje jammer, als het zo duidelijk om een huiswerkopgave gaat.

[ Voor 10% gewijzigd door Soultaker op 07-09-2003 17:19 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
rwb schreef op 07 September 2003 @ 17:11:
En ik zie ook niet echt in waarom je er een string van zou moeten maken. Dat is totaal niet efficient.
Denk er wel aan dat de TS op dit punt geen idee heeft hoe 'ie het probleem op moet lossen. Voor jou en mij ligt de efficiënte oplossing voor de hand, maar voor de TS is het veel nuttiger als 'ie zelf een correcte oplossing kan construeren. De conversie naar een string is niet efficiënt, maar levert wel een algoritme op waarvan makkelijk in te zien is dat het correct is. Als eerste stap is het dus zeker niet fout.

  • codeweb
  • Registratie: Juni 2002
  • Nu online
bedankt iedereen voor de hulp :)

soultaker: jij ook bedankt voor het uitleggen van het modulo 10 verhaal, na dat gelezen te hebben was t voor mij een stuk makkelijker en heb het nu weten op te lossen :) ik zal dat in ieder geval onthouden voor de volgende keer

misschien voor de geinteresseerde hoe ik het heb opgelost:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;

int telCijfer(int getal, int cijfer);

int main()
{
    int getal, cijfer, eind;
    cout << "Voer een getal in: ";
    cin >> getal;
    cout << "Voer een cijfer in: ";
    cin >> cijfer;
    while(getal > 0 && cijfer > 0)
    {
        eind = telCijfer(getal, cijfer);
        cout << eind << endl << "Voer een getal in: ";
        cin >> getal;
        cout << "Voer een cijfer in: ";
        cin >> cijfer;
    }
    return 0;
}

int telCijfer (int getal, int cijfer) 
{ 
    int nieuw_getal(getal), aantal(0);
    while(nieuw_getal > 0)
    {
        if((nieuw_getal%10) == cijfer)
        {
            aantal++;
        }
        nieuw_getal = nieuw_getal/10;
    }
    return aantal;
}


het zal misschien sneller kunnen, maar dit is dus de oplossing die ik na soultaker's post heb verzonnen.

Heel hartelijk bedankt iig :)

[ Voor 17% gewijzigd door codeweb op 07-09-2003 18:05 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Randgevalletje: met de invoer 0 en het gevraagde cijfer 0, levert je implementatie nu het resultaat 0 op, terwijl dat wellicht 1 zou moeten zijn. Het is een beetje de vraag of je die invoer wilt toestaan en of je daar een uitzondering voor wilt maken.

  • codeweb
  • Registratie: Juni 2002
  • Nu online
het zit zo; bij ons op school (huiswerk opdracht jah :P ) willen ze het zo hebben dat wanneer er een 0 word ingevoerd (in 1 vd 2 invoerruimten) het programma moet stoppen zonder uitkomst te geven (nu ik dit aan het typen ben heb ik nog iets kleins toegevoegd aan het script zodat hij nu ook stopt als cijfer 0 is :) )

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Soultaker schreef op 07 september 2003 @ 17:21:
[...]

Denk er wel aan dat de TS op dit punt geen idee heeft hoe 'ie het probleem op moet lossen. Voor jou en mij ligt de efficiënte oplossing voor de hand, maar voor de TS is het veel nuttiger als 'ie zelf een correcte oplossing kan construeren. De conversie naar een string is niet efficiënt, maar levert wel een algoritme op waarvan makkelijk in te zien is dat het correct is. Als eerste stap is het dus zeker niet fout.
Ja hier heb je gelijk in. Het was eigenlijk ook meer een reactie op Toetsje. Op de manier dat jij het uitlegd met strings is het al een stuk duidelijker omdat je er meteen bijverteld dat dit niet de beste oplossing is.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Killemov
  • Registratie: Januari 2000
  • Laatst online: 17-08 12:12

Killemov

Ik zoek nog een mooi icooi =)

de mod 10 oplossing is het meest efficient

Hey ... maar dan heb je ook wat!


Verwijderd

rwb schreef op 07 September 2003 @ 18:16:
[...]

Ja hier heb je gelijk in. Het was eigenlijk ook meer een reactie op Toetsje. Op de manier dat jij het uitlegd met strings is het al een stuk duidelijker omdat je er meteen bijverteld dat dit niet de beste oplossing is.
Maar denk jij dat hij nou de modulo functie helemaal snapt? :)
Je kunt trouwens wel een integer direct in een C++ Builder String (geen Ansi-string) omzetten.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

rwb schreef op 07 september 2003 @ 17:11:
[...]


Dit gaat natuurlijk nooit zo werken. Je kunt niet zomaar een int aan een string assignen. En ik zie ook niet echt in waarom je er een string van zou moeten maken. Dat is totaal niet efficient.

kan je beter zoiets doen
C++:
1
2
3
4
5
6
int divideBy = 1;
while( divideBy < getal )
{
    int singlePos = (getal / divideBy ) % 10;
    divideBy *= 10;
}
als je het toch over efficientie hebt kun je sowieso beter elke keer delen door 10, in plaats van een deler steeds met 10 te vermenigvuldigen en het getal elke keer te delen door die deler ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op 07 September 2003 @ 18:47:
[...]


Maar denk jij dat hij nou de modulo functie helemaal snapt? :)
Je kunt trouwens wel een integer direct in een C++ Builder String (geen Ansi-string) omzetten.
Ah okee blijkbaar is er dus een assignment operator voor een int naar een string ofzo gedefineerd. Is dit in C++ Builder trouwens gewoon de std::String of is het een String implementatie van Borland?
Maar deze conversie zal waarschijnlijk ook gewoon op dezelfde manier werken met mod 10 dus kan je dat net zo goed meteen zelf doen.

Als hij de modulo operator niet snapt dan kan hij dat of opzoeken in de documentatie of er hier een vraag over stellen. Overigens heeft soultaker het nu al verteld dus lijkt me dat het niet zo'n probleem moet zijn het is nou niet echt een van de ingewikkeldste dingen om te snappen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Verwijderd

rwb schreef op 07 September 2003 @ 19:55:
[...]

Ah okee blijkbaar is er dus een assignment operator voor een int naar een string ofzo gedefineerd. Is dit in C++ Builder trouwens gewoon de std::String of is het een String implementatie van Borland?
Maar deze conversie zal waarschijnlijk ook gewoon op dezelfde manier werken met mod 10 dus kan je dat net zo goed meteen zelf doen.

Als hij de modulo operator niet snapt dan kan hij dat of opzoeken in de documentatie of er hier een vraag over stellen. Overigens heeft soultaker het nu al verteld dus lijkt me dat het niet zo'n probleem moet zijn het is nou niet echt een van de ingewikkeldste dingen om te snappen.
De String is een implementatie van Borland zelf. Zit in een complete eigen klasse met nog een hele hoop andere (handige) functies :)
Pagina: 1