PizzaPat
PizzaPat

Reputation: 13

Segmentation fault (core dump) at the end of executing

I am writing a C++ program on Linux Ubuntu for my class. The program is supposed to find the frequency of a string(s) that user inputs. The frequency is calculated by the number of each character that appears in a sentence and then divided by the maximum characters in a sentence. After that I print out the asterisks based on how many percent of each character appear. Here is the code I wrote

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;
int main(){
string text;//partial text for each whitespace
string finalText;//String that has been concat
int totalLetter=0;//Total number of all letter
double storedValue[26];//Giving Result to each array
int i;//"for" statement counter declaring
int j;//"for" statement second counter declaring
int letters[26];//array to reducing ascii value on line 26
cout << "Enter the text at the prompt to calculate letter frequencies. " << endl <<
        "Enter DONE when finished with the input."<< endl;
while(text!="DONE"){//check the input, if it's not "DONE" then continue adding string
    cout<< "Enter a line of a text: ";
    std::getline(std::cin,text);
    if(text=="DONE")break;
    finalText = finalText + text;
}

char *charArray = new char[finalText.length()+1];//Converting string input to char type
std::strcpy(charArray,finalText.c_str());//Copying string to char


for(i=0; i<finalText.length(); i++){//reduce to smaller case
    if(charArray[i]>='A' && charArray[i]<='Z')
        charArray[i]=charArray[i]+32;
}
for(i=0; i<finalText.length(); i++){//set default for charArray to be 0
    if(charArray[i]<'a' && charArray[i]>'z'){
        charArray[i]=0;
    }
}

for(i=0; i<finalText.length(); i++){//calculate the total characters input
    if(charArray[i]>='a' && charArray[i]<='z'){
        totalLetter++;
    }
}

for(i=0; i<26; i++){//Set all storeValue to be 0 from a - z
    storedValue[i] = 0;
}
for(i=0; i<finalText.length(); i++){//convert letters to start at 0 as an 'a' from ascii code and so on
    letters[i]=(int)charArray[i]-97;
    storedValue[i] = 0;
}
for(i=0; i<finalText.length(); i++){//increment value in array for each letter
    for(j=0; j<26; j++){
        if(letters[i]==j)
            storedValue[j]++;
    }
}
    cout << endl;
cout << "A total of " << totalLetter << " letters of the alphabet were processed" << endl;

    cout << endl;
cout << "a b c d e f g h i j k l m n o p q r s t u v w x y z  %"<<endl;
//calculate the percent
for(i=0; i<26; i++){
    storedValue[i]=round((storedValue[i]/totalLetter)*100);
}

cout<<endl;

//Get Maximum Percent
int maxPercent=0;
int maxLetterPercent=0;
for(i=0; i<25; i++){
if(storedValue[i]>maxPercent){
    maxPercent=storedValue[i];
    maxLetterPercent=i;
    }
}

//Printing asterisk
for(i=0; i<maxPercent; i++){
    for(j=0; j<26; j++){
        if(storedValue[j]>0)
            cout<<"* ";
        else if(storedValue[j]<=maxPercent)
            cout<<"  "; 
}
cout<<" "<<i+1;
cout<<endl;
}

char finalCharMax = maxLetterPercent + 'a';
cout<<"The most common letter is " << finalCharMax << " with a frequency of " << maxPercent
    << " %";

cout<<endl;
    return 0;
}

After executing, it shows perfect result; the asterisks were in place as they should be. But my problem occurred when I started to input long sentence, for example I input

Enter a line of text: asd asd asd asd asd asd asd asd asd asd asd asd asd

and after I input "DONE", it gives junk result, the asterisks were messed up and at the end of executing, it showed the message

Segmentation fault (core dumped)

In this case, what did I do wrong?

Upvotes: 0

Views: 2545

Answers (2)

Tom Tanner
Tom Tanner

Reputation: 9354

It's always an indicator that you're overrunning the end of an array if everything works for a short input string and fails catastrophically for a long input string or one with 'unexpected' characters.

Use of a debugger would enable you to pinpoint where you are crashing

Your actual problem is here:

for(i=0; i<finalText.length(); i++){//convert letters to start at 0 as an 'a' from ascii code and so on
    letters[i]=(int)charArray[i]-97;
    storedValue[i] = 0;
}

as storedvalue has only 26 entries, so if your string is 27 or more characters long you'll start overwriting your stack.

In passing, why on earth do you convert your nice std::string to a char array? You're losing a lot of free functionality and checkability when you do that, and the std::string is sufficient for what you need, and as you don't delete[] charArray, you have a memory leak.

I'd not bother doing the checks on length and make storedvalue a 256 entry array (but remember that characters can be signed or unsigned depending on platform). Or better, use a std::map<char, int> to hold the counts.

Upvotes: 0

vershov
vershov

Reputation: 928

The problem is in this part of code. The letters array is 26 items lenght and when you are entering long text, stack is corrupted. It leads to segfault at the end of the main() function call.

for(i=0; i<finalText.length(); i++){//convert letters to start at 0 as an 'a' from ascii code and so on
    letters[i]=(int)charArray[i]-97;
    storedValue[i] = 0;
}
for(i=0; i<finalText.length(); i++){//increment value in array for each letter
    for(j=0; j<26; j++){
        if(letters[i]==j)
            storedValue[j]++;
    }
}

Upvotes: 1

Related Questions