Runlength Encoding Algorithm[Data Compression] - c++

I am trying to implement the algorithm RLE with simple input like:
ddddddddddhhhhhhhhhhhhhhhttttttttttttt
code:
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
int main() {
vector<char> read;
ifstream file;
file.open("file.txt");
if (!file) {
cout << "Unable to open";
}
char v;
while(file>>v) {
read.push_back(v);
}
char x;
int count=0;
for(int i=0; i<read.size(); i++) {
x = read[i];
if(x != read[++i]) {
cout << x << "1";
}
while(x == read[++i]) {
count++;
}
cout << x << count;
count = 0;
}
return 0;
}
The output I am getting is:
d9d1h12h1t10t1
Please help me with the code.
Update: I have updated the question as I have realized few things.
Plus: This code produced no output, is there anything wrong which I am doing wrong?
char o;
char n;
int count=0;
for(int i=0; i<read.size(); i++) {
o = read[i];
n = read[++i];
while(o == n) {
count++;
}
cout << o << count;
if(o != n) {
cout << o << "1";
} count = 0;
}
return 0;

This loop:
char x;
int count=0;
for(int i=0; i<read.size(); i++) {
int j=i;
x = read[i];
if(x != read[++j]) {
cout << x << "1";
}
while(x == read[++j]) {
count++;
}
cout << x << count;
}
Has several errors. First, you should use two indices, i and j. i is going through each element of read, but then j is iterating through a subsequence too. What you want is to go through each element only once, and in each case either print or increase the count. However having a for loop and moving the index inside too is not a very good practice, is rather error-prone. Also you have to cout statements that are do not run at the right time (you don't wan to print something on every iteration, only when the character changes). You could do it with a while loop, or using a simpler structure like:
// If there are no characters finish
if (read.empty()) {
return 0;
}
// Get the first character
char lastChar = read[0];
int count = 1; // We have counted one character for now
// Go through each character (note start from 1 instead of 0)
for(int i = 1; i < read.size(); i++) {
// Get the next char
char newChar = read[i];
// If it is different, print the current count and reset the counter
if (lastChar != newChar) {
cout << lastChar << count;
count = 1;
lastChar = newChar;
} else { // Else increase the counter
count++;
}
}
// Print the last one
cout << lastChar << count;
return 0;

Related

filling 2d char array and accessing each element

It's my first question in stack overflow so if there is some mistakes sorry about that. I'm trying to fill a 2d char array and then access each letter. I complied my code, there is no error but when I try to run it doesn't work. Here it's my code.
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main() {
char ch[] = "Welcome text in a separate line.";
char strWords[5][7];
int counter = 0;
int a = 0;
for (int i = 0; i < sizeof(ch); i++) {
if (ch[i] == ' ') {
strWords[counter][a] = '\0';
counter++;
a = 0;
}
else
{
strWords[counter][a] += ch[i];
a++;
}
}
for (int i = 0; i <= 5; i++) {
for (int a = 0; a <= 7; a++) {
cout << strWords[i][a] << " ";
}
}
return 0;
}
A few things wrong with your code
int main() {
char ch[] = "Welcome text in a separate line.";
// char strWords[5][7]; <<<=== i would change to be larger that you need, just in case
char strWords[20][20];
int counter = 0;
int a = 0;
for (int i = 0; i < strlen(ch); i++) { // sizeof is wrong, you need strlen
if (ch[i] == ' ') {
strWords[counter][a] = '\0';
counter++;
a = 0;
}
else
{
//strWords[counter][a] += ch[i];
strWords[counter][a] = ch[i]; // you do not need to try to concatenate, you are already walking down the buffer with 'a'
a++;
}
}
for (int i = 0; i < counter; i++) { // use 'counter' as it has the number of lines
// since you 0 terminated the string you do not need to walk character by character
cout << strWords[i] << " ";
}
return 0;
}
You are also not detecting and terminating the last word (since there is no space after it). I will leave that to you. The code I show does not print the word 'line.'
You should really have tests to make sure you do not overflow the length or number of words.
Plus you should ideally use std::string and std::vector
Note - if, for experimentation, you do want to walk through char by char to output the strings you should look for the terminating '0' character and exit the inner loop

issue with pointers and count

I need to build a code where it takes a 2d array of char and checks if its palindrome the second function uses the first one to see how many arrays are palindrome my issue with the code is that every time I get count is 0; I know the issue is in the second function but don't know where
#include <iostream>
using namespace std;
int CountPal(char M[][5], int rows);
int pal(char* S) {
char *p, *start, flag = 1;
p = S;
while(*p != NULL) {
++p;
}
--p;
for(start = S; p >= start && flag;) {
if(*p == *start) {
--p;
start++;
} else
flag = 0;
}
}
int main() {
int x;
cout << "please enter the number of rows " << endl;
cin >> x;
char M[5][5];
cout << "before test" << endl;
cout << CountPal(M, x) << endl;
cout << "After test" << endl;
system("pause");
}
int CountPal(char M[][5], int rows) {
int count = 0;
cout << "please enter the string " << endl;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < 5; j++) {
cin >> M[i][j];
}
for(int i = 0; i < rows; i++) {
char* S;
S = &M[i][0];
if(pal(S) == 1) count++;
}
}
return count;
}
I think your problem is in int pal(char* S) function. You want it to return 1 if a given string of your 2d array is a palindrome to up your count by 1. And anything other than 1 would be non palindrome string.
So i think you should add a return statement after the end of your int pal(char* S) function like this;
int pal(char* S) {
char *p, *start, flag = 1;
p = S;
while(*p != NULL) {
++p;
}
--p;
for(start = S; p >= start && flag;) {
if(*p == *start) {
--p;
start++;
} else
flag = 0;
}
return flag;
}
You could even change your function to bool data type. It's more proper because you only want to return "true" or "false" values.

Square Root Code C++ without sqrt()

I have to create a code where the user inputs a number which is a perfect square, and I have to show its root. I've made this code, but I'm getting Segmentation Fault 11 , in this piece: int j = squareRootVector[i];
squareRoot.push_back(j);.
I can't change the code too much, so is there a way that I can do that?
#include <iostream>
#include <vector>
using namespace std;
int main() {
cout <<
"Enter the number:\n";
int input;
int number = input;
int divider = 2;
vector<int> squareRootVector;
vector<int> squareRoot;
cin >> number;
for(int divider = 2; number > 1; divider++) {
while((number % divider) == 0) {
number /= divider;
cout << number << endl;
squareRootVector.push_back(divider);
}
}
for(int i = 0; i < squareRootVector.size(); i++) {
cout << squareRootVector[i] << " ";
/*******PROBLEM*******/
if(squareRootVector[i] == squareRootVector[i+1]) {
int j = squareRootVector[i];
squareRoot.push_back(j);
}
/*********************/
}
int root;
for (int i = 0; squareRoot.size(); i++) {
root = root * squareRoot[i];
}
cout << "Square Root of " << input << " is: " << root << endl;
return 0;
}
The behaviour on accessing squareRootVector[i+1] with i just one below size (which your loop constaint allows) is undefined.
Consider writing
for (std::size_t i = 1; i < squareRootVector.size(); i++) {
instead, and rebasing the for loop body accordingly. I've also slipped in a change of type for i.
Shortly, the problem is that the last cycle in the last "for":
for(int i = 0; i < squareRootVector.size(); i++)
has the following line in it:
squareRootVector[i] == squareRootVector[i+1];
This is an "out of limits" error: squareRootVector only has squareRootVector.size() elements (let's say n), and the elements are indexed from 0 to n-1.
squareRootVector[i+1] in the last cycle points one element after the last one of squareRootVector, which is undefined behavior.
Using vector::iterator is proper way.
for(vector<int>::iterator it = squareRootVector.begin(); it != squareRootVector.end(); ++it)
{
if( (it+1) == squareRootVector.end() )
{
//what to do if there's no next member???
break;
}
if( *it == *(it+1) )
{
squareRoot.push_back(*it);
}
}
Thanks for the answers, guys. I've ended up with this code:
#include <iostream>
#include <vector>
using namespace std;
int main() {
cout << "Enter the number:\n";
int input = 0;
int number = 0;
cin >> input;
number = input;
int divider = 2;
vector<int> squareRootVector;
vector<int> squareRoot;
for(int divider = 2; number > 1; divider++) {
while((number % divider) == 0) {
number /= divider;
squareRootVector.push_back(divider);
}
}
int vectorSize = squareRootVector.size() - 1;
for(int i = 0; i < vectorSize; i++) {
if(squareRootVector[i] == squareRootVector[i+1]) {
int j = squareRootVector[i];
squareRoot.push_back(j);
}
}
int root = 1;
for (int i = 0; i < squareRoot.size(); i++) {
root = root * squareRoot[i];
}
cout << "Square Root of " << input << " is " << root << endl;
return 0;
}

copying one element of a char array to another using for loop

I'm trying to write a simple program which takes an array of chars, and spits it out backwards. I know there are plenty of other ways to shorten this using a library header function, but I wanted to do it using for loops just to get used to them.
#include<stdio.h>
#include<iostream>
using namespace std;
char string1[10];
int count = 0;
char stringy[10];
void enterString()
{
cout << "please enter a string: " << endl;
cin >> string1;
}
void stringCounter(const char stringLength[])
{
//initiate for loop i = 0
//if stringLength[i] does not does not equal 'i' then carry on
//increment i
for (int i = 0; stringLength[i] != '\0'; i++)
{
count++;
}
cout << "size of string is: " << count << endl;
}
void reverseString(int arraySize, char string2[])
{
int counter = 0;
for (int i = arraySize; i >= 0; string2[i--])
{
stringy[counter] = string2[i];
counter++;
}
stringy[count] = '\0';
cout << stringy << endl;
}
int main()
{
enterString();
stringCounter(string1);
reverseString(count, string1);
return 0;
}
This is the whole program. The program is failing in function reverseString. I can't work out how to successfully read the last index of the char array string2[] and copy it into the first index of char array stringy.
One, If the user enters a string more than 10 characters long then your enterString() function will access the array out of its bound, at cin>>string1. So better to use getline to make sure you don't read more than what your array can hold.
Two, with your current implementation the reverseString() function will write to the first element of the array with the null terminator character,if the arraySize<=10, and trying to display that string will not show you anything.
This:
cin >> string1;//will try to access the array out of its bound if user give more than it can hold,i.e 10 characters
...
for (int i = arraySize; i >= 0; string2[i--])
{
stringy[counter] = string2[i];//the first iteration will put the '\0' character as the first elements of stringy
counter++;
}
Should be changed to:
cin.getline(string1,10);//make sure to get not more than 10 characters,including the null terminator
.....
for (int i = arraySize-1; i >= 0; i--)
{
stringy[counter] = string2[i];
counter++;
}
There are many mistakes in your program. If this is the exact code you are compiling then it should throw many errors.
Following might help.
#include<iostream>
using namespace std;
void reverseString(int , char *);
int stringCounter(const char );
int stringCounter(const char stringLength[])
{
int count = 0;
for (int i = 0; stringLength[i] != '\0'; i++)
count++;
cout << "size of string is: " << count << endl;
return count;
}
void reverseString(int arraySize, char string2[])
{
int counter = 0;
char stringy[100];
for (int i = arraySize - 1; i >= 0; i--)
{
stringy[counter] = string2[i];
counter++;
}
stringy[counter] = '\0';
cout << stringy << endl;
}
int main()
{
char str[] = "string";
reverseString(stringCounter(str),str);
return 0;
}

Debug error. R6010 abort has been called()

#include "../../../std_lib_facilities.h"
int main()
{
vector <int> nmb;
vector <int> rep;
vector <int> prt;
int flag = 0;
int temp = 0;
int br = 0;
int max = -1;
int ind = 0;
cout << "Enter as much integers as you like\n";
while (cin >> temp)
{
if (nmb.size() == 0)
{
nmb.push_back(temp);
prt.push_back(temp);
++rep[br];
++br;
}
else
{
for (int i = 0; i < nmb.size(); ++i)
{
if (temp == nmb[i])
{
++rep[i];
flag = 1;
}
}
if (flag == 0)
{
nmb.push_back(temp);
prt.push_back(temp);
++rep[br];
++br;
}
else if (flag == 1)
{
flag = 0;
prt.push_back(temp);
}
}
}
cout << "You've entered numbers\n";
for (int j = 0; j < prt.size(); ++j)
cout << prt[j] << " ";
for (int k = 0; k < rep.size(); ++k)
if (rep[k] > max)
{
max = rep[k];
ind = k;
}
cout << "\n\nMost repeated number is " << nmb[ind] << endl;}
My task is to write what number has been entered max times. I know it's probably not the best idea but it was the first "good" one I had so I went with it. It compiles fine but gives me that error from that title when running. I tried cout << in few places and it seems that problem starts at the beginning of while loop.
You try to access the first element of rep, which is an empty vector.
You have to actually add elements before you may access them. Right now you're reading from and writing to memory that is not yours.