Just nu i M3-nätverket
Jump to content

Programmet krachar vid längre text


AnnaGK

Recommended Posts

Sitter med näst sista uppgiften i kursen och har väl kommit en liten bit på vägen att förstå C++ underbara värld.

Men jag behöver er hjälp ytterligare en gång. Har skrivit nedan program och det fungerar om jag läser in en kortare text. Men så fort jag läser in exempeltexterna som inte är några längre texter (17 kb är filen bara på ca 2000 tecken)så kraschar programmet och jag får upp en ruta om att programmet måste avslutas. Kan ju vara något lokalt på min burk. Men ni brukar ju se direkt om man skrivit något fel, så snälla! Lite hjälp tack att kontrollera koden.

#include <string>
#include <cctype>
#include <iostream>
#include <fstream>
#include <iomanip>
#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:
 string text;
 int histogram_abs[ANTAL_BOKSTAVER];
 double histogram_rel[ANTAL_BOKSTAVER];
 int tot_ant_bok;


public:
 Text();	// Standardkonstruktor


 void setText(string nyText); // Ger variabeln text ett värde
 bool beraknaHistogramAbs();  // Beräknar bokstavshistogram
 void skrivHistogramAbs();	// Skriver ut ett bosktavshistogram
 void absTillRel();   		// Beräknar relativt bokstavshistogram
 void plottaHistogramRel();   // Plottar ut relativa histogrammet med symboler
 void beraknaHistogram(); 	// Har hand om de olika beräkningsmetoderna
 string tolka();          	// Jämför det relativa histogrammet med 4 olika språk och
                      		// ger ett förslag på vilket språk texten kan vara skrivet på.


};


 // Nya metoder:
void namn_pa_fil(string &filnamn);
void inlasning(string &filnamn, string &text);

// -------------------------------------------------------

// Huvudprogram:

int main()
{
// Deklarera variabler
 string text;
 bool histOK;
 Text minText;  // Ett objekt av typen Text skapas
 string filnamn;

 // Läs in en rad med text från tangentbordet
 //cout <<"Ge en rad med text:" << endl;
 //getline(cin,text)

  namn_pa_fil(filnamn);
  inlasning(filnamn, text);

 // Skicka strängen text till objektet minText
 minText.setText( text );

 minText.beraknaHistogram();


 //histOK = minText.beraknaHistogramAbs( );
 //-----------tabort
  // minText.absTillRel();

 //----------

 //if(histOK)
  minText.skrivHistogramAbs( );
// else if(!histOK)
  // cout << "Texten inneh\x94ll inga bokst\x84ver.";

 minText.plottaHistogramRel();
 minText.tolka();

 return 0;
}

// -------------------------------------------------------
// Här skriver du klassimplementationen
// Standardkonstruktor
Text::Text()
{
 text="";
 for(int i=0;i<ANTAL_BOKSTAVER;i++)
{
 	histogram_abs[i]=0;
}

 for(int i=0;i<ANTAL_BOKSTAVER;i++)
{
 	histogram_rel[i]=0.0;
}

tot_ant_bok=0;

}


// ========================================================
// Ger variabeln text ett värde.
void Text::setText(string nyText)
{
text=nyText;
}
// ========================================================
// Beräknar ett bokstavshistogram samt returnerar sant om bokstäver finns
bool Text::beraknaHistogramAbs()
{
 	//Nollställ frekvens:
for (int i=0; i<ANTAL_BOKSTAVER; i++)
histogram_abs[i] = 0;

 for(unsigned int i = 0; i<text.length(); i++)
  { char temp = text[i];
if(isalpha(temp)) // ökar räknaren med 1 om tecknet är en bokstav
  	tot_ant_bok++;

if(isupper(text[i])) // om bokstaven är en versal så ändras den till en gemen
  	temp=tolower(temp);

histogram_abs[(temp - 'a')]++; // frekvensräknaren för den valda bokstaven ökas med 1
}

 if(tot_ant_bok==0)
return false;
 else
return true;

}
// ========================================================
// Skriver ut ett bokstavshistogram
void Text::skrivHistogramAbs()
{
 cout << endl << "Totalt antal bokst\x84ver: " << tot_ant_bok << endl;

 for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
 	cout << char('A'+i) << "   " << histogram_abs[i] << endl;
}
}
// ========================================================
// Beräknar relativt bokstavshistogram
void Text::absTillRel()
{
 for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
 	histogram_rel[i]=100*(double(histogram_abs[i])/double(tot_ant_bok));
}
}
// ========================================================
// Plottar ut relativa histogrammet med symboler
void Text::plottaHistogramRel()
{
 int j;

 for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
 	cout << char('A'+i) << "   ";
 	j = 2*histogram_rel[i];

 	for(int k=0; k<j; k++)
{
        cout << '*';
      }
 	cout << endl;
}
}
// ========================================================
// Har hand om de olika beräkningsmetoderna
void Text::beraknaHistogram()
{
  //Nollställ frekvens:
for (int i=0; i<ANTAL_BOKSTAVER; i++)
histogram_abs[i] = 0;

 for(unsigned int i = 0; i<text.length(); i++)
  { char temp = text[i];
if(isalpha(temp)) // ökar räknaren med 1 om tecknet är en bokstav
  	tot_ant_bok++;

if(isupper(text[i])) // om bokstaven är en versal så ändras den till en gemen
  	temp=tolower(temp);

histogram_abs[(temp - 'a')]++; // frekvensräknaren för den valda bokstaven ökas med 1
}

   	if(tot_ant_bok==0)
   	cout << "Texten innehöll inga bokst\x84ver.";

       	else
   	for(int i=0; i<ANTAL_BOKSTAVER; i++)
   	{
       	histogram_rel[i] = 0.0;
       	histogram_rel[i]=100*(double(histogram_abs[i])/double(tot_ant_bok));
   	}
}

// Jämför det relativa histogrammet med 4 olika språk och ger förslag på vilekt språk texten kan vara skrivet på.

string Text::tolka()
{
double skillnad=0.0;
double minsta;
double sum[ANTAL_SPRAK];
int minIndex;
string spraknamn[4]={"engelska", "franska", "svenska", "tyska"};
for(int j=0; j<ANTAL_SPRAK; j++)
{
   	for (int i=0; i<ANTAL_BOKSTAVER; i++)
   	{
       	skillnad=TOLK_HJALP[j][i]- histogram_rel[i];
       	sum[j]= sum[j]+ skillnad*skillnad;
   	} //kvadratskillnad

   	cout << "Kvadratsumman f\x94r " ;
   	cout << spraknamn[j] << " " << sum[j] <<endl;

   	minsta=sum[j];
   	minIndex=j;
   	for(int k=0;k<ANTAL_SPRAK;k++)
   	{
       	if(minsta>sum[k]){minsta=sum[k];minIndex=k;}
   	}
}
cout << "Texten \x84r sannolikt skriven p\x86 " << spraknamn[minIndex];

}

//--------------------------------------------------------
 // Nya metoder:
// Funktionen namn_pa_fil
void namn_pa_fil(string &filnamn)
{
cout<<"Vad heter filen du vill testa: ";
getline(cin,filnamn);

{
   	int i = filnamn.rfind( ".txt" );
   	{
       	if(i == string::npos)
       	{
           	filnamn.append( ".txt" );
       	}
   	}
}

}
// Funktionen inlasning
void inlasning(string &filnamn, string &text)
{
//öpnnar filen för läsning
// skapa objektet fin
ifstream fin(filnamn.c_str() );

   	//Felkontroll
   	if(!fin)
   	{
       	cout << "Det finns ingen fil med namnnet " << filnamn << endl;
       	exit(EXIT_FAILURE);
   	}


   	//while (!fin.eof())
   	string tmpString;
       	while (getline(fin, tmpString))
       	{
           	for (int i=0; i<=(int) text.length()-1; i++)
           	text.at(i);
           	text +=tmpString;
       	}
}

Link to comment
Share on other sites

Är lite för trött idag för att läsa igenom din kod, men jag har en sidorelaterad motfråga. Har ni i kursen inte fått lära er använda någon debugger? Med de kunskaperna hade du direkt själv kunna spåra var i programmet det går snett.

Om svaret på frågan är nej, ställ kursansvarig mot väggen och begär en förklaring :rolleyes:

Link to comment
Share on other sites

I brist på debugger är det ju klassiskt att köra med utskrifter i programmet för att ta reda på hur långt det kommer egentligen.

 

Jag är lite undrade över raden:

text.at(i);

Link to comment
Share on other sites

Jag har just börjat och räknat ut ungefär radien mha pii, men debuggern vi använder är det inget fel på tror jag, även om jag inte kan tolka den än :rolleyes:. Den ger följande på din kod.

 

eforum.cpp: In function ‘int main()’:

eforum.cpp:82: warning: unused variable ‘histOK’

eforum.cpp: In member function ‘std::string Text::tolka()’:

eforum.cpp:265: warning: no return statement in function returning non-void

eforum.cpp: In function ‘void namn_pa_fil(std::string&)’:

eforum.cpp:278: warning: comparison between signed and unsigned integer expressions

eforum.cpp: In function ‘void inlasning(std::string&, std::string&)’:

eforum.cpp:297: error: ‘EXIT_FAILURE’ was not declared in this scope

eforum.cpp:297: error: ‘exit’ was not declared in this scope

Link to comment
Share on other sites

Jag gissar att ditt problem kan ha att göra med de svenska tecknen å, ä och ö.

 

Skapa en fil med ett enda tecken, exempelvis tecknet 'a' och testa om det fungerar att läsa filen.

Om det fungerade så skapa en annan fil som endast innehåller tecknet 'å' (ta ej med '), om programmet crashar så beror det troligtsvis på hur ditt system behandlar de svenska tecknen å, ä och ö. I vissa system kan dessa tecken representeras i typen char i andra inte. Detta beror på följande: En char är en byte lång. Men en char är inte bara ett tecken det är också en heltalsvariabel som kan innehålla små tal. När du matar in ett tecken i en char-variabel kommer den i verkligheten att innehålla talets ordningsnummer i det teckenkodsystem som används på din dator. I heltals variabler används oftast en bit till att representera om det är ett positivt eller negativt tal. Datatypen är då signed, t ex signed int. Om alla bitarna används för talvärdet kan endast positiva tal representeras. En sådan typ kallas då unsigned. Så är också fallet med typen char, som vanligen har varit just signed char. I så fall kan bara tal mellan 0 - 127 representeras (å, ä och ö representeras alla av ett tal > 127).

 

Om man debuggar ditt program med en textfil som innehåller tecknet 'å' så crashar Visual studio på följande rad

_ASSERTE((unsigned)(c + 1)

där c har värdet -27. Tecknet 'å' har värdet 134 i ASCII tabellen

 

Om du i din kod gör följande tilldelning

char c = 'å';

så få c värdet -27 p.g.a overflow (134 > 127)

 

Hoppas att det hjälper dig att finna en lösning på problemet.

Link to comment
Share on other sites

  • 4 weeks later...

Tack för alla svar. Har äntligen tagit tag i detta igen och när jag fixat till alla småfel så får jag det att fungera till viss del:

1. Om jag inte lägger in beräkningarna beraknaHistogramAbs och absTillRel i beraknaHistogram så fungerar programmet som det ska. Men i uppgiften ingår det att man ska ha med beraknaHistogram.

 

2. Om jag lägger in koden

void Text::beraknaHistogram()

{

if (Text::beraknaHistogramAbs())

Text::absTillRel();

else if(!Text::beraknaHistogramAbs())

cout << "Texten inneh\x94ll inga bokst\x84ver.";

} Så fungerar det med texter som INTE innehåller siffror men så fort det innehåller siffror så krachar den. Kör jag direkt på beraknaHistogramAbs etc så fungerar det med siffror. Suck vad är det för fel? Snälla ni hjälp mig.

 

// Hanterar fallet med 26 bokstäver A-Z

#include <string>
#include <cctype>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#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:
 string text;
 int histogram_abs[ANTAL_BOKSTAVER];
 double histogram_rel[ANTAL_BOKSTAVER];
 int tot_ant_bok;


public:
 Text();	// Standardkonstruktor
~Text();	// destruktor


 void setText(string nyText); // Ger variabeln text ett värde
 bool beraknaHistogramAbs();  // Beräknar bokstavshistogram
 void skrivHistogramAbs();	// Skriver ut ett bosktavshistogram
 void absTillRel();   		// Beräknar relativt bokstavshistogram
 void plottaHistogramRel();   // Plottar ut relativa histogrammet med symboler
 void beraknaHistogram(); 	// Har hand om de olika beräkningsmetoderna
 string tolka();          	// Jämför det relativa histogrammet med 4 olika språk och
                      		// ger ett förslag på vilket språk texten kan vara skrivet på.


};


 // Nya metoder:
void namn_pa_fil(string &filnamn);
void inlasning(string &filnamn, string &text);

// -------------------------------------------------------

// Huvudprogram:

int main()
{
// Deklarera variabler
 string text;
 bool histOK;
 Text minText;  // Ett objekt av typen Text skapas
 string filnamn;

  namn_pa_fil(filnamn);
  inlasning(filnamn, text);

 // Skicka strängen text till objektet minText
 minText.setText( text );

 minText.beraknaHistogram();


 //histOK = minText.beraknaHistogramAbs( );
// minText.absTillRel();


 //if(histOK)
  minText.skrivHistogramAbs( );
// else if(!histOK)
  // cout << "Texten inneh\x94ll inga bokst\x84ver.";

 minText.plottaHistogramRel();
 minText.tolka();

 return 0;
}

// ========================================================
// Här skriver du klassimplementationen
// Standardkonstruktor
Text::Text()
{
 text="";
 for(int i=0;i<ANTAL_BOKSTAVER;i++)
{
 	histogram_abs[i]=0;
}

 for(int i=0;i<ANTAL_BOKSTAVER;i++)
{
 	histogram_rel[i]=0.0;
}

tot_ant_bok=0;

}
// ========================================================
Text::~Text()
{
 cout << "Nu stängs programmet"<< endl;
}

// ========================================================
// Ger variabeln text ett värde.
void Text::setText(string nyText)
{
text=nyText;
}
// ========================================================
// Beräknar ett bokstavshistogram samt returnerar sant om bokstäver finns
bool Text::beraknaHistogramAbs()
{
 	//Nollställ frekvens:
for (int i=0; i<ANTAL_BOKSTAVER; i++)
histogram_abs[i] = 0;

 for(unsigned int i = 0; i<text.length(); i++)
  { char temp = text[i];
	if(isalpha(temp)) // ökar räknaren med 1 om tecknet är en bokstav
  	tot_ant_bok++;

	if(isupper(text[i])) // om bokstaven är en versal så ändras den till en gemen
  	temp=tolower(temp);

	histogram_abs[(temp - 'a')]++; // frekvensräknaren för den valda bokstaven ökas med 1
}

 if(tot_ant_bok==0)
return false;
 else
return true;

}
// ========================================================
// Skriver ut ett bokstavshistogram
void Text::skrivHistogramAbs()
{
 cout << endl << "Totalt antal bokst\x84ver: " << tot_ant_bok << endl;

 for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
 	cout << char('A'+i) << "   " << histogram_abs[i] << endl;
}
}
// ========================================================
// Beräknar relativt bokstavshistogram
void Text::absTillRel()
{
 for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
 	histogram_rel[i]=100*(double(histogram_abs[i])/double(tot_ant_bok));
}
}
// ========================================================
// Plottar ut relativa histogrammet med symboler
void Text::plottaHistogramRel()
{
 int j;

 for(int i=0; i<ANTAL_BOKSTAVER; i++)
{
 	cout << char('A'+i) << "   ";
 	j = 2*histogram_rel[i];

 	for(int k=0; k<j; k++)
{
 	  	cout << '*';
 		}
 	cout << endl;
}
}
// ========================================================
// Har hand om de olika beräkningsmetoderna
void Text::beraknaHistogram()
{

if (Text::beraknaHistogramAbs())
   	Text::absTillRel();
else if(!Text::beraknaHistogramAbs())
cout << "Texten inneh\x94ll inga bokst\x84ver.";

}
// ========================================================
// Jämför det relativa histogrammet med 4 olika språk och ger förslag på vilekt språk texten kan vara skrivet på.

string Text::tolka()
{
double skillnad=0.0;
double minsta;
double sum[ANTAL_SPRAK];
int minIndex;
string spraknamn[4]={"engelska", "franska", "svenska", "tyska"};
for(int j=0; j<ANTAL_SPRAK; j++)
{
   	for (int i=0; i<ANTAL_BOKSTAVER; i++)
   	{
       	skillnad=TOLK_HJALP[j][i]- histogram_rel[i];
       	sum[j]= sum[j]+ skillnad*skillnad;
   	} //kvadratskillnad

   	cout << "Kvadratsumman f\x94r " ;
   	cout << spraknamn[j] << " " << sum[j] <<endl;

   	minsta=sum[j];
   	minIndex=j;
   	for(int k=0;k<ANTAL_SPRAK;k++)
   	{
       	if(minsta>sum[k]){minsta=sum[k];minIndex=k;}
   	}
}
cout << "Texten \x84r sannolikt skriven p\x86 " << spraknamn[minIndex];
return spraknamn[minIndex];
}

// ========================================================
 // Nya metoder:
// Funktionen namn_pa_fil
void namn_pa_fil(string &filnamn)
{
cout<<"Vad heter filen du vill testa: ";
getline(cin,filnamn);

{
   	int i = filnamn.rfind( ".txt" );
   	{
       	if(i == string::npos)
       	{
           	filnamn.append( ".txt" );
       	}
   	}
}

}
// Funktionen inlasning
void inlasning(string &filnamn, string &text)
{
//öpnnar filen för läsning
// skapa objektet fin
ifstream fin(filnamn.c_str() );

   	//Felkontroll
   	if(!fin)
   	{
       	cout << "Det finns ingen fil med namnnet " << filnamn << endl;
       	exit(EXIT_FAILURE);
   	}


   	//while (!fin.eof())
   	string tmpString;
       	while (getline(fin, tmpString))
       	{
           	for (int i=0; i<=(int) text.length()-1; i++)
           	//text.at(i);
           	text +=tmpString;
       	}
}

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.



×
×
  • Create New...