Transform a void function into char* C++ - c++

Some guy presented me with a beautiful code in my other question. Here it is:
#include <iostream>
#include <cstring>
using namespace std;
void encode(char* source, char const* alpha)
{
int i, j;
int len = strlen(source);
for (i = 0; i < len; i++)
{
if (source[i] >= 'a' && source[i] <= 'z')
{
j = source[i] - 'a';
source[i] = alpha[j];
}
}
}
int main(void)
{
char source[1001];
char alpha[27];
cin.getline(source, 1001);
cin.getline(alpha, 27);
encode(source, alpha);
cout << source;
return 0;
}
What should I do to transform this void function into a char* one (it should become char* encode(char* source, char const* alpha))? Apparently as it won't be a 'void' it should return a value but what value? Those pointers confuse me immensely.

#include <iostream>
#include <cstring>
using namespace std;
char* encode(char* source, char const* alpha)
{
int i, j;
int len = strlen(source);
for (i = 0; i < len; i++)
{
if (source[i] >= 'a' && source[i] <= 'z')
{
j = source[i] - 'a';
source[i] = alpha[j];
}
}
return source;
}
int main()
{
char source[1001];
char alpha[27];
cin.getline(source, 1001);
cin.getline(alpha, 27);
cout << encode(source, alpha);
return 0;
}
Do something like that. And if you want to change a char array of main, your void function would work. :)

char* encode(char* source, char const* alpha)
{
int i, j;
int len = strlen(source);
for (i = 0; i < len; i++)
{
if (source[i] >= 'a' && source[i] <= 'z')
{
j = source[i] - 'a';
source[i] = alpha[j];
}
}
return source;
}
Though it doesn't look like your doing anything with that return value.
(Were you supposed to return a copy of the char array, or is modifying in-place it okay?)

Returning char * really only makes sense if you're trying to alert the calling function an error has occurred:
char *encode(char *source, char const *alpha)
{
int i, j;
int len = strlen(source);
/* Check For Argument Errors */
if((source == NULL) || (alpha == NULL))
return NULL;
for (i = 0; i < len; i++)
{
if (source[i] >= 'a' && source[i] <= 'z')
{
j = source[i] - 'a';
source[i] = alpha[j];
}
}
return source;
}
The calling function can check for errors like this:
if(encode(source, alpha) == NULL)
{
printf("Encoding error!\n");
return -1;
}
else
{
cout << source;
}

Related

Implicit conversion from char* to bool

I managed to solve my problem, it working properly and giving the correct results. The problem now is that I have this warning: Implicit conversion from char* to bool[readability-implicit-bool-conversion].
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
bool is_letter(const char s) {
return ('a' <= s && s <= 'z') || ('A' <= s && s <= 'Z');
}
int main() {
const int MAX_LENGTH = 260;
const int VOWELS = 11;
char is_vowel[VOWELS] = "aeiouAEIOU", s[MAX_LENGTH];
ifstream fin("date.in");
int k;
cin >> k;
int start = -1,nrVowels = 0, finish = 0, counter = 0;
while (!fin.eof()) {
fin.getline(s, MAX_LENGTH);
int n = strlen(s);
int have_word = 0;
for (int i = 0; i < n; ++i) {
if (is_letter(s[i])) {
have_word = 1;
if (strchr(is_vowel, s[i])) {
++nrVowels;
}
if (counter == 0) {
start = i;
finish = i;
++counter;
} else {
finish = i;
}
} else if (have_word == 1) {
if (nrVowels >= k) {
for (int i = start; i <= finish; ++i) {
cout << s[i];
}
cout << "\n";
}
counter = 0;
have_word = 0;
nrVowels = 0;
}
}
if (have_word == 1) {
if (nrVowels >= k) {
for (int i = start; i <= finish; ++i) {
cout << s[i];
}
cout << "\n";
}
counter = 0;
nrVowels = 0;
finish = 0;
}
}
return 0;
}
The error appears on the line where I am searching for the vowels
"
if (strchr(is_vowel, s[i]))
"
strchr() returns a char *. You're then using it in a boolean operation. While it works, the compiler is suggesting you change the code to:
if (strchr(...) != nullptr)
Then there is no implicit conversion.
Note that there are people who think C++ implicit conversion should be removed. Jason Turner has a talk on this on YouTube. I have no idea how many bugs I've had over the years due to implicit conversion, which is why your compiler warns you about it.

c++ cstring merge and sort programming without using string library

#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;
}

Dynamic Memory issue in C++

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.

Printing an integer value from an ASCII character

I am trying to implement the function stoi() in c++. I have made an int array arr to store the integer ASCII of all elements of char_arr. This works fine if I print the values from my char_arr array because its a character array. But, how do I transfer my integer values from the char array to an int array and print only the numbers and not their ASCII?
Code:
int stoi(){
int *arr = new int [strlen(char_arr)];
for (int i=0; char_arr[i]!='\0'; ++i){
arr[i] = char_arr[i];
}
for (int i=0; char_arr[i] != '\0'; ++i){
if (arr[i] >= 48 && arr[i] <= 57){
cout << char_arr[i];
}
}
}
First of all, remove the first loop and use char_arr directly. You don't need to hold ints to make it work.
As for printing int values, you can use this:
for (int i = 0; char_arr[i] != '\0'; ++i) {
if (char_arr[i] >= '0' && char_arr[i] <= '9') { //I would suggest you to use this syntax instead of raw ASCII codes.
cout << (char_arr[i] - '0');
}
}
int stoi(){
/* if you do not use arr.
int *arr = new int[strlen(char_arr)];
for (int i = 0; char_arr[i] != '\0'; ++i){
arr[i] = char_arr[i];
}
*/
int sign = 1, value = 0;
if (*char_arr == '+') {
++char_arr;
}
else if (*char_arr == '-') {
++char_arr;
sign = -1;
}
while (*char_arr) {
if (*char_arr >= '0' && *char_arr <= '9') {
value = value * 10 + *char_arr - '0';
++char_arr;
} else {
break;
}
}
return sign * value;
}
Here's the one I came up with:
#include <cstdio>
#include <cstring>
#define _BASE_ 10
int main(int argc, char **argv)
{
char ascii[] = "474927";
signed int value = 0;
signed int ascii_len = strlen(ascii);
int pos = 0;
for(signed int i = ascii_len-1; i >= 0; i--)
{
if(i == 0 && ascii[i] == '-')
{
value *= -1;
continue;
}
int base = 1;
if(pos > 0)
{
base = _BASE_;
for(int j = 1; j < pos; j++)
base *= _BASE_;
}
value += base * (ascii[i] - 48);
pos++;
}
printf("Value: %d\n", value);
return 0;
}

Vinegere Cipher with C++ having an issue with output

I am having some issues trying to get my code to work. It prints ALMOST the right data but maybe it isn't looping correctly? I don't think it repeats the key through the alphabet. It's all lowercase and doesn't exceed 26.
void vigenereEncrypt( const char plaintext[], char ciphertext[], const char key[] )
{
int idx;
int j;
for( idx = 0, j = 0; idx <= strlen(plaintext); idx++ )
{
if ( CHAR_OUT_OF_RANGE(plaintext[idx]) )
{
ciphertext[idx] = plaintext[idx];
}
else
{
ciphertext[idx] = plaintext[idx];
ciphertext[idx] += key[j] - MIN_ASCII_VALUE;
if (ciphertext[idx] >= MAX_ASCII_VALUE) ciphertext[idx] += -MAX_ASCII_VALUE + MIN_ASCII_VALUE - 1;
}
j = (j + 1) % strlen(key);
}
ciphertext[idx] = 0;
}
for instance: if I enter the plaintext toner with a key of jerry the output will be csevé. It should change it to csevp
Do everybody (especially yourself) a favor, and use std::string instead of C-style strings. Then use a standard algorithm instead of writing messing up the loops on your own.
#include <iostream>
#include <iterator>
#include <algorithm>
class crypt {
std::string key;
size_t pos;
public:
crypt(std::string const &k) : key(k), pos(0) { }
char operator()(char input) {
char ret = input ^ key[pos];
pos = (pos + 1) % key.size();
return ret;
}
};
int main() {
std::string input("This is some input to be encrypted by the crappy encryption algorithm.");
std::transform(input.begin(), input.end(),
std::ostream_iterator<char>(std::cout),
crypt("This is the key"));
return 0;
}
Your loop is going one-to-far. You should use < instead of <=. And I assume you should be testing for > MAX_ASCII_VALUE, not >= (but you haven't shown what MAX_ASCII_VALUE is).
But your basic problem is a signed vs. unsigned char problem. With signed chars, when it goes above 127 it wraps around and becomes negative, so the > test will fail when it should have passed.
void vigenereEncrypt(const char plaintext[], char ciphertext[], const char key[])
{
size_t i, j;
for(i = 0, j = 0; i < strlen(plaintext); ++i )
{
ciphertext[i] = plaintext[i];
if (!CHAR_OUT_OF_RANGE(plaintext[i]))
{
ciphertext[i] += (uchar)key[j] - (uchar)MIN_ASCII_VALUE;
if ((uchar)ciphertext[i] > (uchar)MAX_ASCII_VALUE)
ciphertext[i] -= (uchar)MAX_ASCII_VALUE - (uchar)MIN_ASCII_VALUE + 1;
}
j = (j + 1) % strlen(key);
}
ciphertext[i] = 0;
}