I try to design a program that implements the multiplication between two big integers(Using C++). But after I complete it, I found that if I input the two integers by the command arguments, the results would be sometimes very weird and sometimes right. Please help me figure out the reason and tell me how to fix it. Thanks (The main function that implements the function of multiplication between two big integers is mul() ).
#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std;
void mul(char *c1, char *c2, int len1, int len2);
void printArr(char *c1, char *c2, int len1, int len2);
int main(int argc, char **argv)
{
if (argv[1] != NULL)
{
char cArr1[500], cArr2[500];
for (int i = 0; i < strlen(argv[1]); i++)
{
cArr1[i] = argv[1][i];
}
for (int i = 0; i < strlen(argv[2]); i++)
{
cArr2[i] = argv[2][i];
}
int len1 = strlen(cArr1);
int len2 = strlen(cArr2);
printArr(cArr1, cArr2, len1, len2);
(len1 > len2) ? mul(cArr1, cArr2, len1, len2) : mul(cArr2, cArr1, len2, len1);
exit(100);
}
while (true)
{
cout << "Please input two integers" << endl;
char cArr1[500], cArr2[500];
cin >> cArr1;
if (cArr1[0] == 'q' && cArr1[1] == 'u' && cArr1[2] == 'i' && cArr1[3] == 't')
{
exit(1000);
}
cin >> cArr2;
int parity = 0;
int len1 = strlen(cArr1);
int len2 = strlen(cArr2);
printArr(cArr1, cArr2, len1, len2);
if (cArr1[0] == '-')
{
for (int i = 1; i < len1; i++)
{
cArr1[i - 1] = cArr1[i];
}
parity++;
len1--;
}
if (cArr2[0] == '-')
{
for (int i = 1; i < len2; i++)
{
cArr2[i - 1] = cArr2[i];
}
parity++;
len2--;
}
bool isDigit = true;
for (int i = 0; i < len1; i++)
{
if (!isdigit(cArr1[i]))
{
isDigit = false;
}
}
for (int i = 0; i < len2; i++)
{
if (!isdigit(cArr2[i]))
{
isDigit = false;
}
}
if (!isDigit)
{
cout << "\rInvalid input. Try again" << endl;
continue;
}
if (parity % 2 != 0)
{
cout << "-";
}
(len1 > len2) ? mul(cArr1, cArr2, len1, len2) : mul(cArr2, cArr1, len2, len1);
}
}
void mul(char *bigger, char *smaller, int bigLen, int smallLen)
{
int *bigNum = new int[bigLen];
int *smallNum = new int[smallLen];
for (int i = 0; i < bigLen; i++)
{
bigNum[i] = bigger[bigLen - i - 1] - '0';
}
for (int i = 0; i < smallLen; i++)
{
smallNum[i] = smaller[smallLen - i - 1] - '0';
}
int res[30];
for (int i = 0; i < 30; i++)
{
res[i] = 0;
}
for (int i = 0; i < smallLen; i++)
{
for (int j = 0; j < bigLen; j++)
{
res[i + j] += bigNum[j] * smallNum[i];
}
}
for (int i = 0; i < bigLen + smallLen; i++)
{
int digit = res[i] % 10;
int carry = res[i] / 10;
res[i] = digit;
res[i + 1] += carry;
}
bool null = false;
for (int i = bigLen + smallLen - 1; i >= 0; i--)
{
if (res[i] != 0 && res[i + 1] == 0)
{
null = true;
}
if (null)
{
cout << res[i];
}
}
cout << endl;
}
void printArr(char *c1, char *c2, int len1, int len2)
{
for (int i = 0; i < len1; i++)
{
cout << c1[i];
}
cout << " * ";
for (int i = 0; i < len2; i++)
{
cout << c2[i];
}
cout << " = ";
}
Just initialize your char arrays to empty ones:
char cArr1[500] = {};
char cArr2[500] = {};
then, for the sake of clarity, assign the lengths from your arguments to two integers, casting them since the compiler might warn you about incompatibility between size_t and int.
int lenArg1 = 0;
int lenArg2 = 0;
lenArg1 = (int)strlen ( argv[1] );
lenArg2 = (int)strlen ( argv[2] );
Then, printing the lengths len1 and len2 for debugging purposes only:
int len1 = strlen ( cArr1 );
int len2 = strlen ( cArr2 );
cout << "len1 >> " + to_string(len1) <<endl;
cout << "len2 >> " + to_string(len2) <<endl;
In fact, as #Kevin SUN mentioned, it was possible that your argument reading steps were missing the null characters, however, after running some tests it seems to work fine just by initializing the char arrays.
Also, as mentioned in the comments you need to increase the size reserved for res array, I did it to 500
Compiled with g++ -Wall main.cpp -o calc.exe and running: calc 10 100
Without initialization you get problems like:
after initializing, the output works just fine:
Related
I have following code which is simply tokenizing an array and then deviding on the basis of '<' and '>' characters. It is running fine in VS community 2019 but when I run it in Linux using g++ command it gives
Free(): invalid pointer
and
Aborted (core dumped)
errors. What am I doing wrong.
PS: error seems to be in the instructions where I am deallocating b in rangbrk and langbrk because when I put it in comments it runs fine in Linux too. But it runs fine in VS 2019 anyways.
//#include <sys/types.h>
//#include <sys/wait.h>
//#include <sys/stat.h>
#include <fcntl.h>
//#include <unistd.h>
#include<string.h>
#include<stdio.h>
#include<fstream>
#include<iostream>
#include<stdlib.h>
using namespace std;
//_________________________________________________________
int reads(char str[])
{//a simple function to get input
int s = 1;
char buffer[100];
cout << "enter command" << endl;
cin.getline(buffer, 100);
if (strlen(buffer) == 0)
{
cout << "Couldnt get input\n";
return 0;
}
for (int i = 0; i <= strlen(buffer); i++)
{
str[i] = buffer[i];
if (buffer[i] == 32)
s++;
}
return s;
}
//____________________________________________________________
int tokenizing(char** a, char str[], char buff[50], int x)
{//a function to devide a complete string into smaller parts
//also stores '/bin/command' into buff to pass as first parameter of execvp
int k = 0, m = 0;
bool check = false;
for (int i = 0; i < x; i++)
{
a[i] = new char[50];
for (int j = 0; str[k] != 32; j++)
{
if (str[k] == 0)
{
check = true;
break;
}
a[i][j] = str[k];
if (i == 0)
buff[j + 5] = str[k];
k++;
a[i][j + 1] = 0;
if (i == 0)
buff[j + 6] = 0;
}
m++;
k++;
if (check)
break;
}
return m;
}
//__________________________________________________________
void rangbrk(char**& a, char**& b, int& x, char filename[])
{//saperates the array before and after '>'
for (int i = 0; i < (x - 2); i++)
{
b[i] = new char[50];
for (int j = 0; j < 50; j++)
{
b[i][j] = a[i][j];
}
}
b[x - 2] = NULL;
for (int i = 0; i < 50; i++)
{
filename[i] = a[x - 1][i];
}
char** c;//temprory pointer to swap a and b
c = a;
a = b;
b = c;
x = x - 2;
for(int i=0;i<x-1;i++)
{
delete [] b[i];
}
b=NULL;
}
//__________________________________________________________
void langbrk(char** &a, char** &b, int& x, int index, char filename[])
{//saperates the array before and after '<'
int k = 0;
for (int i = 0; i < x; i++)
{
if ((i != index) && (i != index - 1))
{
b[k] = new char[50];
for (int j = 0; j < 50; j++)
{
b[k][j] = a[i][j];
}
k++;
}
}
b[x - 2] = NULL;
for (int i = 0; i < 50; i++)
{
filename[i] = a[index - 1][i];
}
char** c;//temprory pointer to swap a and b
c = a;
a = b;
b = c;
x = x - 2;
for(int i=0;i<x-1;i++)
{
if(b[i]!=NULL)
delete [] b[i];
}
b=NULL;
}
//__________________________________________________________
int main()
{
char buff[50] = { "/bin/" };
char str[100];
char exit[5] = { 'e','x','i','t',0 };
char outfile[50];
char infile[50];
int x = reads(str);
char** a;
a = new char* [x];
int s = tokenizing(a, str, buff, x);
a[s] = NULL;
bool flag = false;
for (int i = 0; a[i] != NULL; i++)
cout << a[i] << endl;
cout << s << endl;;
for (int i = 0; i < s; i++)
{
if (a[i][0] == '>')//checks if it need to print in a file
{
cout << i;
char** b;
b = new char* [s - 2];
rangbrk(a, b, s, outfile);
flag = true;
cout << "New" << endl;
for (int j = 0; j < s; j++)
cout << a[j] << endl;
i = 0;
}
else if (a[i][0] == '<')
{
cout << i;
char** c;
c = new char * [s - 2];
langbrk(a, c, s, i, infile);
cout << "New" << endl;
for (int j = 0; j < s; j++)
cout << a[j] << endl;
i = 0;
}
}
}
The reads function gets input, tokenizing tokenized the string in form of words. langbrk copies the string having index 1 less than index of '<' in infile and removes them both from main char** a. rangbrk removes '>' and string succeeding it from a and stores it in outfile
I want to input alphabet to binary code, and output the alphabet from generated binary code.
Example
1 --> a
01 --> b
001 --> c
0001 --> d
00001 --> e
000001 --> f
a => 1
b => 01
c => 001
d => 0001
e => 00001
-------------Encode.cpp--------------------
#include "Encode.h"
Encode::Encode()
{
}
Encode::~Encode()
{
}
void Encode::inputWord()
{
cout << "Input word: ";
cin.getline(word, 255);
return;
}// User input a word
char * Encode::getBuf(void)
{
return buffer;
}// return buffer to Decode::setBuf(char* buf)
void Encode::printEncResult()
{
int size = strlen(word);
int buffersize = 0;
cout << "Encoding result" << endl; // print similar binary
for (int i = 0; i < size; i++)
{
if (word[i] == 'z')
{
for (int j = 0; j < 25; j++)
{
cout<<buffer[buffersize++];
}
}
else
{
int len = (int)word[i] - (int)'a';
for (int j = 0; j < len; j++)
{
cout<<buffer[buffersize++];
}
cout << buffer[buffersize++];
}
}
}// output similar binary
int Encode::encodeWord(void)
{
int buffersize = 0;
int size = strlen(word);
for (int i = 0; i < size; i++)
{
if (word[i] == 'z')
{
for (int j = 0; j < 25; j++)
{
buffer[buffersize++] = '0';
}
}
else
{
int len = (int)word[i] - (int)'a';
for (int j = 0; j < len; j++)
{
buffer[buffersize++] = '0';
}
buffer[buffersize++] = '1';
}
}
return 0;
}// change word to similar binary
--------Decode.cpp-------------
#include "Decode.h"
Decode::Decode()
{
}
Decode::~Decode()
{
}
void Decode::setBuf(char * buf)
{
int i = 0;
int size = 0;
while (*(buf + i) == '1' || *(buf + i) == '0')
{
i++;
}
size = i;
for(int i = 0; i < size; i++)
{
buffer[i] = buf[i];
}
return;
}// set buffer from Encode::getBuf(void)
void Decode::printWord() // print similar binary
{
int i = 0;
int size = 0;
int check = 1;
while (check)
{
if (word[i] >= 'a' && (int)word[i] <= 'z')
{
i++;
size = i;
}
else
check = 0;
}
cout << "Decoding result" << endl;
for (int i = 0; i < size; i++)
{
if (word[i] >= 'a' && (int)word[i] <= 'z') // **this part is also strange** I can not shoten the code.
cout<<word[i];
}
cout << endl;
}
int Decode::decodebin(vector<char> buffer)
{
int buffersize = 0;
int check = 0;
int size = 0;
int i = 0;
char printval = 'a';
while (buffer[i] == '1' || buffer[i] == '0')
{
i++;
}
size = i;
for (int j = 0; j < size; j++) // nested loop does not work. I want save words in order
{
for (i = 0; i < size; i++)
{
if (buffer[i] == '0')
++printval;
else
{
word[j] = printval; // In this part, word[0] does not have any value.
printval = 'a';
}
}
}
return 0;
}
In this code, I want save values in order, but word[0] does not have any value. Moreover, If I input 'bb' then, 'bbbb' saved ins word array.
There are some problems and consideration you need to take care of:
as Fei Xiang said in the comments don't use magic numbers, use characters since you have a character array.
int printWord function you actually get the word and print the same word, there is no conversion as your problem statement. your didn't take buffer into account.
you are using some data validation to get your array size, this could end up a disaster(UB). you need to pass your array size to your function or use std::vector(Recommended).
in this statement if ((int)word[i] >= 97 || (int)word[i] <= 122) as I said don't use magic number and || should be change to && otherwise you end up in an infinity loop.
Anyway by keeping your approach(using array) and function signature here's what you can do :
int Decode::decodebin(void)
{
int buffersize = 0;
int check = 0;
int size = 0;
int i = 0;
char printval = 'a';
while(buffer[i] == '1' || buffer[i] == '0')
{
i++;
size = i;
}
for(int i = 0; i < size; i++)
{
if(buffer[i] == '0')
++printval;
else
{
cout << printval;
printval = 'a';
}
}
return 0;
}
void Decode::printWord()
{
int i = 0;
int size = 0;
int check = 1;
while(check)
{
if(word[i] >= 'a' && word[i] <= 'z')
{
i++;
size = i;
}
else
check = 0;
}
cout << "Decoding result" << endl;
for(int i = 0; i < size; i++)
{
int distance = word[i] - 'a';
for(int j = 0; j < distance; ++j)
cout << '0';
cout << '1';
}
cout << endl;
}
EDIT BASED ON OP REQUIREMENT IN COMMENTS:
using std::vector you can implement your needs like this :
#include <iostream>
#include <vector>
class Decode
{
public:
void decodebin(std::vector<char> buffer)
{
char printval = 'a';
for(unsigned int i = 0; i < buffer.size(); i++)
{
if(buffer[i] == '0')
++printval;
else
{
word.push_back(printval);
printval = 'a';
}
}
}
void printWord(void)
{
for(auto iter = word.begin(); iter != word.end(); ++iter)
std::cout << *iter;
std::cout << std::endl;
}
private:
std::vector<char> word;
};
int main()
{
Decode decoder;
std::vector<char> buffer = {'0', '1', '0', '0', '0', '0', '1', '0', '0', '0', '1'};
decoder.decodebin(buffer);
decoder.printWord();
return 0;
}
Here decodebin stores the given input into word member variable of Decode class. Then printWord function print word values on the screen.
std::vector has all the power of C-style array and it's nicer and easier to use. You can retrieve it's size whenever you want and you don't have to worry about the memory it's allocating.
Hi i have a problem with my code, i try sort array by counting sort (it must be stable sort), but my code doesn't work. I try implemented counting-sort from some wbesite, but it was in c# and I'm not sure s it done correctly. Can you tell me what is wrong with it?
#include <stdio.h>
#include <iostream>
using namespace std;
void sort_with_show(int **a, int rozmiar, int polecenie)
{
int y, d;
for (int i = 0; i< rozmiar - 1; i++)
{
for (int j = 0; j < rozmiar - 1 - i; j++)
{
if (a[j + 1][0] < a[j][0])
{
y = a[j][0];
a[j][0] = a[j + 1][0];
a[j + 1][0] = y;
}
}
}
for (int i = 0; i < rozmiar; i++)
{
//cout << tablica[i].x << " " << tablica[i].y << "\n";
if (polecenie == 0)
{
cout << a[i][0] << '\n';
}
else if (polecenie == 1)
{
cout << a[i][0] << "," << a[i][1] << "\n";
}
}
}
int main()
{
int rozmiar = 0;
int polecenie = 0;
char t[20] = { '\0' };
char *p, *q;
int liczba = 0;
int calaLiczba = 0;
bool isY = false;
cin >> rozmiar;
int ** a = new int *[rozmiar];
for (int i = 0; i < rozmiar; i++)
a[i] = new int[2];
cin.ignore();
int i = 0;
while(i < rozmiar)
{
fgets(t, sizeof t, stdin);
for (p = t, q = t + sizeof t; p < q; p++)
{
if (*p >= 48 && *p <= 57)
{
liczba = *p - 48;
calaLiczba = calaLiczba * 10 + liczba;
}
if (*p == ' ')
{
a[i][0] = calaLiczba;
isY = true;
calaLiczba = 0;
liczba = 0;
}
if (*p == '\n')
{
a[i][1] = calaLiczba;
isY = false;
}
}
for (int j = 0; j < 20; j++)
t[j] = '\0';
liczba = 0;
calaLiczba = 0;
isY = false;
i++;
}
cin >> polecenie;
cin.ignore();
sort_with_show(a, rozmiar, polecenie);
return 0;
}
I have an assignment for school where I need to create a lottery program. It is supposed to allow the user to input six numbers and then generate six random numbers for comparison. I got the inputs working, but I have encountered a problem where the random number generator (located in the while loop) is stuck in an infinite loop, and I have absolutely no idea what is causing it since I have never had an infinite loop in any previous programs. If someone could please look through the code and possibly establish what is wrong, I would greatly appreciate it.
#include<iostream>
#include<time.h>
using namespace std;
void randomizeSeed();
int randomRange(int min, int max);
int getInteger();
int main()
{
randomizeSeed();
const int minNumber = 1;
const int maxNumber = 49;
const int Size = 6;
int luckyNumbers[6] = {};
int randomNumber = randomRange(minNumber, maxNumber);
int winningNumbers[6] = {};
cout << "Enter six numbers between 1 and 49...\n";
{
for (int i = 0; i < Size; i++)
{
luckyNumbers[i] = getInteger();
}
for (int i = 0; i < Size; i++)
{
for (int i = 0; i < Size - 1; i++)
{
if (luckyNumbers[i] > luckyNumbers[i + 1])
{
int temp = luckyNumbers[i];
luckyNumbers[i] = luckyNumbers[i + 1];
luckyNumbers[i + 1] = temp;
}
}
}
cout << "Lucky Numbers: ";
for (int i = 0; i < Size; i++)
{
cout << luckyNumbers[i] << " ";
}
cout << "\n";
cout << "Press any button to see the Winning Numbers.\n";
system("pause");
bool exist = true;
while (exist == true)
{
int count = 0;
cout << "Winning Numbers: ";
for (int j = 0; j < 6; j++)
{
winningNumbers[j] = randomRange(1, 49);
cout << winningNumbers[j] << " ";
system("pause");
}
}
}
}
void randomizeSeed()
{
srand(time(NULL));
}
int randomRange(int min, int max)
{
int randomValue = rand() % (max + 1 - min) + min;
return randomValue;
}
int getInteger()
{
int value = 0;
while (!(cin >> value) || (value >= 50) || (value <= 0))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
return value;
}
for (int i = 0; i < Size; i++)
for (int i = 0; i < Size - 1; i++)
if (luckyNumbers[i] > luckyNumbers[i + 1])
{
int temp = luckyNumbers[i];
luckyNumbers[i] = luckyNumbers[i + 1];
luckyNumbers[i + 1] = temp;
}
You have two loops and they both use i. You probably mean to use the second loop with another variable name, for example:
for (int i = 0; i < Size; i++)
{
for (int k = 0; k < Size - 1; k++)
{
if (luckyNumbers[i] > luckyNumbers[k + 1])
{
int temp = luckyNumbers[i];
luckyNumbers[i] = luckyNumbers[k + 1];
luckyNumbers[k + 1] = temp;
}
}
}
If you set your compiler warning level to 4 then compiler should warn you about these errors. Try to resolve all compiler warnings.
I want to create a big number with 128 bit.
When I convert the string decimal to binary and set bit to the new data QInt :__int64 a[2], it only true for a small number (about 10 digits).
This is my code: http://codepad.org/HmYqMQme
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
//new data
class QInt
{
private:
__int64 a[2];
public:
void Get()
{
cout << a[0] << endl;
cout << a[1] << endl;
}
QInt()
{
a[0] = 0;
a[1] = 0;
}
//the funtion get the string binary of a[1]
char* GetQInt(char *A);
//the devide two of string decimal
char* Div2(char *Str);
//the funtion set bit to a[0] and a[1]
void Setbit(int i, int bit);
//con vert decimal to binary
QInt ConvertDecimalToBinary(char *De, char *Bi);
};
//the funtion get the string binary of a[1]
char *QInt::GetQInt(char *A)
{
for (int i = 0; i < 64; i++)
{
if (((a[1] >> i) & 1) != 0)
{
A[63 - i] = 49;
}
else
{
A[63 - i] = 48;
}
}
return A;
}
// the funtion set bit to a[0] and a[1]
void QInt:: Setbit(int i, int bit)
{
//if i<64 we set bit to a[1]
if (i < 64)
{
if (bit==1)
{
a[1]=(1 << i) | a[1];
}
}//similar to a[1]
else
{
if (bit == 1)
a[0]=(1 << i) | a[0];
}
}
//the devide two of string decimal
char*QInt:: Div2(char *Str)
{
char Arr[100];
int n = strlen(Str);
int a = 0;//lay phan du
int i = 0;
int j = 0;
while (Str[i] == 0)
{
i++;
}
for (i; i < n; i++)
{
int c = Str[i] - 48 + a * 10;
a = c % 2;
Arr[j] = c / 2 + 48;
j++;
}
Arr[i] = '\0';
for (i = 0; i < strlen(Arr); i++)
{
Str[i] = Arr[i];
}
Str[i] = '\0';
return Str;
}
//con vert decimal to binary
QInt QInt::ConvertDecimalToBinary(char *De,char *Bi)
{
int bit;
int i = 127;
int lenth = strlen(De);
while (1)
{
//variable h use to count the number 0 of the string decimal,if h=lenth,exit
int k = 0;
int h = 0;
while (De[k])
{
if (De[k] == '0')
h++;
k++;
}
if (h == lenth)
break;
else
{
bit = (De[lenth - 1] - 48) % 2;
Bi[i] = bit + 48;
Setbit(127 - i, bit);
De = Div2(De);
i--;
}
}
Bi[128] = NULL;
return *this;
}
int main()
{
char s[100];
char b[200];
char c[200];
for (int i = 0; i < 128; i++)
{
b[i] = 48;
}
cout << "Please enter a string : ";
gets_s(s, 99);
QInt a;
a.ConvertDecimalToBinary(s, b);
a.Get();
a.GetQInt(c);
for (int i = 0; i < 64; i++)
cout << b[i];
cout << endl;
for (int i = 64; i < 128; i++)
cout << b[i];
cout << endl;
for (int i = 0; i < 64; i++)
{
cout << c[i];
}
cout << endl;
system("pause");
return 0;
}
If i==100, what do you think (1 << i) does? What should it do? And why are you ignoring a[0] in GetQInt ?
In general, you have quite a few problems. You're not comfortable with std::string, and making a mess of the char* everywhere. You're not clearly articulating (not even to yourself) what methods are supposed to be doing. You're putting mathods in a class that are unrelated to the class. Even worse, some of those methods redefine the name a ! That is very confusing.