How to resolve the segmentation fault in this code? - c++

I am trying to make an infix calculator for which I am currently trying to convert numbers entered in a character array to double.
here's my code:
#include <iostream>
#include<cmath>
using namespace std;
int main()
{
char exp[500];
const int SIZE = 100;
char temp[SIZE];
char op;
int strLen = 0, k, l, num = 0, fnum = 0;
double number = 0;
cin.getline(exp, 500,'\n');
int i = 0, j = 0, fpoint=0;
cout << exp;
for (i = 0, j = 0; exp[j] != 0; i++)
{
if (i % 2 == 0)
{
for (int m = 0; exp[m] != ','; m++) //stopped working
temp[m] = exp[m];
cout << temp;
for (k = 0; k < SIZE && temp[k] != 0; k++)
{
strLen = k;
if (temp[k] == '.')
fpoint = k + 1;
}
cout << fpoint<<endl;
cout << "strLen" << strLen;
for (k = 0; k <= fpoint; k++)
{
num = num + ((temp[fpoint - k] - '0') * pow(10, k));
}
for (k = fpoint + 1, l = 0; k <= strLen; k++, l++)
{
fnum = fnum + ((temp[strLen - l] - '0') * pow(10, l));
}
number = num + (fnum / pow(10, strLen - fpoint + 1));
cout << number;
j = j + strLen + 1;
}
else
{
char op = temp[j];
cout << op;
}
}
system("pause");
return 0;
}
sample input
2.5*3
It stops working and gives segmentation fault as an error on the marked position.

This line for (int m = 0; exp[m] != ','; m++) //stopped working will always fail if there are no , characters since exp[m] != ',' will always be equal to true and so will reach beyond the end of the array of exp which triggers the "segmentation fault".

Related

Rabin-Karp algorithm in c++

I am trying to understand the implementation of the Rabin-Karp algorithm. d is the number of characters in the input alphabet, but if I replace 0 or any other value instead of 20, it won't affect anything. Why is this happening like this ?
// Rabin-Karp algorithm in C++
#include <string.h>
#include <iostream>
using namespace std;
#define d 20
void rabinKarp(char pattern[], char text[], int q) {
int m = strlen(pattern);
int n = strlen(text);
int i, j;
int p = 0;
int t = 0;
int h = 1;
for (i = 0; i < m - 1; i++)
h = (h * d) % q;
// Calculate hash value for pattern and text
for (i = 0; i < m; i++) {
p = (d * p + pattern[i]) % q;
t = (d * t + text[i]) % q;
}
// Find the match
for (i = 0; i <= n - m; i++) {
if (p == t) {
for (j = 0; j < m; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == m)
cout << "Pattern is found at position: " << i + 1 << endl;
}
if (i < n - m) {
t = (d * (t - text[i] * h) + text[i + m]) % q;
if (t < 0)
t = (t + q);
}
}
}
int main() {
// char text[] = "ABCCDXAEFGX";
char text[] = "QWERTYUIOPASDFGHJKLXQWERTYUIOPASDFGHJKLX";
char pattern[] = "KLXQW";
int q = 13;
rabinKarp(pattern, text, q);
}
I believe the short answer is that the lower d is the more hash collisions you will have, but you go about verifying the match anyway so it does not affect anything.
A bit more verbose:
First let me modify your code to be have more expressive variables:
// Rabin-Karp algorithm in C++
#include <string.h>
#include <iostream>
using namespace std;
#define HASH_BASE 0
void rabinKarp(char pattern[], char text[], int inputBase) {
int patternLen = strlen(pattern);
int textLen = strlen(text);
int i, j; //predefined iterators
int patternHash = 0;
int textHash = 0;
int patternLenOut = 1;
for (i = 0; i < patternLen - 1; i++)
patternLenOut = (patternLenOut * HASH_BASE) % inputBase; // hash of pattern len
// Calculate hash value for pattern and text
for (i = 0; i < patternLen; i++) {
patternHash = (HASH_BASE * patternHash + pattern[i]) % inputBase;
textHash = (HASH_BASE * textHash + text[i]) % inputBase;
}
// Find the match
for (i = 0; i <= textLen - patternLen; i++) {
if (patternHash == textHash) {
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == patternLen)
cout << "Pattern is found at position: " << i + 1 << endl;
}
if (i < textLen - patternLen) {
textHash = (HASH_BASE * (textHash - text[i] * patternLenOut) + text[i + patternLen]) % inputBase;
if (textHash < 0)
textHash = (textHash + inputBase);
}
}
}
int main() {
// char text[] = "ABCCDXAEFGX";
char text[] = "QWEEERTYUIOPASDFGHJKLXQWERTYUIOPASDFGHJKLX";
char pattern[] = "EE";
int q = 13;
rabinKarp(pattern, text, q);
}
The easiest way to attack it is to set HASH_BASE (previously d) to zero and see where we can simplify. The rabinKarp function can then be reduced to:
void rabinKarp(char pattern[], char text[], int inputBase) {
int patternLen = strlen(pattern);
int textLen = strlen(text);
int i, j; //predefined iterators
int patternHash = 0;
int textHash = 0;
int patternLenOut = 0;
// Calculate hash value for pattern and text
for (i = 0; i < patternLen; i++) {
patternHash = (pattern[i]) % inputBase;
textHash = (text[i]) % inputBase;
}
// Find the match
for (i = 0; i <= textLen - patternLen; i++) {
if (patternHash == textHash) {
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == patternLen)
cout << "Pattern is found at position: " << i + 1 << endl;
}
if (i < textLen - patternLen) {
textHash = (text[i + patternLen]) % inputBase;
if (textHash < 0)
textHash = (textHash + inputBase);
}
}
}
now you'll notice that all the hashes becomes is the sum of the letters mod some number (in your case 13, in my case 2). This is a bad hash, meaning many things will sum to the same number. However, in this portion of the code:
if (patternHash == textHash) {
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == patternLen)
cout << "Pattern is found at position: " << i + 1 << endl;
}
you explicitly check the match, letter by letter, if the hashes match. The worse your hash function is, the more often you will have false positives (which will mean a longer runtime for your function). There are more details, but I believe that directly answers your question. What might be interesting is to record false positives and see how the false positive rate increases as d and q decrease.

How to display this pyramid of numbers?

I have this task:
A user inputs a number N and you have to output this pyramid:
0
101
21012
.......
N.21012.N
For N=5 it will be :
0
101
21012
3210123
432101234
54321012345
I managed to only get it working for N<10 with this code:
int n;
cin >> n;
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < n - i; j++)
cout << " ";
int dir = -1;
for (int k = i; k <= i; k += dir) {
cout << k;
if (k == 0)
dir = 1;
}
cout << endl;
}
For N=10 it will look like this :
0
101
21012
3210123
432101234
54321012345
6543210123456
765432101234567
87654321012345678
9876543210123456789
10987654321012345678910
After the answers I settled on this :
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int main()
{
int n, spaces;
string number;
cin >> n;
if (n < 10)
spaces = n;
else
{
spaces = 9;
int pwr = 0, k = n;
while (k > 9)
{
pwr++;
k /= 10;
}
for (int i = 1; i < pwr; i++)
{
spaces += pow(10, i) * 9 * (i + 1);
}
spaces += (n - pow(10, pwr) + 1) * (pwr + 1);
}
// cout << spaces << endl;
for (int i = 0; i < n + 1; i++)
{
for (int j = i; j > -1; j--)
number += to_string(j);
int len = number.length() - 1;
for (int j = 0; j < spaces - len; j++)
cout << " ";
for (int j = 1; j <= i; j++)
number += to_string(j);
cout << number << endl;
number.clear();
}
cout << endl;
return 0;
}
int padding(int n) {
constexpr auto singleDigitNumbersCount = 9;
constexpr auto doubleDigitNumbersCount = 90; // from 10 to 99
if (n < 10) return n;
if (n < 100) return 2*n - singleDigitNumbersCount;
return 3*n - doubleDigitNumbersCount - 2*singleDigitNumbersCount;
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n + 1; i++) {
std::cout << std::string(padding(n) - padding(i), ' ');
for (int k = i; k >= 0; k--) {
cout << k;
}
for (int k = 1; k <= i; k++) {
cout << k;
}
cout << '\n';
}
return 0;
}
https://godbolt.org/z/EEaeWEvf4
I made this a bit ago Compiler Explorer
Not sure if that'd help 🤔
Here is the working code:
#include <string>
#include <iostream>
using namespace std;
#define MAX_SPACE 50
int main()
{
int n;
cin >> n;
string output = "";
for (int i = 0; i < n + 1; i++)
{
for (int k = i; k >= 0; k--) {
output += to_string(k);
}
for (int k = 1; k <= i; k++) {
output += to_string(k);
}
for (uint8_t i = 0, max = MAX_SPACE - output.length() / 2.00; i < max; i++) // Print max spaces minus the integer length divided by 2
{
cout << " ";
}
cout << output << endl; // Print number
output = "";
}
return 0;
}

C++ getting segfaults on an array I already assigned values to

I was trying to do a problem on HackerEarth, and I am getting Segmentation Faults for this for loop:
for (int index = 0; index < 18; index++){
cout << arr_list[arr_index][index];
}
Even though I assigned values to arr_list[arr_index][index] in the loop right before (so I'm guessing the values are somehow not being saved, but I don't know how the values aren't being saved).
When I remove this for loop, I don't get any segfaults, and the cout information prints what's expected (the numbers I've inputted, with each digit twice for each cout inside the loop).
#include <iostream>
#include <string>
using namespace std;
void step(int arr_list[1000000][18], int cs, int N){
/**
int freq[100000] = {0};
for (int i = 0; i < N; i++){
int cur_arr[18];
for (int index = 0; index < 18; index++){
cur_arr[index] = arr_list[i][index];
}
if (cs == 4){
freq[cur_arr[0]*100 + cur_arr[1] * 10 + cur_arr[2]] += 1;
} else{
freq[cur_arr[18 - cs*5] * 10000 + cur_arr[18 - cs*5 + 1] * 1000 + cur_arr[18 - cs*5 + 2]*100 + cur_arr[18 - cs*5 + 3] * 10 + cur_arr[18 - cs*5 + 4]] += 1;
}
}
for (int i = 1; i < 100000; i++){
freq[i] += freq[i-1];
}
int new_arr_list[1000000][18];
for (int i = N-1; i >= 0; i--){
int pos;
int cur_arr[18];
for (int index = 0; index < 18; index++){
cur_arr[index] = arr_list[i][index];
}
if (cs == 4){
pos = cur_arr[0]*100 + cur_arr[1] * 10 + cur_arr[2];
} else{
pos = cur_arr[18 - cs*5] * 10000 + cur_arr[18 - cs*5 + 1] * 1000 + cur_arr[18 - cs*5 + 2]*100 + cur_arr[18 - cs*5 + 3] * 10 + cur_arr[18 - cs*5 + 4];
}
for (int index = 0; index < 18; index++){
new_arr_list[freq[pos] - 1][index] = arr_list[i][index];
}
freq[pos] --;
}
for (int i = 0; i < N; i++){
for (int index = 0; index < 18; index++){
arr_list[i][index] = new_arr_list[i][index];
}
}
**/
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int T;
int arr_index = 0;
cin >> T;
int arr_list[1000000][18];
int max_len = 0;
for (int testcase = 0; testcase < T; testcase ++){
string a;
cin >> a;
int a_len = a.length();
if (a_len > max_len){
max_len = a_len;
}
int arr_entry[18];
for (int i = 0; i < a_len ; i++){
arr_entry[18 - a_len + i] = a[i] - 48;
}
for (int i = 0; i < 18 - a_len; i++){
arr_entry[i] = 0;
}
for (int index = 0; index < 18; index++){
arr_list[arr_index][index] = arr_entry[index];
cout << arr_entry[index];
cout << arr_list[arr_index][index];
}
for (int index = 0; index < 18; index++){
cout << arr_list[arr_index][index];
}
arr_index ++;
}
/**
for (int c = 1; c < 5; c++){
if (max_len > (c-1)*5){
step(arr_list, c, T);
for (int i = 0; i < T; i++){
int is_leading_zero = 1;
for (int j = 0; j < 18; j++){
if (is_leading_zero == 0){
cout << arr_list[i][j];
}else{
if (arr_list[i][j] != 0){
is_leading_zero = 0;
cout << arr_list[i][j];
}
}
}
cout << " ";
}
cout << "\n";
}
}
**/
}
I'm assuming this is a common error, and that I'm missing something simple that gives me segfaults for values I already assigned data to.
Does anyone know why this is happening?
You are allocating 72 MB on the stack:
int main()
{
[...]
int arr_list[1000000][18];
[...]
}
This is probably causing a stack overflow.
On the Microsoft Windows platform, the maximum stack size is, by default, 1 MB. On Linux, it is typically 8 MB.
When allocating such large amounts of memory, I recommend that you instead either use
dynamic memory allocation, or
a global variable, or
a static local variable.
This ensures that the array is not stored on the stack.

C++ - Output always pushes to the most left?

The fiboEncoding() function below is to read an integer then return the Fibonacci encoding.
When I test it in the main function, it always pushes itself into the most left part of the output. How can I solve this problem? What did I do wrong to cause this problem?
#include <iostream>
#include <vector>
using namespace std;
string fiboEncoding(int n) {
string word;
int fib[1000];
fib[0] = 1;
fib[1] = 2;
int i = 0;
for(i = 2; fib[i-1] <= n; i++) {
fib[i] = fib[i-1] + fib[i-2];
}
int r = i - 2;
int index = r;
vector<char> v(r+3);
while(n > 0) {
v[index] = '1';
n = n - fib[index];
index = index - 1;
while (index >= 0 && fib[index] > n) {
v[index] = '0';
index = index - 1;
}
}
v[r + 1] = '1';
for (int j = 0; j < v.size() - 1; j++) {
cout << v[j];
}
return word;
}
int main() {
int n;
string fibo;
cin >> n;
fibo = fiboEncoding(n);
cout << "code: " << fibo << endl;
}
Your function returns an empty string word. You forgot to copy the result into word string.
What you see in the console is the result of executing the following part not cout.
for (int j = 0; j < v.size() - 1; j++) {
cout << v[j];
}
To fix replace the above for loop by
for (int j = 0; j < v.size() - 1; j++) {
//cout << v[j];
word += v[j];
}

Adding big numbers using pointers (c++)

i need help, the code below does not work as it returns nothing when i run it. I'm trying to add big number so large that the numbers won’t be able to be represented in the standard C++ integer data structures
mission.cpp
void Big2Add(const char * num1, const char * num2, char * result)
{
string a = num1;
string b = num2;
int min = (a.length() < b.length() ? a.length():b.length());
int max = (a.length() < b.length() ? b.length():a.length());
int *n1 = new int[max];
int *n2 = new int[max];
for (unsigned int i=0; i < a.length(); i++)
{
n1[i] = a.at(a.length() - 1 -i) - 48;
}
cout << a << endl;
for (unsigned int i=0; i < b.length(); i++)
{
n2[i] = b.at(b.length()-1 -i) - 48;
}
cout << b << endl;
int carry = 0;
int* sum = new int[max];
int k=0;
for (k = 0; k < max; k++)
{
sum[k] = (n1[k] + n2[k] + carry) % 10;
if ( (n1[k] + n2[k] + carry) >= 10)
carry = 1;
else carry = 0;
}
sum[max] = carry;
for (int j= max; j >= 0; j--)
{
*result = sum[j];
}
}
main.cpp
char result[10];
const char * num1 = "10";
const char * num2 = "10";
Big2Add(num1, num2, result);
cout << "Part 3" << endl;
cout << "The addition of " << num1 << " and " << num2 << " is " << result << endl;
cout << endl;
First obvious bug:
int* sum = new int[max];
...
sum[max] = carry;
You need to allocate max+1 in order to use position max.
Second and third obvious bugs:
*result = sum[j];
You forgot to advance result and you forgot to add '0'
Fourth, you forgot to null terminate the string.
Try:
for (int j= max; j >= 0; j--)
{
*(result++) = sum[j] + '0';
}
*result = 0;
ok it works now tks but my main problem now is that is that there is a extra zero in front of my answer if let say i do 10 plus 10 it will give me 010 or 100 with 10 it will give me 0110 but if i plus 99 with 99 it will give 198 y?
void Big2Add(const char * num1, const char * num2, char * result)
{
string a = num1;
string b = num2;
int max = (a.length() < b.length() ? b.length():a.length());
int *n1 = new int[max];
int *n2 = new int[max];
unsigned int i;
for (i=0; i < a.length(); i++)
{
n1[i] = a.at(a.length() - 1 -i) - 48;
}
for (int j = i; j < max; ++j)
{
n1[j] = 0;
}
for (i=0; i < b.length(); i++)
{
n2[i] = b.at(b.length()-1 -i) - 48;
}
for (int j = i; j < max; ++j)
{
n2[j] = 0;
}
int carry = 0;
int* sum = new int[max];
int k=0;
for (k = 0; k < max; k++)
{
sum[k] = (n1[k] + n2[k] + carry) % 10;
if ( (n1[k] + n2[k] + carry) >= 10)
carry = 1;
else carry = 0;
}
sum[max] = carry;
for (int j= max ; j >= 0; j--)
{
if(sum[0] == 0)
{
}
*(result++) = sum[j] + '0';
}
*result = 0;
}