Hjälp med att räkna ut kvadratsumma korrekt
Hej,
Jag måste ändra i denna kod eftersom kvadratsumman som beräknas i funktionen "tolka" blir fel. Detta beror på att jag inte beräknar rätt antal tecken i texten som läses in. Meningen är att man bara ska räkna tecken mellan a/A och z/Z i alfabetet. När jag använder int antal = text.size(); så ger de textens totala längd inklusive blanksteg och övriga tecken. Dessa ska exkluderas och sedan ska man räkna antal tecken i berakna_histogram_abs() och returnera det värdet)!"
Har någon några idéer på hur jag kan lösa detta? Hur kan jag ändra berakna_histogram_abs() så den returnerar värdet? Jag får inte använda pointers.
//-----------------------------------------------------------
//
// Hanterar fallet med 26 bokstâver A-Z
#include <string>
#include <cctype>
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
// Globala konstanter:
// Tips: Anvând de globala konstanterna ANTAL_BOKSTAVER och ANTAL_SPRAK
// istâllet fàr vârdena 26 och 4 i programmet.
const int ANTAL_BOKSTAVER = 26; //A-Z
const int ANTAL_SPRAK = 4;
// 2d-arrayen TOLK_HJALP inneh¬ller bokstavsfrekvensen i %
// fàr fyra spr¬k. TOLK_HJALP[0][0] âr frekvensen av
// bokstaven a fàr engelska.TOLK_HJALP[0][25] âr frekvensen av
// bokstaven z fàr engelska.
// Arrayen âr en GLOBAL KONSTANT och skall allts¬ ej skickas
// som parameter till den funktion som behàver den.
const double TOLK_HJALP[ANTAL_SPRAK][ANTAL_BOKSTAVER] =
{ {8.27,1.48,2.94,4.03,11.78,2.22,1.72,6.77, //engelska
7.39,0.12,0.81,3.76,2.85,6.71,7.79,1.54,
0.05,5.95,6.69,9.07,2.66,1.13,2.14,0.19,
1.89,0.03},
{7.97,1.40,3.55,3.79,16.89,1.02,1.00,0.75, //franska
7.08,0.38,0.04,5.51,2.82,8.11,5.19,2.78,
1.01,6.69,8.35,7.22,6.09,1.35,0.02,0.54,
0.30,0.15},
{9.50,1.11,1.53,5.30,8.94,1.74,3.57,3.94, //svenska
3.98,0.89,3.26,4.93,3.41,8.46,5.01,1.77,
0.00,6.73,5.56,9.20,1.94,2.42,0.00,0.05,
0.45,0.00},
{5.12,1.95,3.57,5.07,16.87,1.35,3.00,5.79, //tyska
8.63,0.19,1.14,3.68,3.12,10.64,1.74,0.42,
0.01,6.30,6.99,5.19,3.92,0.77,1.79,0.01,
0.69,1.24} };
// Globala variabler âr ej till¬tna
//--------------------------------------------------------
// Funktionsdeklarationer:
string namn_pa_fil(string namn);
string inlasning(const string& namn);
void berakna_histogram_abs(const string& text, int(&frekvens)[ANTAL_BOKSTAVER]);
void skriv_histogram_abs(const int(&frekvens)[ANTAL_BOKSTAVER]);
void abs_till_rel(const std::string& text, int(&histogram_abs)[ANTAL_BOKSTAVER], double(&histogram_rel)[ANTAL_BOKSTAVER]);
void plotta_histogram_rel(const double(&histogram_rel)[ANTAL_BOKSTAVER]);
void tolka(const double(&histogram_rel)[ANTAL_BOKSTAVER]);
string removeSpaces(string text);
//--------------------------------------------------------
// Huvudprogram:
int main()
{
string text;
string filnamn;
int histogram_abs[ANTAL_BOKSTAVER] = {0};
double histogram_rel[ANTAL_BOKSTAVER] = {0.0};
filnamn = namn_pa_fil(filnamn);
text = inlasning(filnamn);
berakna_histogram_abs(text, histogram_abs);
skriv_histogram_abs(histogram_abs);
abs_till_rel(text, histogram_abs, histogram_rel); //Ber‰kning fˆr att omvandla absolut fˆrekomst (st) av varje bokstav till relativ fˆrekomst (%)
plotta_histogram_rel(histogram_rel); //Ett histogram med hur stor relativ fˆrekomst i % av varje bokstav A, b, c...., x, y, z som finns i variabeln 'text'
tolka(histogram_rel); //Anger vilket sprÂk som str‰ngen i variabeln 'text' troligen ‰r skriven pÂ
string sluta;
while (sluta != "ja")
{
cin >> sluta;
}
return 0;
}
//--------------------------------------------------------
// Funktionsdefinitioner:
string namn_pa_fil(string filnamn) //Namn p fil som ska kontrolleras anges
{
cout << "Vad heter filen du vill testa?: " << endl;
getline(cin, filnamn);
if (filnamn.rfind(".txt") == string::npos) //Kontrollerar om filnamnet ha .txt - format
{
filnamn.append(".txt"); //L‰gger till ‰ndelsen .txt om det ej angavs
}
return filnamn;
} //Funktionen namn_pa_fil fungerar felfritt
string inlasning(const string& filnamn) //L‰ser in angiven filen
{
string tmpString; //Skapar en tempor‰r str‰ng
string returneradText;
ifstream fin(filnamn.c_str()); //Skapar objektet fin
if (!fin) //Kontrollerar om den angiven fil existerar
{
cout << "Det finns ingen fil med namnnet " << filnamn << endl;
exit(EXIT_FAILURE); //Avslutar programmet
}
else
{
while (getline(fin, tmpString))
{
returneradText += tmpString;
}
}
return returneradText;
}
void berakna_histogram_abs(const string& text, int(&frekvens)[ANTAL_BOKSTAVER])
{
cout << "\nResultat för bokstäverna A-Z " << endl;
cout << "\nTotala tecken i texten: " << text.size() << endl;
for (char bokstav : text)
{
int index;
if (bokstav >= 'a' && bokstav <= 'z')
{
index = bokstav - 'a';
frekvens[index]++;
}
if (bokstav >= 'A' && bokstav <= 'Z')
{
index = bokstav - 'A';
frekvens[index]++;
}
}
}
void skriv_histogram_abs(const int(&frekvens)[ANTAL_BOKSTAVER]) //Detta histogram skriver ut den absoluta fˆrekomsten av varje bokstav, tex att det finns 2 st 'R' i variabeln 'text' som innehÂller str‰ngen "Skriv en historia"
{
//Skriv ut frekvensen fˆr de bokst‰ver som finns
cout << "\nBokstav:\tAbsolut frekvens:\n";
for (int i = 0; i < ANTAL_BOKSTAVER; i++)
{
char b = char(i + 'A');
cout << b << ": " << "\t" << frekvens[i] << endl;
}
}
void abs_till_rel(const std::string& text, int(&histogram_abs)[ANTAL_BOKSTAVER], double(&histogram_rel)[ANTAL_BOKSTAVER]) //Denna funktion ska omvandla absoluta (stycken) fˆrekomsten av varje bokstav till en relativ (andel i %) fˆrekomst av varje bokstav
{
int antal = text.size();
for (int i = 0; i < ANTAL_BOKSTAVER; i++)
{
histogram_rel[i] = ((double)histogram_abs[i] / antal) * 100.0; //Bokst‰vernas relativa fˆrekomst ber‰knas, frÂn stycken till andel i %
//cout << histogram_rel[i] << endl;
}
}
void plotta_histogram_rel(const double(&histogram_rel)[ANTAL_BOKSTAVER]) //Denna funktion ska nu plotta den relativa fˆrekomsten av varje bokstav, tex att det finns 0,3 % 'R' i variabeln 'text' som innehÂller str‰ngen "Skriv en historia"
{
char bokstav;
cout << "\nBokstav:\tRelativ frekvens:\n";
for (int i = 0; i < ANTAL_BOKSTAVER; i++)
{
double k = 0.5;
bokstav = 'A' + i;
cout << bokstav << ": ";
while (k < histogram_rel[i])
{
cout << "*";
k += 0.5;
}
cout << endl;
}
}
void tolka(const double(&histogram_rel)[ANTAL_BOKSTAVER])
{
double minsta_skillnaden; //Minsta skillnaden mellan frekvenser i texten och sprÂken
int minsta_index; //Index fˆr det sprÂk med minsta skillnaden
string sprak[ANTAL_SPRAK] = { "engelska", "franska", "svenska", "tyska" };
double skillnad = 0.0; //Skillnaden mellan frekvens i texten och frekvens i sprÂken
double summa[ANTAL_SPRAK] = { 0.0, 0.0, 0.0, 0.0 }; //Summan av kvadraterna av de olika skillnaderna
for (int j = 0; j < ANTAL_SPRAK; j++)
{
for (int i = 0; i < ANTAL_BOKSTAVER; i++)
{
skillnad = (TOLK_HJALP[j][i] - histogram_rel[i]); //Ber‰knar skillnad i frekvens fˆr varje bokstav i texten och sprÂken
summa[j] = summa[j] + (skillnad * skillnad); //Summerar kvadraterna av skillnader i frekvens
}
minsta_skillnaden = summa[j]; //Startgissning
minsta_index = j; //Startgissning
for (int k = 0; k < ANTAL_SPRAK; k++)
{
if (summa[k] < minsta_skillnaden) //Kontroll om summan ‰r mindre ‰n minsta skillnaden
{
minsta_skillnaden = summa[k]; //Uppdaterar den nya minsta skillnaden
minsta_index = k; //Uppdaterar index fˆr det sprÂk med minst skillnad
}
}
}
cout << "Engelska har kvadratsumman: " << summa[0] << endl;
cout << "Franska har kvadratsumman: " << summa[1] << endl;
cout << "Svenska har kvadratsumman: " << summa[2] << endl;
cout << "Tyska har kvadratsumman: " << summa[3] << endl;
cout << "Det är mest troligt att språket är: " << sprak[minsta_index] << endl;
}
Du kan t.ex. skicka med en int antal (via referens) till berakna_histogram_abs, så kan den räkna ut det faktiska antalet tecken. Sedan skickar du 'antal' till de andra funktionerna.
Laguna skrev:Du kan t.ex. skicka med en int antal (via referens) till berakna_histogram_abs, så kan den räkna ut det faktiska antalet tecken. Sedan skickar du 'antal' till de andra funktionerna.
Menar du så här (plockade ut det relevanta):
int berakna_histogram_abs(const string& text, int(&frekvens)[ANTAL_BOKSTAVER], int& antal);
void skriv_histogram_abs(const int(&frekvens)[ANTAL_BOKSTAVER]);
void abs_till_rel(const std::string& text, int(&histogram_abs)[ANTAL_BOKSTAVER], double(&histogram_rel)[ANTAL_BOKSTAVER], int &antal);
int main()
{
string text;
string filnamn;
int antal;
int histogram_abs[ANTAL_BOKSTAVER] = {0};
double histogram_rel[ANTAL_BOKSTAVER] = {0.0};
filnamn = namn_pa_fil(filnamn); //Tar emot filens namn frÂn anv‰ndaren,
text = inlasning(filnamn); //l‰ser in str‰ngen "Skriv en historia" som finns i filen liten_fil.txt och lagrar den i variabeln 'text'
berakna_histogram_abs(antal, histogram_abs); //Ber‰knar hur mÂnga st A, b, c...., x, y, z som finns i variabeln 'text' skriv_histogram_abs(histogram_abs); //Ett histogram med hur mÂnga stycken bokst‰ver A, b, c...., x, y, z som finns i variabeln 'text'. Behövs ej skrivas ut i uppgift B, så kommenterar bort raden.
abs_till_rel(antal, histogram_abs, histogram_rel); //Ber‰kning fˆr att omvandla absolut fˆrekomst (st) av varje bokstav till relativ fˆrekomst (%)
plotta_histogram_rel(histogram_rel); //Ett histogram med hur stor relativ fˆrekomst i % av varje bokstav A, b, c...., x, y, z som finns i variabeln 'text'
tolka(histogram_rel); //Anger vilket sprÂk som str‰ngen i variabeln 'text' troligen ‰r skriven pÂ
string sluta;
while (sluta != "ja")
{
cin >> sluta;
}
return 0;
}
int berakna_histogram_abs(const string& text, int(&frekvens)[ANTAL_BOKSTAVER], int &antal)
{
cout << "\nResultat för bokstäverna A-Z " << endl;
cout << "\nTotala tecken i texten: " << text.size() << endl;
for (char bokstav : text)
{
int index;
if (bokstav >= 'a' && bokstav <= 'z')
{
index = bokstav - 'a';
frekvens[index]++;
}
if (bokstav >= 'A' && bokstav <= 'Z')
{
index = bokstav - 'A';
frekvens[index]++;
}
}
return antal;
}
void skriv_histogram_abs(const int(&frekvens)[ANTAL_BOKSTAVER]) //Detta histogram skriver ut den absoluta fˆrekomsten av varje bokstav, tex att det finns 2 st 'R' i variabeln 'text' som innehÂller str‰ngen "Skriv en historia"
{
//Skriv ut frekvensen fˆr de bokst‰ver som finns
cout << "\nBokstav:\tAbsolut frekvens:\n";
for (int i = 0; i < ANTAL_BOKSTAVER; i++)
{
char b = char(i + 'A');
cout << b << ": " << "\t" << frekvens[i] << endl;
}
}
void abs_till_rel(const std::string& text, int(&histogram_abs)[ANTAL_BOKSTAVER], double(&histogram_rel)[ANTAL_BOKSTAVER], int &antal) //Denna funktion ska omvandla absoluta (stycken) fˆrekomsten av varje bokstav till en relativ (andel i %) fˆrekomst av varje bokstav
{
for (int i = 0; i < ANTAL_BOKSTAVER; i++)
{
histogram_rel[i] = ((double)histogram_abs[i] / antal) * 100.0; //Bokst‰vernas relativa fˆrekomst ber‰knas, frÂn stycken till andel i %
}
}
Jag får felmeddelande i main() vid anropet för berakna_histogram_abs() och abs_till_rel() som säger "No matching function for call" för båda funktionerna. Detta är min första kurs i programmering, så har en del svårigheter! Ledsen om jag inte förstår så snabbt! :)
Just så, men du får sätta argumentet 'antal' på samma plats i anropet som i deklarationen, t. ex. sist. Nu är det först ibland.
Laguna skrev:Just så, men du får sätta argumentet 'antal' på samma plats i anropet som i deklarationen, t. ex. sist. Nu är det först ibland.
Tusen tack Laguna!!
Nu funkar det :)