Process exited prematurely with a SIGSEGV signal - c++

This code shows this SIGSEGV error, which I understand, is a segmentation error. Can someone please help!
The code returns the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string.
I am using this on a programming challenge so this is only a function.
So, If I input "aabcdef" it should return 2 because 'a' occurs twice. Input can contain alphabets as well as numerics.
int duplicateCount(const char* in)
{
int a[39]={0},b=0;
for(int i=0;i<strlen(in);i++)
{
if(in == NULL)
return 0;
if((int)in[i] < 97)
{
a[(int)in[i]]++;
}
a[tolower(in[i])-'a'+1]++;
}
for(int i=0;i<39;i++)
{
if(a[i]>1)
b++;
}
return b;
}

Problem is here
if((int)in[i] < 97)
{
a[(int)in[i]]++;
}
a[tolower(in[i])-'a'+1]++;
you may write outside of bounds which, as we know, has UB.
Fix
First you have to check if character is letter with isalpha(c)
Then you have to transform character to lower via tolower(c)
And sub the first low case letter in alphabet c - 'a'
Then you can index an array and increment its value.
Here is fixed code
Since we are in c++, you may use std::map
#include <iostream>
#include <map>
int main()
{
std::string text("aabbc");
std::map<char, int> letterCounter;
for(auto& it : text)
{
letterCounter[it]++;
}
for (auto& it : letterCounter)
{
if (it.second > 1)
{
std::cout << "Character " << it.first << " has appeared "
<< it.second << " times." << std::endl;
}
}
return 0;
}
Output
Character a has appeared 2 times.
Character b has appeared 2 times.

Related

Why do I have a line break?

there is a problem with the code. Displays an error "std::out_of_range at memory location". during debugging.
The task of the code is to find all the letters "A" in the text and delete them.
**ะก++ code:
**
#include <iostream>
#include <string>
using namespace std;
int main()
{
string a;
getline(cin, a);
int n = 0;
do {
n = a.find('a',1);
cout << n;
a.erase(n, 0);
cout << a;
} while (n != -1);
cout << a;
}
I tried to change int to double, but the program does not work correctly. However, the error disappears
There are two problems with this do-while loop
do {
n = a.find('a',1);
cout << n;
a.erase(n, 0);
cout << a;
} while (n != -1);
The first one is that you are starting to search the letter 'a' starting from the position 1 instead of the position 0.
The second one is that if the letter 'a' is not found then n is equal to std::string::npos and you are using this value in the call of erase. You need to check that n is not equal to std::string::npos before calling the member function erase.
And the call of erase in any case is incorrect.
Instead of the do-while loop it is better to use the for loop. For example
for ( std::string::size_type n; ( n = a.find( 'a' ) ) != std::string::npos; )
{
std::cout << n;
a.erase(n, 1 );
std::cout << a << '\n';
}
Also you should declare the variable n as having the type std::string::size_type.
And as #Ted Lyngmo wrote in a comment if your compiler supports C++ 20 then you can use standard C++ function erase defined for standard containers like
std::erase( a, 'a' );
to remove all occurrences of the letter 'a' in the string.

Function To Count occurrence of given string

#include<iostream>
using namespace std;
void check_exist_get_count(string str,char ch)
{
int counter=0;
for(int x=0;x<str.length();x++)
{
if(str[x]==ch)
counter++;
}
cout<<ch<<" : "<<counter;
}
int main ()
{
string str;
cin>>str;
for(int x=0;x<str.length();x++)
{
check_exist_get_count(str,str[x]);
}
return 0;
}
Without built in function i need to to count the occurence of letter but i have problem what condition i should use to check which make for loop not sending letter more than one time
example:in my code i get
input
aaabbc
output
a : 3 a : 3 a : 3 b : 2 b : 2 c : 1
but Required answer should be
a : 3 b : 2 c : 1
You're just iterating over the string once in your main function, and for every character in that string, again go over the whole string and count how many characters like that are in there.
What you don't do is track which characters you already have counted, that's why you count them multiple times. Don't nest loops (calling your function inside the first loop), but tear those things apart:
One option would be to do a first pass over the string, in which you just build a list of characters that are in the string, something like this:
std::set<char> chars;
for (char c: str)
{
chars.insert(c); // a set doesn't allow duplicate entries
// so you don't have to check yourself if it's already in there
}
Then you could, in a second loop, call count for each of the characters in the set. That would still be inefficient, though; you can use a map for keeping track what characters are as well as their count so far. Something like this:
Code to compute the histogram of character frequencies then could look something like this:
#include <iostream>
#include <map>
#include <string>
int main ()
{
std::string str("aaabbc");
std::map<char, size_t> charHistogram;
for (char c: str)
{
// if c not contained in map yet, it's automatically initialized to 0
++charHistogram[c];
}
for (auto const & p: charHistogram)
{
std::cout << p.first << " : " << p.second << " ";
}
return 0;
}
See code in cpp.sh
Another option to add to #codeling's answer. Same idea, but different implementation:
You can use an array to count the used letters.
First array position will tell you number of appearances for 'a', second position for 'b' and so on.
You could extend it to count uppercase and symbols.
You could also change the std::array for a size_t counts[26] array.
[Demo]
#include <array>
#include <iostream> // cout
#include <string>
int main()
{
const std::string s{"aaabbc"};
std::array<size_t, 26> counts{};
for (auto&& ch : s)
{
if (ch >='a' and ch <= 'z')
{
counts[ch - 'a']++;
}
}
for (char i{0}; i < counts.size(); ++i)
{
if (counts[i])
{
std::cout << static_cast<char>('a' + i) << ": " << counts[i] << "\n";
}
}
}

How to check if a character matches another character in a char array?

I'm currently trying to figure out how I can replace a certain character in a char array using a for loop to check each index position in the array. However, when I assign the correct character to the char variable "letterGuessed" and it is checked it instantly goes to the else statement. This leaves the character as an asterisks. This is the code below:
#include <iostream>
#include <cstring>
void hide_Word(char hide[], int size);
int main()
{
char hiddenWord[] = "Hello";
char displayWord[30] = { 0 };
int length = strlen(hiddenWord);
hide_Word(displayWord, length);
std::cout << hiddenWord << std::endl;
std::cout << displayWord << std::endl;
char letterGuessed;
std::cout << "Enter a character: ";
std::cin >> letterGuessed;
for (int i = 0; i < length; i++)
{
if (displayWord[i] == letterGuessed)
{
letterGuessed == displayWord[i];
}
else
{
std::cout << "*";
}
}
std::cout << std::endl;
std::cout << displayWord << std::endl;
std::cin.get();
return 0;
}
void hide_Word(char hide[], int size)
{
for (int i = 0; i < size; i++)
{
hide[i] = '*';
}
}
When I compile your code I get the warning
main.cpp|27|warning: statement has no effect [-Wunused-value]
for the line
letterGuessed == displayWord[i];
This, for one, means that what you do to make correctly guessed letters visible is achieving nothing. Reading and considering warning messages is really helpful, you know.
I guess that your goal here is to turn the "*", which you filled displayWord with, should be replaced by the correctly guessed character.
That would better be achieved by an assignment using =.
letterGuessed = displayWord[i]; /* still unhelpful */
But that line would still not achieve anything visible.
To change something in the displayWord, it should be what gets the guessed character as a new value, not the other way around.
displayWord[i] = letterGuessed;
This is however still not satisfying, because you don't do this in the right situation.
Let's have a look at the condition which determines when you do it.
if (displayWord[i] == letterGuessed) /* unhelpful */
This will trigger, when the guessed character is an asterisk "*", because displayWord is filled with asterisks early on.
Which means that the condition only triggers if the user guesses an asterisk, which is unlikely. Even if it happens, the result is to overwrite an asterisk with an asterisk.
The condition you need should not check the asterisk-filled displayWord, it should instead check the "Hello"-filled hiddenWord.
if (hiddenWord[i] == letterGuessed)
In total, the code should hence be
for (int i = 0; i < length; i++)
{
if (hiddenWord[i] == letterGuessed)
{
displayWord[i]=letterGuessed;
std::cout << letterGuessed;
}
else
{
std::cout << "*";
}
}
This turns an asterisk in the displayed word into the correctly guessed character at each found position.
Note that I added an output of the guessed letter, to complete the letter-by-letter output. I guess you want to delete that output, or the word-output after the loop, so that the filled in word is only seen once.
Output:
Hello
*****
Enter a character: l
**ll*
**ll*

How to fix iteration without a cause (with an input); in c++?

Just on a starting note, Please excuse the lack of c++ conventions and logic shown in this code. I'm still trying to get around formatting syntax for c++..
With this small part of a larger application building project, I am trying to create a 'data validation' type subroutine with integers and strings being the main test cases, the input coming from the intended user.
The problem is that each character of the variable input is being iterated over, even if the 'if statements' are outside of the 'for loop' (or in some other cases while loops).
An example of the error being:
Enter a value:f1o2o3
Your value is a string
Your value is a integer
Your value is a string
Your value is a integer
Your value is a string
Your value is a integer
The extra lines after the first Your value is a string and
Your value is a integer are unwanted.
I know that I could just instead return the boolean variable letexists or intexsits, with them both being iterated without a problem.
However this 'character iterating' problem has been a nuisance in other parts too and I cannot seem to find a definite, understandable fix anywhere.
I am used to using python so this 'iterating over every character while passing parameters' is quite new to me.
I have tried looking into what it could be for multiple days now. Both: searching online and asking others (in person showing them code that has problems) about the 'iteration over each character' problem, however, none seem to know why this happens.
I have solved this problem in the past by breaking a while(true) loop after the intended data value has been received, however I understand this is really bad practice and therefore want to figure out how I can improve data validation.
#include <iostream> // for std::cin, std::cout
#include <string> // for string datatype
#include <algorithm> // for std::find
#include <iterator> // for std::begin, std::end
using namespace std;
// If the 'cout's are changed to returning functions I will change this to a function itself (using int datacheck(...){...})
void datacheck(string &i) {
const char nums[] = { '0','1','2','3','4','5','6','7','8','9','\0' };
const char alph[] = { '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','\0' };
for (char& c : i) {
bool intexists = find(begin(nums), end(nums), c) != end(nums);
bool letexists = find(begin(alph), end(alph), c) != end(alph);
if (letexists || (letexists && intexists))
cout << "Your value is a string" << endl;
// This will be changed for a return value
else if (!letexists && intexists)
cout << "Your value is a integer" << endl;
// This will be changed for a return value
else
cout << "Your value has an erogenous input (Special characters or non-letter/ number related stuff.";
}
}
int main(void) {
string checkedvalue;
cout << "Enter a value: ";
cin >> checkedvalue;
cin.clear();
cin.ignore(512, '\n');
datacheck(checkedvalue);
return 0;
}
I have realised that it may be because each character is being sent through individually into the subroutine, however, if this is the case I am still unsure how to fix this.
Just to end off...
Overall, an explained solution for why the iterating happens and how it can be fixed will be greatly appreciated. If possible for general cases, however, just this case will be extremely helpful nonetheless.
Thank you.
I have to admit, i dont understand all of what you write. What I did understnad is
The problem is that each character of the variable input is being
iterated over, even if the 'if statements' are outside of the 'for
loop'
And that is wrong!
for (char& c : i) {
bool intexists = find(begin(nums), end(nums), c) != end(nums);
bool letexists = find(begin(alph), end(alph), c) != end(alph);
if (letexists || (letexists && intexists))
cout << "Your value is a string" << endl;
// This will be changed for a return value
else if (!letexists && intexists)
cout << "Your value is a integer" << endl;
// This will be changed for a return value
else
cout << "Your value has an erogenous input (Special characters or non-letter/ number related stuff.";
}
All this above is "the for loop". In simple terms the syntax for a (ranged based) for loop is
for (char& c : i) {
// body of the loop
}
Your code will be more clear and readable if you use {} also for the if, even if not needed and proper intendation:
for (char& c : i) {
bool intexists = find(begin(nums), end(nums), c) != end(nums);
bool letexists = find(begin(alph), end(alph), c) != end(alph);
if (letexists || (letexists && intexists)) {
cout << "Your value is a string" << endl;
} else if (!letexists && intexists) {
cout << "Your value is a integer" << endl;
} else {
cout << "Your value has an erogenous input (Special characters or non-letter/ number related stuff.";
}
}
In C++, the standard provides different ways to checks if an string contains alpha/numeric values:
Check if all characters are numeric: std::isalnum
Check if all characters are alpha: std::isalpha
So you can replace part of your code with:
const all_numeric = std::all_of(std::begin(str), std::end(str), [](const auto c) {
return std::isalnum(c);
})
const all_alpha = std::all_of(std::begin(str), std::end(str), [](const auto c) {
return std::isalpha(c);
})
So to solve your problem, you can start by creating a helper function that checks if a string is a number by using standard functions like strtool or recycle what we did later:
bool is_number(const std::string& s) {
return !s.empty() && std::find_if(s.begin(),
s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
}
Now that you know if the string is a number or not, you can check if your string contains any weird character, and discard it.
Updates:
void datacheck(string &i) {
const auto intexists = is_number(i);
if (intexists) {
// do whatever
return;
}
const all_alpha = std::all_of(std::begin(str), std::end(str), [](const auto c) {
return std::isalpha(c);
});
if (all_alpha) {
// do whatever
return;
}
}

I continually get a "Bus Error" while this is code is being executed?

The purpose of this code is to take a file that has been passed into the program and generate the letter frequency of each letter in the file. In above code, I remove punctuation and convert to lowercase letters.
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main()
{
string fileContent = "qr rqh zrxog kdyh eholhyhg lq wkh odvw bhduv ri wkh qlqhwhhqwk fhqwxub wkdw wklv";
int count[26] = { 0 }; // an array the size of the alphabet.
for(int f = 0; f < fileContent.length(); f++) // run til the file end.
{
if(fileContent[f] == 32) // to take care of the spaces.
{
f++; // also tried "continue;" and yeild different and also incorrect results.
}
if(fileContent[f] >= 48 && fileContent[f] <= 57) //take care of numbers.
{
f++; // tried "continue;"
}
count[fileContent[f]]++;
}
for(int p = 0; p < 26; p++)
{
cout << char(p + 97) << ": " << count[p] << endl;
}
return 0;
}
When I run this code I get some accurate frequencies, and some horribly incorrect ones (seems like every other result is wrong, yet after a few letters it trails off into astronomically large numbers). Any way to do this better? what is wrong with this code? As per request I have added some more of the code (including a string with a random 100 in it) as it was apparently not clear enough)
For more context, this program is for a Ceasar shift decoder I'm working on. I am in basic c++ and would greatly appreciate any advise from you more experienced devs. thank you!
In your program, this statement:
count[fileContent[f]]++;
should be:
count[fileContent[f]-97]++; //Assuming that all alphabets are in lowercase
If you do not do -97, it is trying to increase the value at index fileContent[f] of count array, which may be beyond the limit of count array.
Also, make sure to continue in both the if blocks and you don't need to do f++ explicitly in both the if blocks as in the for loop you are already doing f++.
You are doing things the difficult way: using C-style arrays, magic numbers in your code, and risking buffer overflows everywhere.
Compare your code to this:
#include <string>
#include <iostream>
#include <map>
using namespace std;
int main()
{
string fileContent = "qr rqh zrxog kdyh eholhyhg lq wkh odvw bhduv ri wkh qlqhwhhqwk fhqwxub wkdw wklv";
map<char, int> counts;
for (char ch : fileContent)
++counts[ch];
for (char ch = 'a'; ch <= 'z'; ++ch)
cout << ch << ": " << counts[ch] << '\n';
}
Or to print all the map contents (if you do not want to print 0 for letters that did not occur) you can use:
for (auto& item : counts)
cout << item.first << ": " << item.second << '\n';
Exercise for the reader to add in the code to exclude the spaces and numbers. Hint: look up the cctype header.