Felmeddelande "Segmentation Fault" pga värdet försöker ändras utanför array
Hej,
När jag kör detta program så får jag felmeddelandet "segmentation fult" eftersom ett värde försöker andras utanför arrayen "histogram_abs" i funktionen "berakna_histogram_abs()". Jag har stirrat mig blind på koden och behöver hjälp! Jag fick feedback från en assistent som rättade min uppgift och assistenten sa: "Kolla på vilka index du försöker uppdatera histogram_abs i funktionen berakna_histogram_abs."
Någon som har en idé på hur man åtgärdar detta felmeddelande? Se kod nedan.
Tacksam för svar!
#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
//--------------------------------------------------------
// H‰r kommer klassdeklarationen
class Text
{
private: //Attribut
string text; //Textsträng för analys
int histogram_abs[ANTAL_BOKSTAVER]; //Array, innehåller absoluta histogrammet, längen är 26
double histogram_rel[ANTAL_BOKSTAVER]; //Array, innehåller relativa histogrmmet
int antal; //Attribut som håller reda på antal bokstäver i histogrammet
public: //Metoder
Text(); //Standardkonstruktor
void set_text(string ny_text); //Metod (funktion) som sätter värdet på textsträngen i klassen
bool berakna_histogram_abs(); //Beräknar ett bokstavshistogram av texten, dvs antal bokstäver i histogrammet
void skriv_histogram_abs(); //Skriver ut bokstavshistogrammet
void abs_till_rel(); //Metod som beräknar relativt histogram
void plotta_histogram_rel(); //Metod som plottar relativa histogrammet med * (en procent är två symboler)
void berakna_histogram(); //Gör inga nya beräkningar av histogrammet, men ska anropa berakna_histogram_abs() och abs_till_rel(). Det absoluta beräknas först och sedan det relativa histogrammet. Det relativa histogrammet ska bara beräknas om det absoluta histogrammet innehåller bokstäver.
string tolka(); //Metoden jämför beräknat relativt histogram med fyra fördefinerade språkhistogram
};
string namn_pa_fil(string namn);
string inlasning(const string& namn);
// -------------------------------------------------------
// Huvudprogram:
int main()
{
// Deklarera variabler
string text;
string filnamn;
bool hist_OK;
Text min_text; // Ett objekt av typen Text skapas
filnamn = namn_pa_fil(filnamn);
text = inlasning(filnamn);
min_text.set_text( text ); //Skickar strängen 'text' till objektet minText
// Ber‰kna och skriv ut histogrammet
//hist_OK = min_text.berakna_histogram_abs( );
//min_text.abs_till_rel();
min_text.berakna_histogram();
min_text.skriv_histogram_abs( );
min_text.plotta_histogram_rel();
min_text.tolka();
return 0;
}
// -------------------------------------------------------
// H‰r skriver du klassimplementationen
Text::Text() //Skapar och nollställer standardkonstruktorn
{
text="";
for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
histogram_abs[i]=0;
}
antal=0;
}
void Text::set_text(string ny_text) //Tilldelar variabeln text ett värde
{
text = ny_text;
}
bool Text::berakna_histogram_abs() //Beräknar förekomst av olika bokstäver
{
for (int i=0; i<ANTAL_BOKSTAVER; i++)
{
histogram_abs[i] = 0; //Nollställer frekvensen
}
antal=0;
for(unsigned int i = 0; i<text.length(); i++)
{
char temp = text[i];
if(isalpha(temp)) //Om tecknet är en bokstav så vill vi öka med 1
antal++;
if(isupper(text[i])) //Om bokstaven är en stor bokstav så ändras den till en liten
temp=tolower(temp);
histogram_abs[(temp - 'a')]++; // frekvensräknaren för den valda bokstaven ökas med 1
}
if(antal==0) //Om antalet bokstäver är noll så ges boolen värdet false, annars är den true
return false;
else
return true;
}
void Text::skriv_histogram_abs()
{
cout << "\nResultat för bokstäverna A-Z " << endl;
cout << "\nTotala tecken i texten: " << text.size() << endl;
cout <<"\nBokstav:\tFrekvens:\n";
for (int i=0; i<ANTAL_BOKSTAVER; i++)
{
char Bokstav = char (i+'A');
if (histogram_abs[i])
cout << Bokstav << " \t" << histogram_abs[i] <<endl;
else
cout << Bokstav << " 0" << endl;
}
}
void Text::abs_till_rel()
{
for (int i=0; i<ANTAL_BOKSTAVER; i++)
{
histogram_rel[i] = (float(histogram_abs[i]))/(float(antal))*100;
}
}
void Text::plotta_histogram_rel()
{
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 Text::berakna_histogram()
{
bool histOK=Text::berakna_histogram_abs();
if (histOK)
{
Text::abs_till_rel();
}
else
cout << "Texten innehåller inga bokstäver.";
}
string Text::tolka()
{
double minst_skillnad;
int minst_index;
string sprak[ANTAL_SPRAK]={"engelska", "franska", "svenska", "tyska"};
double skillnad = 0.0;
double summa[ANTAL_SPRAK]={0.0, 0.0, 0.0, 0.0};
for(int j=0; j<ANTAL_SPRAK; j++)
{
for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
skillnad = (TOLK_HJALP[j][i] - histogram_rel[i]);
summa[j] = summa[j]+(skillnad*skillnad);
}
minst_skillnad = summa[j];
minst_index = j;
for(int k=0; k<ANTAL_SPRAK; k++ )
{
if(summa[k]<minst_skillnad)
{
minst_skillnad = summa[k];
minst_index = k;
}
}
}
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 texten är skriven på: " << sprak[minst_index] << endl;
return 0;
}
//--------------------------------------------------------
// Funktionsdefinitioner:
string namn_pa_fil(string filnamn)
{
cout << "Vad heter filen du vill testa?: " << endl;
getline(cin, filnamn);
if (filnamn.rfind(".txt") == string::npos)
{
filnamn.append(".txt");
}
return filnamn;
}
string inlasning(const string& filnamn)
{
string tmpString;
string returneradText;
ifstream fin(filnamn.c_str());
if (!fin)
{
cout << "Det finns ingen fil med namnnet " << filnamn << endl;
exit(EXIT_FAILURE);
}
else
{
while (getline(fin, tmpString))
{
returneradText += tmpString;
}
}
return returneradText;
}
Du verkar uppdatera histogrammet även om det inte är en bokstav du får in. Vad händer då?
Vi behöver se indata också för att se varför det blir fel, men använd assistentens tips och skriv ut värdet av temp-'a' precis innan du använder det som index, så får du se om det blir ett olämpligt värde.
Gör utskrifter för att titta vad variablerna har för värde där felet uppstår.
haraldfreij skrev:Du verkar uppdatera histogrammet även om det inte är en bokstav du får in. Vad händer då?
Man kan utgå från att endast bokstäver läses in, dvs man behöver endast hantera input/inläsning av bokstäverna A-Z (a-z). Det är ju iaf skönt att ej felhantering krävs för uppgiften! :)
Laguna skrev:Vi behöver se indata också för att se varför det blir fel, men använd assistentens tips och skriv ut värdet av temp-'a' precis innan du använder det som index, så får du se om det blir ett olämpligt värde.
Indata är bl.a en textfil som innehåller följande text:
"aBbCcCDDDDEEeFFGhhiiiJJJJKkkLLmMnooPpPQQQQRRrSSTuuVVvWwWwXXxyyyZ"
Men det kan också vara en textfil som innehåller en lååååång text skriven på engelska, tyska, svenska eller franska och så avgör programmet vilket text den är skriven på. Men när jag testkör programmet så använder jag textfilen med bara det som står ovan.
Tror du att du kan kolla på hur det ser ut om du har denna rad som input? Problemet är att jag inte får ett felmeddelande, utan det är assistenten som får det när han kör koden. Så jag har jättesvårt att hitta felet själv!
"aBbCcCDDDDEEeFFGhhiiiJJJJKkkLLmMnooPpPQQQQRRrSSTuuVVvWwWwXXxyyyZ"
Om assistenten får felet men inte du så måste ni reda ut vad ni gör olika. Tittar du på när assistenten kör?
Gör det jag föreslog och låt assistenten köra igen.
En sak som är fel är i alla fall att du hanterar alla tecken på samma sätt, även sådana som inte är bokstäver. Vad blir temp-'a' då?
shiela skrev:Laguna skrev:Vi behöver se indata också för att se varför det blir fel, men använd assistentens tips och skriv ut värdet av temp-'a' precis innan du använder det som index, så får du se om det blir ett olämpligt värde.
Indata är bl.a en textfil som innehåller följande text:
"aBbCcCDDDDEEeFFGhhiiiJJJJKkkLLmMnooPpPQQQQRRrSSTuuVVvWwWwXXxyyyZ"
Men det kan också vara en textfil som innehåller en lååååång text skriven på engelska, tyska, svenska eller franska och så avgör programmet vilket text den är skriven på. Men när jag testkör programmet så använder jag textfilen med bara det som står ovan.
Tror du att du kan kolla på hur det ser ut om du har denna rad som input? Problemet är att jag inte får ett felmeddelande, utan det är assistenten som får det när han kör koden. Så jag har jättesvårt att hitta felet själv!
"aBbCcCDDDDEEeFFGhhiiiJJJJKkkLLmMnooPpPQQQQRRrSSTuuVVvWwWwXXxyyyZ"
Det fetade. Om assistenten får fel men inte du då kör ni olika program. Skicka ditt program till assistenten som fungerar så löser det sig. Jag tror du rättat felet omedvetet i din kod. Om din kod bara får bokstäver som input då ser jag inga fel (, så klart positivt att skriva en if-sats så det bara lagras bokstäver i histogrammet ändå. Veta att input data är rätt till en viss funktion är sällan fel), kan absolut vara så att assistenten har en text som innehåller något tecken som inte är en bokstav.
Aerius skrev:shiela skrev:Laguna skrev:Vi behöver se indata också för att se varför det blir fel, men använd assistentens tips och skriv ut värdet av temp-'a' precis innan du använder det som index, så får du se om det blir ett olämpligt värde.
Indata är bl.a en textfil som innehåller följande text:
"aBbCcCDDDDEEeFFGhhiiiJJJJKkkLLmMnooPpPQQQQRRrSSTuuVVvWwWwXXxyyyZ"
Men det kan också vara en textfil som innehåller en lååååång text skriven på engelska, tyska, svenska eller franska och så avgör programmet vilket text den är skriven på. Men när jag testkör programmet så använder jag textfilen med bara det som står ovan.
Tror du att du kan kolla på hur det ser ut om du har denna rad som input? Problemet är att jag inte får ett felmeddelande, utan det är assistenten som får det när han kör koden. Så jag har jättesvårt att hitta felet själv!
"aBbCcCDDDDEEeFFGhhiiiJJJJKkkLLmMnooPpPQQQQRRrSSTuuVVvWwWwXXxyyyZ"
Det fetade. Om assistenten får fel men inte du då kör ni olika program. Skicka ditt program till assistenten som fungerar så löser det sig. Jag tror du rättat felet omedvetet i din kod. Om din kod bara får bokstäver som input då ser jag inga fel (, så klart positivt att skriva en if-sats så det bara lagras bokstäver i histogrammet ändå. Veta att input data är rätt till en viss funktion är sällan fel), kan absolut vara så att assistenten har en text som innehåller något tecken som inte är en bokstav.
Tack för hjälpen! Jag tror att jag vet vad jag gjorde för fel... (Jag hade inte koll på att filen man läser in ska ligga i Debugging mappen när man kör i Xcode, så får nog ta nya tag med uppgiften och kolla vad det är frågan om nu när jag vet detta)
i funktionsdefinitionen
bool Text::berakna_histogram_abs()
under
for(unsigned int i =0; i<text.length(); i++)
finns en if-sats
if(isalpha(temp))
denna if-sats ger möjligheten att den som skrivit programmet tänkt sig att det ibland inte kommer en bokstav. Sätt måsvingar runt det som är under denna if-sats så du är säker på att histogram_abs[(temp - 'a')]++ bara uppdateras med bokstäver.
Aerius skrev:i funktionsdefinitionen
bool Text::berakna_histogram_abs()
under
for(unsigned int i =0; i<text.length(); i++)
finns en if-sats
if(isalpha(temp))
denna if-sats ger möjligheten att den som skrivit programmet tänkt sig att det ibland inte kommer en bokstav. Sätt måsvingar runt det som är under denna if-sats så du är säker på att histogram_abs[(temp - 'a')]++ bara uppdateras med bokstäver.
Tack så mycket!!