so I was writing a program which has to check if the input sting is a palindrome or not. And it's actually working but a problem with deleting the array I created during the course of it arouse.
#include <iostream>
using namespace std;
bool checkPalindrome(char* text);
char* clearString(char* src);
int main()
{
char buffer[1000];
cin.getline(buffer, 1000);
cout << boolalpha << checkPalindrome(buffer) << endl;
return 0;
}
bool checkPalindrome(char* text)
{
char* newStr = clearString(text);
if (!newStr)
return false;
int newLen = strlen(newStr);
for (int i = 0; i < newLen / 2; i++) {
if (newStr[i] == newStr[newLen - i - 1])
continue;
else
return false;
}
//delete[] newStr;
return true;
}
char* clearString(char* src)
{
unsigned len = strlen(src);
unsigned counter = 0;
for (int i = 0; i < len; i++) {
if (src[i] == ' '||src[i] == '.'||src[i] == ','||src[i] == '!')
counter++;
}
unsigned newSize = len - counter + 1;
char* dest = new(nothrow) char[newSize];
if (!dest) {
cout << "not enoough memory\n";
return NULL;
}
int i, j;
for(i = j = 0; j < newSize; ++i, ++j) {
if(src[i]==' '||src[i]=='.'||src[i]==','||src[i]=='!'||src[i]=='?')
i++;
else
dest[j] = src[i];
}
dest[j] = '\0';
return dest;
}
So the commentated delete in the checkPalindrome function causes a crash if executed and I get the "Heap corruption detected" error. I tried changing the function type to void and delete there and the same thing happened. Any ideas what causes it?
Your loop copies the '\0' at the end of the string, but then you add another '\0', using one more byte of memory than you allocated.
Related
#include <iostream>
using namespace std;
int strlength(char *str)
{
int length = 0;
int index = 0;
while (*(str + index)) {
length++;
index++;
}
return length;
}
char *mergeSortedStrings(char str1[], char str2[])
{ //get the length of the newstring
int str1len = strlength(str1);
int str2len = strlength(str2);
int newStringlen = str1len + str2len;
char *newString= new char[newStringlen];
int i, j = 0;
char temp;
// copy str2 to the end of str1
for (i = strlength(str1); i<256; i++)
{
str1[i] = str2[j];
j++;
}
for (i=0; i<newStringlen;i++)
for (j = newStringlen - 1; j > i; j--) {
if (str1[j - 1] > str1[j])
{
temp = str1[j];
str1[j] = str1[j - 1];
str1[j - 1] = temp;
}
}
str1[newStringlen] = '\0';
return str1;
}
void main()
{
char str1[20];
char str2[20];
cout << "Input string 1: ";
cin >> str1;
cout << "Input string 2: ";
cin >> str2;
cout << "The merged string is: " << mergeSortedStrings(str1, str2) << endl;
}
This is C++ string merge and sort programming without using string library functions. When I copied the contents of the final str1 to newString using for loop, it didn't give the correct result so that I just used str1 as the result. It gives out the correct result somehow but I think this may not be efficient.
Can you please help me with this?
This is an example of how you could do it using a custom String class. If you do not understand what's going on i suggest you to take a look at: NULL terminated string, copy constructor, operator overloading. Be careful, this is just an example to give you an idea on how you could approach the problem, there might be some errors.
#include <iostream>
using namespace std;
class String
{
private:
char *_str;
int _len;
public:
String()
{
_str = NULL;
_len = 0;
}
~String()
{
if (_str != NULL)
delete _str;
}
String(const char *str)
{
_str = NULL;
_len = 0;
if (str == NULL) return;
int i;
for (i = 0; str[i] != '\0'; i++);
_len = i;
_str = new char[_len];
for (i = 0; i < _len; i++)
_str[i] = str[i];
}
String(const String &s)
{
_str = NULL;
_len = 0;
if (s._len == 0) return;
_str = new char[s._len];
_len = s._len;
for (int i = 0; i < _len; i++)
_str[i] = s._str[i];
}
//constructor for concatenation
String(const char* a, const char* b)
{
_str = NULL;
_len = 0;
if (a == NULL || b == NULL)
return;
int lenA;
for (lenA = 0; a[lenA] != '\0'; lenA++);
int lenB;
for (lenB = 0; b[lenB] != '\0'; lenB++);
_len = lenA + lenB;
_str = new char[_len];
for (int i = 0; i < lenA; i++)
_str[i] = a[i];
for (int i = 0; i < lenB; i++)
_str[lenA + i] = b[i];
}
int getLength() const { return _len; }
operator const char*() { return _str; }
void operator=(const char* str)
{
_str = NULL;
_len = 0;
if (str == NULL) return;
int i;
for (i = 0; str[i] != '\0'; i++);
_len = i;
if (_str != NULL)
delete _str;
_str = new char[_len];
for (i = 0; i < _len; i++)
_str[i] = str[i];
}
String operator+(const char* str)
{
return String(*this, str);
}
bool operator==(const char* str)
{
int len;
for (len = 0; str[len] != '\0'; len++);
if (len != _len) return false;
for (int i = 0; i < len; i++)
if (str[i] != _str[i])
return false;
return true;
}
bool operator<(const char* str)
{
int i;
for (i = 0; i < _len && str[i] != '\0'; i++)
{
if (_str[i] < str[i])
return true;
else if (_str[i] > str[i])
return false;
}
return false;
}
bool operator<=(const char* str)
{
int i;
for (i = 0; i < _len && str[i] != '\0'; i++)
{
if (_str[i] < str[i])
return true;
else if (_str[i] > str[i])
return false;
}
return (i == _len);
}
bool operator>(const char* str)
{
int i;
for (i = 0; i < _len && str[i] != '\0'; i++)
{
if (_str[i] > str[i])
return true;
else if (_str[i] < str[i])
return false;
}
return (_len > i);
}
bool operator>=(const char* str)
{
int i;
for (i = 0; i < _len && str[i] != '\0'; i++)
{
if (_str[i] > str[i])
return true;
else if (_str[i] < str[i])
return false;
}
return (_len >= i);
}
friend istream& operator>>(istream &is, String &s)
{
char str[512];
is.getline(str, 512);
s = str;
return is;
}
};
int main()
{
String str1;
String str2;
cout << "Input string 1: ";
cin >> str1;
cout << "Input string 2: ";
cin >> str2;
String sortedMerged = str1 <= str2 ? str1 + str2 : str2 + str1;
cout << sortedMerged;
return 0;
}
i use strtok to split a string into different pieces and assemble them as a struct. This is my code:
object* parseJSON(size_t length, char* json, size_t jsonLen){
char *finalString = prepareJSON(json,jsonLen);
cout << finalString << "\n";
char delimiter[] = ",:";
char *token = strtok(finalString, delimiter);
object *retObj = (struct object *)malloc(length);
size_t returnObjectIndex = 0;
size_t index = 0;
bool firstTime = true;
struct object item;
while(token != NULL){
if((index % 2) != 0){
if(firstTime){
item.Type = token;
firstTime = false;
} else {
item.ID = token;
retObj[returnObjectIndex] = item;
returnObjectIndex++;
firstTime = true;
}
}
token = strtok(NULL,delimiter);
index++;
}
return retObj;
}
This is the finalString:
Type:temp,id:3,Type:temp,id:1
In my mind this should come out with this code:
for(int n = 0; n < 5; n++){
cout << returnObject[n].Type << " " << returnObject[n].ID << "\n";
}
as:
temp 3
temp 1
but instead i get this on the console:
temp 3
temp 1
h"° Ó*°
C
Is this because i loop 5 times even though there should be only 2 elements in the array? I loop 5 times because i can't get the number of elements of the array in the pointer (atleast i think that this is not possible).
Any help is very much appreciated
Best regards
Edit: This is my prepareJSON function:
char* prepareJSON(char* json, size_t jsonLen){
char forbiddenChars[] = {'[', '{','\"', '}', ']'};
bool isForbbidenChar = false;
char* finalString = (char*)malloc(jsonLen);
size_t finalStringIndex = 0;
for(size_t i = 0; i < jsonLen; i++){
char c = json[i];
isForbbidenChar = false;
for(int k = 0; k < 5; k++){
if(c == forbiddenChars[k]){
isForbbidenChar = true;
break;
}
}
if(isForbbidenChar){
continue;
}
else{
finalString[finalStringIndex] = c;
finalStringIndex++;
}
}
return finalString;
}
and this my main function:
int main(){
object *returnObject;
char json[] = "[{\"Type\":\"temp\",\"id\":\"3\"},{\"Type\":\"temp\",\"id\":\"1\"}]";
returnObject = parseJSON(5,json, strlen(json));
for(int n = 0; n < 5; n++){
cout << returnObject[n].Type << " " << returnObject[n].ID << "\n";
}
}
Solution:
I did indeed allocate too little memory, changed it:
object *retObj = (struct object *)malloc(sizeof(struct object) * length);
Now it works!
Sorry if this seems really noobish and all, and the fact is, i've only been studying this for about a month now. I can't seem to get this to work right, wondering if any of you can help me out. The program once compiled only says that the inputted words are "not palindrome" even if they are.
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
bool isPal (char[], int);
int main ()
{
const int size = 10;
int flag = 0;
char arr[size];
cout << "Enter Word\n";
cin.getline(arr,10);
flag = isPal(arr, size);
if (flag == true)
cout << "Word is Palindrome\n";
else
cout << "Not Palindrome\n";
return 0;
}
bool isPal (char arr [],int size)
{
int q = 0;
char arr2[size];
for (int i = 0;i < size - 1; i++)
{
arr2[i] = arr[9 - q]; //here I attempt to reverse arr1 and assign each element to arr2
q++;
}
for (int j = 0; j < size - 1; j++)
{
if (arr [j] != arr2[j])
return false;
}
return true
}
If you only want to use plain C arrays then check with below code:-
bool isPallindrome ( char *p, int size ) //Remember here size must be one character before null //terminator.
{
char *begin, *end;
begin = p;
end = p + size;
while ( begin != end )
{
if( *begin != *end )
break;
begin++;
end--;
}
if ( begin != end )
return false;
return true;
}
Initialize the arr2
Use strlen to know the length you Input rather than use size, because your input data is not always fixed in 10
In your original code:
input: 1234567
*arr => "1234567\0"
*arr2 => "??\07654321"
Use size replaced by q
bool isPal (char arr [],int size)
{
//q=0; /* modified 3 */
char arr2[size] = ""; /* modified 1 */
for (int i=0; i<strlen(arr); i++) /* modified 2 */
{
arr2[i] = arr[strlen(arr)-i-1]; /* modified 2 */
//q++; /* modified 3 */
}
for (int i=0; i<strlen(arr); i++) /* modified 2 */
{
if (arr[i] != arr2[i])
return false;
}
return true
}
Array is "a pointer point to begin of array address", But for newbie, it's not easy to know how it works. You can reserve this thread until you learn the chapter pointer
Following the example of modified original code:
char arr[size];
char arr2[size];
// char *parr = (char*)malloc(sizeof(char)*size);
// char *parr2 = (char*)malloc(sizeof(char)*size);
cin.getline(arr,10);
// parr = &arr[0];
// cin.getline(parr, 10);
arr2[i] = arr[9 - q];
// parr1 = &arr[9-q];
// parr2 = &arr2[i]
// *parr2 = *parr1;
if (arr [j] != arr2[j])
// parr1 = &arr[j]
// parr2 = &arr2[j]
// if (*parr1 != *parr2)
I have defined the struct chararray as follows.
struct chararray
{
char* lhs;
char* rhs;
};
Now, I have two arrays la[l] and ra[l](both have all l values defined). I assign that to the struct,and return the function.
chararray s;
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &la[0];
s.rhs = &ra[0];
return s;
In main , I ouptut
for(int i = 1; i < l;i++){
cout << *(s.rhs + i);
}
Now,I get gibberish as output.
But if I output *(s.rhs + 0) and *(s.rhs + 1) and ... [ the values 0,1,.. are explicitly included ], I get correct output!
Why doesnt the for loop work?
PS - My entire code is -
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
struct chararray
{
char* lhs;
char* rhs;
};
chararray getcenter(char in[],int l){
int open_count = 0;
int open = 0;
int first = 0;
int last = 0;
int limit;
int close_count = 0;
char lhs[l],rhs[l];
for(int i = 0; i < l;i++){
lhs[i] = ' ';
rhs[i] = ' ';
}
for(int i = 0; in[i]!='\0';i++){
int flag = 0;
if(in[i] == '('){
if(flag == 0){first = i;flag = 1;}
open++;
}
if(in[i] == '('){
last = i;
}
limit = i;
}
for(int i = 0; in[i]!='\0';i++)
{
//cout << "entrt" << endl;
int temp;
if(in[i] == '(') { open_count++; }
if(in[i] == ')') { close_count++; }
if((open_count == close_count) && (open_count != 0) && (open_count != open))
{
//cout << open_count << endl;
for(int j = 0;j < i+1;j++)
{
lhs[j] = in[j];
}
lhs[i+1] = ' ';
lhs[i+2] = ' ';
for(int j = i+3; in[j]!='\0';j++)
{
lhs[j] = ' ';
rhs[j-i-3] = in[j];//Assuming no space between -> and rhs
temp = j;
}
for(int j = temp;rhs[j] != '\0';j++){
rhs[j] = ' ';
}
for(int j = temp;lhs[j] != '\0';j++){
lhs[j] = ' ';
}
break;
}
}
chararray s;
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &lhs[0];
s.rhs = &rhs[0];
return s;
}
int main()
{
string input;
cin >> input;
int l=input.length()+1;
char in[l];
strcpy(in, input.c_str());
chararray s = getcenter(in,l);
for(int i = 1; i < l;i++){
//cout << *(s.rhs + i); - Doesnt work
}
cout << *(s.lhs + 5); // Works!
return 0;
}
Your for loop is starting at i=1, and when you explicitly set the values you are using 0 and 1. Decide where you want to start, and try it again.
Try this:
for(int = 0 ; i < l; i++)
cout << *(s.rhs + i);
Note that you are actually risking a memory leak with these lines of code:
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &lhs[0];
s.rhs = &rhs[0];
You are allocating 1 char and storing its address in s.lhs, then resetting s.lhs to the address of lhs[0]. There is no need for the two first lines with the new in them. So replace that code with this: (also note that &lhs[0] is the same as lhs)
s.lhs = lhs;
s.rhs = rhs;
I wrote a program to compress a string using the counts of repeated characters. if the compressed string is longer than the original string, then we still return the original string. Below is my program:
void stringCompress(char* src) {
char* original;
original = src;
char* rst;
rst = src;
int histogram[256];
for (int i = 0; i < 256; i++) {
histogram[i] = 0;
}
int length = 0;
while (*src != NULL) {
length++;
src++;
}
src = original;
int j = 0;
for (int i = 0; i < length; i++) {
histogram[(int) src[i]]++;
if (histogram[(int) src[i]] == 1) {
rst[j] = src[i];
j++;
}
}
rst[j] = '\0';
char* final;
rst = original;
int index = 0;
char buffer[33];
for (int i = 0; i < j; i++) {
final[index] = rst[i];
stringstream number;
number<<histogram[(int)rst[i]];
-------> //cout<<number.str()<<endl;
char* temp = new char[number.str().length()+1];
strcpy(temp, number.str().c_str());
index++;
cout<<temp<<endl;
for(int k =0 ;k<number.str().length();k++)
{
final[index]=temp[k];
index++;
}
}
final[index] = '\0';
src = original;
if (index <= length) {
for (int i = 0; i < index; i++)
cout<<final[i];
} else {
cout << src << endl;
}
}
But strange thing is that if I leave the cout sentence cout<<number.str()<<endl; there (the arrow points to the sentence), then the output is right. For example, aaaabcdaa outputs a6b1c1d1 and aabcd outputs aabcd. However if I comment out cout<<number.str()<<endl;, then nothing is generated. Any help is appreciated.
The variable final is uninitialized in your code. When I initialize it with a memory buffer, then your program prints the desired output whether the line you pointed to is commented out or not.
Perhaps you meant to use buffer (which is unused) as memory for final, such as:
final = buffer;