Using char* to store integers - c++

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();
}

Related

Multiplying two ridiculously large number stored in an array of chars C++

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

Buffer overrun warning

This script spreads all the digits of a number in an array, so that by doing this: spread(number)[position] you can access the digit with relative position. Now the compilers gives me a Buffer overrun warning (C6386), which I assume is caused by exceeding an array bounds (correct me if I'm wrong), but I scripted the function such that such thing doesn't happen, and the program is still malfunctioning
#include <iostream>
#include <math.h>
using namespace std;
unsigned int size(long long int num)
{
unsigned int size = 1;
while (num >= pow(10, size)) size++;
return size;
}
int* spread(int num)
{
unsigned int digit;
int* nums = new int[size(num)];
for (unsigned int P = 0; P <= size(num) - 1; P++)
{
digit = num - num / 10 * 10;
num /= 10;
nums[P] = digit; //Right in this line the program doesn't seem to behave correctly
}
return nums;
}
int main()
{
cout << split(377)[0] << endl;
cout << split(377)[1] << endl;
cout << split(377)[2] << endl;
system("PAUSE");
return 0x0;
}
/*
Output of the program:
7
7
-842150451 <-- there should be a 3 here
Press any key to continue . . .
*/
The body of your for loop interferes with your end condition:
P=0, num=377, size(num) = 3, P <= 2 = true
P=1, num=37, size(num) = 2, P <= 1 = true
P=2, num=3, size(num) = 1, P <= 0 = false
The fix is to calculate size(num) up front and use that in your loop condition:
int numdigits = size(num);
for (int P=0; P < numdigits; P++) { ... }
{
unsigned int digit;
int* nums = new int[size(num)];
int P = 0;
while(num!=0)
{
digit = num - num / 10 * 10;
num /= 10;
nums[P++] = digit; //Right in this line the program doesn't seem to behave correctly
}
return nums;
}
You will store the digit until the number is 0.
Use this condition and your Code works.
But you have memory leaks...
You have to free dynamic memory!
Update: There is a short code, which works ;-)
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<size_t> spread(int const num)
{
string number = to_string(num);
vector<size_t> digits;
for(size_t i = 0; i < number.size(); ++i)
{
digits.push_back(number[i] - '0');
}
return digits;
}
int main()
{
auto vec = spread(12345000);
for (auto elem : vec)
{
cout << elem << endl;
}
system("PAUSE");
return 0x0;
}

Recursive function to generate string does not contain two adjacent identical substring c++

I have a task that is difficult for me to handle. The task is: Create recursive function that can be generate a string of length N (N <= 100), formed by the letters 'A', 'B' and 'C' and does not containing two identical adjacent substring. For example: enter for N = 6 and the program should generate such a string in which no one else to repeated substrings: ABACAB. Wrong strings are: AABACA - because 'A' is to 'A'; ABCBCA - as 'BC' is to 'BC' and ABCABC is also wrong because 'ABC' is to 'ABC'.
I made a version of the program but an iterative way, here is the code:
#include <iostream>
#include <ctime>
using namespace std;
const char letters[] = "ABC";
char generate_rand()
{
return letters[rand() % 3];
}
int check(char *s, int pos)
{
for (int i = 1; i <= (pos + 1)/2; i++)
{
int flag = 1;
for (int j = 0; j < i; j++)
if (s[pos-j] != s[pos-i-j])
{
flag = 0;
break;
}
if (flag)
return 1;
}
return 0;
}
int main()
{
char s[100];
int n;
cout << "enter n: ";
cin >> n;
srand(time(NULL));
for (int i = 0; i < n; i++)
{
do
{
s[i] = generate_rand();
} while (check(s, i));
cout << s[i] << " ";
}
cout << " ok" << endl;
system("pause");
return 0;
}
I think the entrance of the recursive function may need to be the number of characters in the string, which will seek to repeat with an adjacent string and each time increased by 1, but not more than half the length of the original string, but do not know how to do it.
So lets start with a simple recursive function which prints 10 letters but doesn't check anything:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (strlen(buf) < max_length)
addLetter(buf);
}
int main()
{
srand(time(NULL)); //I forgot srand!
int max_length = 10; //ask user to input max_length, like you had earlier
char buf[100];
memset(buf,0,sizeof(buf));
addLetter(buf, max_length);
printf("\n%s\n", buf);
return 0;
}
Now lets change the recursive function, get it to check just 1 letter:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (len > 0)
{
if (buf[len] == buf[len-1])
buf[len] = 0;
}
if (strlen(buf) < max_length)
addLetter(buf);
}
Next step, check 2 letters with previous ones etc. You should be able to take it from here.

C++ Binary to Decimal and Back Converter

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

How to modify string to char array in C/C++?

i'm writing a program called 'Zuma'. The program works like this.
Input:
ACCBA // a string make up of char from 'A' to 'Z'
5 // number of inputs
1 B // insert char 'B' to position '1' of the string
0 A // and so on...
2 B
4 C
0 A
When 3 same chars next to each other, we erase/remove/delete them from the string.
For example, when we insert char 'C' to position 2 of string 'ABCC', we got 'AB' because
'CCC' are removed from the string.
Output:
ABCCBA
AABCCBA
AABBCCBA // the process is AABBCCCBA -> AABBBA -> AAA -> -
- // if the string is empty, we output "-"
A
This is my code with string:
#include <iostream>
using namespace std;
int main()
{
int n, pos;
int k = 0;
int length = 0;
string zuma, marble; // i use string
cin >> zuma;
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> pos >> marble;
zuma.insert(pos, marble);
length = zuma.length(); // length of current string
// compare each char from pos[i] with pos[i+1] and pos[i+2]
// and then ++i until end of string
while (k != length && length >= 3)
{
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
zuma.erase(k, 3); // erase 3 same char in the string
k = 0; // set k to zero to start from pos[0] again
}
else
k++;
}
// if string is not empty
if (!zuma.empty())
{
cout << zuma << endl; // output the current char in the string
k = 0;
}
else
cout << "-" << endl;
}
return 0;
}
This is my code with char array:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
void append (char subject[], const char insert[], int pos) {
char buf[100] = {};
strncpy(buf, subject, pos);
int len = strlen(buf);
strcpy(buf+len, insert);
len += strlen(insert);
strcpy(buf+len, subject+pos);
strcpy(subject, buf);
}
int main()
{
int n, pos;
int k = 0;
int length = 0;
char zuma[100], marble[100];
scanf("%s", zuma);
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%d %s", &pos, marble);
append(zuma, marble, pos); // acts like string::insert
length = strlen(zuma);
while (k != length && length >= 3)
{
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
//zuma.erase(k, 3); // need help with this part to remove 3 same chars like string::erase
k = 0;
}
else
k++;
}
if (strlen(zuma) != 0)
{
printf("%s\n", zuma);
k = 0;
}
else
printf("%s\n","-");
}
return 0;
}
My problem is how to write a function to remove 3 same chars just like what string::erase do?
Thanks for your help!!
You can use memmove to copy the remainder of the string to the position of the characters to remove. Use strlen to determine how much bytes to move. Note you cannot use strcpy because the source and destination buffers overlap.
if (zuma[k] == zuma[k + 1] && zuma[k] == zuma[k + 2])
{
int len = strlen(zuma+k+3) + 1; // +1 to copy '\0' too
memmove(zuma+k, zuma+k+3, len);
k = 0;
}