I've almost solved this exercise:
Binary to Decimal and Back Converter - "Develop a converter to convert a decimal number to binary or a binary number to its decimal equivalent."
So, the binary to decimal converter works perfectly, but the other one doesn't. convertToBinary() function returns crap and I don't know why. Here is the code:
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
char* convertToBinary(int dec);
int convertToDec(const char* bin);
int main()
{
std::cout << convertToBinary(100) << std::endl; // wtf!
return 0;
}
char* convertToBinary(int dec)
{
char binary[15] = "";
int result;
for(int i = 0; dec >= 1; dec /= 2, ++i)
{
result = !((dec % 2) == 0);
binary[i] = result + 48;
}
for(int i = strlen(binary); strlen(binary) % 4 != 0; ++i) // add some zeros to make it look cool
binary[i] = '0';
for(int i = 0, j = strlen(binary)-1; i < j; ++i, --j) // reverse the array
{
char temp = binary[i];
binary[i] = binary[j];
binary[j] = temp;
}
std::cout << binary << std::endl; // looking good!
return binary;
}
int convertToDec(const char* bin)
{
int dec = 0;
int size = strlen(bin);
for(int i = 0; *bin; ++i, ++bin)
{
int ch = *bin - 48;
dec += ch * pow(2, size - i - 1);
}
return dec;
}
Using c language
char *convertToBinary(int value)
{
char *binary;
size_t length;
size_t i;
length = 8 * sizeof(value);
binary = malloc(1 + length);
if (binary == NULL)
return NULL;
for (i = 0 ; i < length ; ++i)
binary[length - i - 1] = (value & (1 << i)) ? '1' : '0';
binary[length] = '\0';
return binary;
}
int binaryToDecimal(const char *binary)
{
int value;
size_t length;
size_t i;
value = 0;
length = strlen(binary);
for (i = 0 ; i < length ; i++)
value |= (binary[i] == '1') ? (1 << (length - i - 1)) : 0;
return value;
}
Using c++ language
std::string convertToBinary(int value)
{
std::string binary;
size_t length;
length = 8 * sizeof(value);
binary.resize(length);
for (size_t i = 0 ; i < length ; ++i)
binary[length - i - 1] = (value & (1 << i)) ? '1' : '0';
return binary;
}
int binaryToDecimal(const std::string &binary)
{
int value;
size_t length;
value = 0;
length = binary.length();
for (size_t i = 0 ; i < length ; i++)
value |= (binary[i] == '1') ? (1 << (length - i - 1)) : 0;
return value;
}
to convert from binary to decimal, you can use strtol of course.
Your mistake is returning a local variable, a local variable is automatically deallocated when the function returns, and hence the garbage you got.
When you do something like this:
char *toString(...)
{
char res[MAX_RES];
// fill res
return res;
}
you create the array res as a local array on the stack. This array goes out of scope when you return from the function; a pointer to this array is no longer valid and most likely will point to garbage.
If you want to use C-style char buffers, there are two ways to get around this:
Allocate the result on the heap.
char *toString(...)
{
char *res = malloc(MAX_RES);
// fill res
return res;
}
Data allocated on the heap with malloc will be valid until explicitly released with free. The advantage of this approach is that you can make the string as long as you wish. Thedrawback is that the allocation might fail. It is also worth noting that the caller now owns the string and is responsible for freeing it:
char *x = toString(...);
// do stuff with x
free(x);
**Pass the buffer and maximum length **
int toString(char *res, size_t max, ...)
{
// fill res
}
That is the approach many library functions use, notably snprintf. The caller has to provide their own buffer and information on the maximum allowable length in order to avoid buffer overflows. This approach must keep track of the buffer size and truncate the result if necessary, possibly maintaining the string null-terminated. Such functions could be void, but it is customary to return the actual string length or -1 as error indicator.
It is called like this:
char x[200];
toString(x, sizeof(x), ...);
// do stuff with x
Related
I have an assignment which requires me to write a program that multiplies two large numbers that are each stored in an array of characters with the maximum length of 100. After countless efforts and debugging and multiplying 10 digit numbers step by step and by hand I have now written the following piece of messy code:
#include <iostream>
#include <string.h>
using namespace std;
const int MAX_SIZE = 100;
int charToInt(char);
char IntToChar(int);
long long int pow10(int);
bool isNumber(char[]);
void fillWith0(char[], int);
void multiply(char[], char[], char[]);
int main(){
char first_num[MAX_SIZE + 1], second_num[MAX_SIZE + 1], product[2 * MAX_SIZE + 1];
cout << "A =\t";
cin.getline(first_num, MAX_SIZE);
cout << "B =\t";
cin.getline(second_num, MAX_SIZE);
multiply(first_num, second_num, product);
cout << "A * B = " << product << endl;
return 0;
}
int charToInt(char ch){
return ch - '0';
}
char intToChar(int i){
return i + '0';
}
long long int pow10(int pow){
int res = 1;
for (int i = 0; i < pow ; i++){
res *= 10;
}
return res;
}
bool isNumber(char input[]){
for (int i = 0; input[i] != '\0'; i++){
if (!(input[i] >= '0' && input[i] <= '9')){
return false;
}
}
return true;
}
void fillWith0(char input[], int size){
int i;
for (i = 0; i < size; i++){
input[i] = '0';
}
input[i] = '\0';
}
void multiply(char first[], char second[], char prod[]){
_strrev(first);
_strrev(second);
if (isNumber(first) && isNumber(second)){
fillWith0(prod, 2 * MAX_SIZE + 1);
int i, j, k;
long long int carry = 0;
for (i = 0; second[i] != '\0'; i++){
for (j = 0; first[j] != '\0'; j++){
long long int mult = (pow10(i) * charToInt(first[j]) * charToInt(second[i])) + carry + charToInt(prod[j]);
prod[j] = intToChar(mult % 10);
carry = mult / 10;
}
k = j;
while (carry != 0){
carry += charToInt(prod[k]);
prod[k] = intToChar(carry % 10);
carry = carry / 10;
k++;
}
}
prod[k] = '\0';
_strrev(first);
_strrev(second);
_strrev(prod);
}
}
My problem is that it does not work with numbers that have more than 10 digits (1234567891 * 1987654321 works fine but nothing with more digits than that), as the output in those cases is a set of weird characters I presume the issue is somewhere something is overflowing and causing weird issues, although I have used long long int to store the only two numeric integers in the algorithm, doing so helped me bump from 6 digits to 10 but nothing more. Is there any suggestions or possibly solutions I can implement?
P.S. : As I mentioned before this is an assignment, so using libraries and other stuff is not allowed, I've already seen this implemented using vectors but unfortunately for me, I can't use vectors here.
The core mistake is using a long long int to store the intermediate multiplied number. Instead, use another char[] so the core of your multiply becomes simply:
for (i = 0; second[i] != '\0'; i++){
char scratch[2 * MAX_SIZE + 1];
// Fill up the first i positions with 0
fillWith0(scratch, i);
// Store second[i] * first in scratch, starting at position i.
// Make sure to 0-terminate scratch.
multiplyArrWithNumber(&scratch[i], intToChar(second[i]), first);
// Add pairwise elements with carry, stop at the end of scratch
addArrays(scratch, prod);
}
trying to format this function as it will truncate an array of char (anything that the user enters it will split that up to a number the user also enters)
void truncate(char array[], int maxLength)
{
// Variable definition
int x = 0;
// While loop start.
while (array[x] <= maxLength)
{
cout << array[x];
x++;
}
}
The array parameter in the function header is just a string that was entered by the user, its an array of char. And the maxLength parameter is an int variable entered by the user as well, it could be 3, 4 or 5. The maxLength is supposed to act as the null termination whatever the user enters the string will truncate after that number.
But this code doesn't work, it doesn't display an output for the function. Anyone know what I'm doing wrong? Thanks.
The problem here is this:
while (array[x] <= maxLength)
This is comparing the character returned from the array at x to the value of maxLength, so you're comparing a char to an int. I would recommend the more standard for loop for this:
for (int x = 0; x < maxLength; x++) {
cout << array[x];
}
int truncate(const char *str, int maxchunk, char ***chunks)
{
int len = strlen(str);
int nchunks = len / maxchunk + !!(len % maxchunk);
char **table = malloc(sizeof(char *) * (nchunks));
if (table != NULL)
{
for (int i = 0; i < nchunks; i++)
{
if ((table[i] = malloc(sizeof(char) * maxchunk + 1)) == NULL)
{
for (int j = i - 1; j >= 0; j--)
{
free(table[j]);
}
free(table);
table = NULL;
break;
}
strncpy(table[i], str + i * maxchunk, maxchunk);
*(table[i] + maxchunk) = '\0';
}
}
*chunks = table;
return table == NULL ? -1 : nchunks;
}
I am designing a cipher and need to convert between bases repeatedly in a loop. I have optimized the everything else, but I'm not too familiar with C++ code, and and am trying to figure out how to make the conversion faster.
Here's the current code I'm using:
string digits = "0123456789abcdef";
string tohex(string number) { // Decimal to Hexadecimal function
long length = number.length();
string result = "";
vector<long> nibbles;
for ( long i = 0; i < length; i++ ) {
nibbles.push_back(digits.find(number[i]));
}
long newlen = 0;
do {
long value = 0;
newlen = 0;
for ( long i = 0; i < length; i++ ) {
value = (value * 10) + nibbles[i];
if (value >= 16) {
nibbles[newlen++] = value / 16;
value %= 16;
} else if (newlen > 0) {
nibbles[newlen++] = 0;
};
};
length = newlen;
result = digits[value] + result;
} while (newlen != 0);
return result;
}
In my case (cipher) the number will always fit within an int, so it works to do:
string tohex(string number) {
int num = std::stoi(number);
std::stringstream hexnumber;
hexnumber << std::hex << num;
return hexnumber.str();
}
This is better because it is simpler and uses the built-in std::hex method.
I am trying to convert an integer into a string of numerals stored in char *s.
char* ItoA(int n, char *s){
int mod = n;
for(int x = 1; x <= sizeof(n) + 2; x++){
int digit = mod % 10;
s[x-1] = digit;
mod = mod / 10;
}
return s;
}
void main(){
int n = 12345;
char s3;
// should print 12345
cout << "\n" << ItoA(n, &s3);
cin.get();
}
I know that something is wrong with my notation because I keep getting an array of garbage as the output in main. Why am I getting garbage instead of "12345"?
Q: Why am I getting garbage instead of "12345"?
You are using &s3 as though it were an array of characters.
Use:
int main(){
int n = 12345;
char s3[20]; // Use an array of characters large enough to hold the number.
// should print 12345
cout << "\n" << ItoA(n, s3);
cin.get();
}
Also, it's not clear to me what your logic is for using sizeof(n) below:
for(int x = 1; x <= sizeof(n) + 2; x++)
In order to convert a number to a string, you need to convert to ASCII by adding the character '0'. Also, you need to allocate enough memory to store all the characters and initialize the memory.
Finally the logic of your for loop is broken, and it is generally easier to construct the string backwards and then reverse it.
#include <iostream>
#include <string.h>
using namespace std;
char* ItoA(int n, char *s, int bufLength){
// Create the string in reverse order
int i;
for(i = 0; i < bufLength; i++){
int digit = n % 10;
s[i] = digit + '0';
n /= 10;
if (n == 0) break;
}
// Reverse the string.
for (int j = 0; j <= i / 2; j++) {
char c = s[j];
s[j] = s[i - j];
s[i - j] = c;
}
return s;
}
int main(){
int n = 12345;
char s3[6];
memset(s3, 0, 6);
// should print 12345
cout << "\n" << ItoA(n, s3, 6);
cin.get();
}
I have a string like str="ABCDEFGHIJK";
need o/p like this str="CBAFEDIHGJK"
am getting "CBA" correctly after that its not printing anything.
can anyone check the following code and let me know where is the problem?
int main()
{
string str="ABCDEFGHIJK";
char str1[10],rev[10];
int n=str.length(),count=0,c=3,k=0,j=0;
for(int i=0;i<n;i++)
{
str1[i]=str[i];
count++;
cout<<str1[i]<<" and "<<count<<"and "<<c<<endl;
if(count==c)
{
cout<<"Entered into if loop"<<count<<"and"<<c<<"and "<<k<<endl;
cout<<c<<" and "<<k<<endl;
while(j<c)
{
rev[j]=str1[c-k-1];
cout<<rev[j]<<" and "<<str1[c-k-1]<<endl;
j++;
k++;
}
count=0;
}
/*else
{
if(count < c && str[i]=='\0')
{
for(int k=0;k<count;k++)
{
rev[k]=str1[count-1];
count--;
count=0;
}
}
}*/
}
cout<<"The string is: "<<rev<<endl;
return 0;
}
Please help me on this.
No need to use a c++ string object for this use-case; just use a normal char *.
Also, always make sure you store enough room for the string null-terminator character ('\0'). This is required as c string functions assume your string is terminated in this way.
Following will reverse string in ansi C89
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse(char *in, char *rev)
{
int i, n;
n = strlen(in);
for(i = n-1; i>=0; i--)
{
rev[n-i-1] = in[i];
}
/* add the null-terminator */
rev[n] = '\0';
}
int main()
{
char *str = "ABCDEFGHIJK";
char str1[12], temp;
char triplet[4];
char rev_triplet[4];
int index;
triplet[3] = '\0';
rev_triplet[3] = '\0';
str1[0] = '\0';
for(index = 0; index < strlen(str); index += 3)
{
memcpy(triplet, str + index, 3 * sizeof(char));
reverse(triplet, rev_triplet);
strcat(str1, rev_triplet);
}
printf("Initial string is: %s\n", str);
printf("Reverse string is: %s\n", str1);
return 0;
}
Outputs
$ ./test
Initial string is: ABCDEFGHIJK
Reverse string is: CBAFEDIHGKJ
If you intend to use C++ (and not C) for this:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_triples(std::string s)
{
const unsigned int N = 3;
for (int i = 0, j = N - 1; i < s.length() - (s.length() % N); i += N, j += N)
{
std::swap(s[i], s[j]);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s);
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
Whatever value of N you need can be modified (and even supplied as a function parameter if you want). You only need to swap the outer characters (so all the elements below N / 2 will be swapped with the elements above N / 2). For N == 3, it is just a single swap. If you want to do it more generically:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_substrings(std::string s, unsigned int substring_size)
{
for (int i = 0, j = substring_size - 1; i < s.length() - (s.length() % substring_size); i += substring_size, j += substring_size)
{
std::reverse(s.begin() + i, s.begin() + j + 1);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s, 4); // passing 3 gets you the same results as before
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
First, let us examine how std::reverse might be implemented. It uses iterators.
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
We can extend the logic to use indices instead of iterators, where i and j represent iterators (positions) and s[i] and s[j] represent the data pointed to by the iterators.
void reverse(std::string& s)
{
int i = 0;
int j = s.size();
while ((i != j) && (i != (--j)))
{
std::swap(s[i], s[j]);
++i;
}
}
Now you want to reverse "chunks" rather than the entire string.
void reverse(int n, std::string& s)
{
int beg = 0;
int end = beg + n;
int size = s.size();
// We're going to modify s in place
// So store a copy
std::string copy = s;
s = "";
// Add + 1 to avoid the loop cutting off short
// Or do i <= size / n;
for (int i = 0; i < size / n + 1; i++)
{
std::string chunk(copy.begin() + beg, copy.begin() + end);
// If there's no n sized chunks left
// don't reverse
if (end < size)
reverse(chunk);
s += chunk;
beg += n;
// Don't go past the size of the string
end += (end + n > size ? size - end : n);
}
}
int main()
{
std::string s("ABCDEFGHIJK");
std::string target("CBAFEDIHGJK");
reverse(3, s);
std::cout << s << "|" << target <<"|\n";
std::cout << s.size() << " " << target.size() << "\n"; // 11 11
std::cout << std::boolalpha << (s == target); // true
return 0;
}