Subtracting ASCII character/values in C++ [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
This a function of a code I wrote that subtracts two values which are both of type character over and over again to get a text, but the result is not a text of string but symbols instead.
I checked by cout that the keyLetters and analysis have both correct values in ASCII and clear letters before converting them to int.
The lengthText is correct too.
keyLetters is a word of 5 letters.
void originalText(string analysis, string keyLetters) {
int lengthText=analysis.length();
char originText[2000];
int hold;
int k;
for (int i=0; i<lengthText; i++) {
if(i%5==0)
k=0;
hold=keyLetters[k]-analysis[i];
if (hold<=0)
hold*=-1;
originText[i]=(char)hold;
cout<<originText[i];
k++;
}
}
A screenshot of the result I get:

Both keyLetters and analysis consist of characters between 'a' and 'z'.
That means the difference between characters in these two can be from -25 ('a' - 'z') up to +25 ('z' - 'a').
Then you want to represent this difference using ascii characters, multiplicing by -1 the negative case. Nothing simpler:
void originalText(string analysis, string keyLetters) {
int lengthText = analysis.length();
char originText[2000];
int hold;
int k;
for (int i = 0; i < lengthText; i++) {
if (i % 5 == 0) {
k = 0;
}
hold = keyLetters[k] - analysis[i];
if (hold < 0) {
hold *= -1;
}
originText[i] = (char)hold + 'a';
cout << originText[i];
k++;
}
}
You need shift the value in range <0,25> to printable small ascii characters <'a','z'> by adding a 'a' ascii value, that is 97. The range <0,25> in ascii are just control characters.
This will result in:
The decrypted text:
oncegpmnahioethejewasalihtpegirpehmwantedhoplacallthedacandihedidnmtcareabmuhhejshudcahallinschomlherlarenhsgetangjcatherallhhetimebutihedidnmtcareabmuhhejparentifeelingiwhethejthecareangrymriadiheeaisgchabadgirplehuinohbeashejnefejeverhakecaremfevejchhingarogndcogsharhingfjoocogrlarenhstilpcogshudieiatichooltakealpthatieriogslcbestmfpucknmtheshorcdmesnohfiniihherethereismojetmihthatgirlonedaceenhtmschomlwhichiiuniveriitcactualpcbgtleolletendhosacabogtitschmolhhatihiimojecommonandidonnohknmwanyeacthatgirlofcogriewenhtognivejsitymrcollegeifihavetmsacwhenihegohopdejlikeehenshebecameeighheenceariopdsmahuniversitcthereeaiapotmfitudcforhejtodoehichihehohallcicrewgpsmshecjiedandcriedalohahnighhsfhejshecamhmmeandherkindpajentsasqedhejabmuhthereasmnforhejunitmppabpeteajsthaheairgnningouhfjomhejeyesconhinuogspchmwevejsherefgsedtmtellmrsacanyhhingiinceiheeantedtmshayalmnehhatnighthereishwasfglfilledsoathhahnighhshesleltaloneinthedarqeihhmutanconebesideihejtmeahchhejandtmtakecajeofherinhersleepingasshedidhoherlajenhsanditgdiesehenshewascoungersmthecccpehasgothejrogndshapnotfrmmnmwherebgtbecauseofareaionandthatjeaionisbecauiehhingieillcomebackholeolleafhejthecdidhheminanctimeeihhmutanceajningmralejt
As to why this doesn't give the correct text, I leave that to OP, because i don't get this method of encryption.
The whole program:
#include <iostream>
#include <string>
#include <fstream>
#include <cmath>
using namespace std;
string encryptText(string, string);
string cryptanalyzeText(string);
void originalText(string, string);
int main() {
string text, analysis;
string key;
text = "onceuponatimetherewasalittlegirlwhowantedtoplayallthedayandshedidnotcareaboutherstudyatallinschoolherparentsgetangryatherallthetimebutshedidnotcareaboutherparentsfeelingswhethertheyareangryorsadshewassuchabadgirlletusnotbeasherneverevertakecareofeverythingaroundyoustartingfromyourparentstillyoustudiesatschooltakeallthatseriouslybestoflucknothestorydoesnotfinishherethereismoretoitthatgirlonedaywenttoschoolwhichisuniversityactuallybutpeopletendtosayaboutitschoolthatitismorecommonandidonnotknowanywaythatgirlofcoursewenttouniversityorcollegeifihavetosaywhenshegotolderlikewhenshebecameeighteenyearsoldsoatuniversitytherewasalotofstudyforhertodowhichshetotallyscrewupsoshecriedandcriedalotatnightsftershecamhomeandherkindparentsaskedheraboutthereasonforherunstoppabletearsthatwasrunningoutfromhereyescontinuouslyhoweversherefusedtotellorsayanythingsinceshewantedtostayalonethatnightherwishwasfulfilledsoatthatnightshesleptaloneinthedarkwithoutanyonebesideshertowatchherandtotakecareofherinhersleepingasshedidtoherparentsandstudieswhenshewasyoungersothecyclehasgotherroundshapnotfromnowherebutbecauseofareasonandthatreasonisbecausethingswillcomebacktopeopleaftertheydidtheminanytimewithoutanywarningoralert";
analysis = "qegegrfrafkdittgiiwmurpifvcigutcahayrrtqfkspxcpelxvyidmarrdejvhippfxcmtvebawkledukydkckelxkewctqfphqtgerqpkwgqvrrgdarxhqtrplfjvxiygsytejvhippfxcmtvebawkledrrvezvjjeqnzrgeyyittgixhqarvempxvyatjedejvaaeulghmdrhgutcpefwjrofdvestgirehgiivqtkekqerveahvzedaklizirvogpucogukerfkekfdqdcogtgerqpkwtunccogukydugjeteeysoxvroemncxhmvjiruqlwlkdvwtahcycwpfxhquksrkffiszqkjizkjlhqtvxhqtvmsyqiitakkxhmvxmrxqeidmaninfvfwctqfpwtktliewemvqtjmtkctxumnccbgvgiobnvxezfkssmarfogvzxsojfslfjrxifkjqodgtsmyqeenpkusnzqkonayrryicpxhmvxmrxqwgogtjiwqpkxogpzzeduzxyattslxgxiirkyevqvfwakyyinejvkofqchednzoeijvrstgsicmoviisjkiezavereqchsackynuxvvsuvpxhqtvaaeccstahjxupawsrtgixopqnliojjlefqkelxajgrqyltsauyicdkvhazftviqfrpofckrisjkwffgiwhqerqhaovenpjvvkuputadgexsmubidtgiebawkxhqtvesapwsrtgiynevftpmdcitqciwttckaaetlrnupxsufhismtgiiyqutsnfkeyogucchayvzeduyirqhlwepvfxexnfvsmarryfjzrgekegeejvaazvvhtaukeymnfrefjrxnuiyxhqtnmstyrwfgnwmlxguwomvklafpzkhfuyisxggxaxqeiizvyidmtbaifjfytmppsnqdvwipgjledvfaafeyledcehtavroeociiorjvvizjvvsxgvtizirwstgumdfqyirbciinfurrdevlhiqunlezuyiwmupsuzivvsavyickecihmuxsttgivogpuwhmrestrtfqnayyirqdlxbqerysqqwerqcjsnmpuxhmviiaeqemsngteuegklizijaixntsmqdrgkfqgiobnveffgixhqaumdfjvqizcectuovaifjfytmppaadpzrgatrpedv";
cout<<"\n1- The original text:\n"<<text;
cout<<"\n\nEnter a key of type string: ";
key = "cream";
cout<<endl;
cout<<"The text after it has been encrypted:\n"<<encryptText(text, key)<<endl;
cout<<"\n2- An encrpted text:\n"<<analysis;
string keyLetters= cryptanalyzeText(analysis);
cout<<"\n\nThe key is: "<<keyLetters<<endl<<endl;
cout<<"The decrypted text:\n";
originalText(analysis, keyLetters);
cout<<endl<<endl;;
return 0;
}
string encryptText(string text, string key) {
int lengthText=text.length();
int lengthKey=key.length();
int count=0;
for (int i=0; i<lengthText; i++) {
text[i]=key[count];
if (count<lengthKey-1)
count++;
else
count=0;
}
return text;
}
string cryptanalyzeText(string analysis) {
string keyLetters="aaaaa";
char ch;
int i;
int lengthText=analysis.length();
for (int keyPlace=0; keyPlace<6 ; keyPlace++) {
int alphabet[26]={0};
for (i=keyPlace; i<lengthText; i=i+5) {
ch=analysis[i];
alphabet[ch - 'a']++;
}
int max=alphabet[0];
int maxPlace=0;
for (int j=1; j<26; j++) {
if(max<alphabet[j]) {
max=alphabet[j];
maxPlace=j;
}
}
keyLetters[keyPlace]=maxPlace-4;
if (keyLetters[keyPlace]<0)
keyLetters[keyPlace]+=26+97;
else
keyLetters[keyPlace]+=97;
}
return keyLetters;
}
void originalText(string analysis, string keyLetters) {
int lengthText=analysis.length();
char originText[2000];
int hold;
int k;
for (int i = 0; i < lengthText; i++) {
if (i % 5 == 0) {
k=0;
}
hold = keyLetters[k] - analysis[i];
if (hold < 0) {
hold *= -1;
}
originText[i] = (char)hold + 'a';
cout << originText[i];
k++;
}
}

It appeared that since the encrypted text has been generated by %26 (mod 26), the values of the letters that was larger than 26 lost its original values. So when they have been decrypted, they were generated as incorrect letters. That's why I had to return the 26 they have lost, before doing the subtraction procedure, as it will be subtracted correctly.
void originalText(string analysis, string keyLetters) {
int lengthText=analysis.length();
char originText[2000];
int hold;
int k;
for (int i = 0; i < lengthText; i++) {
if (i % 5 == 0) {
k=0;
}
hold = (analysis[i]+26)-keyLetters[k];
if (hold < 0) {
hold *= -1;
}
hold%=26;
originText[i] = (char)hold + 'a';
cout << originText[i];
k++;
}
}
The result of it:

Related

C++ check If a hexadecimal consists of ABCDEF1 OR 0

I have written a program below that converts a string to an int and then converts the decimal number to hexadecimal. I'm struggling to check if the hexadecimal consists only of these characters A, B, C, D, E, F, 1, 0. If so set a flag to true or false.
#include<iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
string solution(string &S){
int n = stoi(S);
int answer;
cout << "stoi(\"" << S << "\") is "
<< n << '\n';
//decToHexa(myint);
// char array to store hexadecimal number
string hexaDeciNum[100];
// counter for hexadecimal number array
int i = 0;
while(n!=0)
{
// temporary variable to store remainder
int temp = 0;
// storing remainder in temp variable.
temp = n % 16;
// check if temp < 10
if(temp < 10)
{
hexaDeciNum[i] = temp + 48;
i++;
}
else
{
hexaDeciNum[i] = temp + 55;
i++;
}
n = n/16;
}
// printing hexadecimal number array in reverse order
for(int j=i-1; j>=0; j--){
cout << hexaDeciNum[j] << "\n";
return "";
}
int main() {
string word = "300";
cout << solution(word);
return 0;
}
OK, it is not the exact answer to what you are asking for, but it is a valuable alternative approach for the entire problem of conversion:
char letter(unsigned int digit)
{
return "0123456789abcdefg"[digit];
// alternatively upper case letters, if you prefer...
}
Now you don't have to differenciate... You can even use this approach for inverse conversion:
int digit(char letter)
{
int d = -1; // invalid letter...
char const* letters = "0123456789abcdefABCDEF";
char* l = strchr(letters, letter);
if(l)
{
d = l - letters;
if(d >= 16)
d -= 6;
}
// alternatively upper case letters, if you prefer...
}
Another advantage: This works even on these strange character sets where digits and letters are not necessarily grouped into ranges (e. g. EBCDIC).

What's wrong with my dynamic programming algorithm with memoization?

*Sorry about my poor English. If there is anything that you don't understand, please tell me so that I can give you more information that 'make sence'.
**This is first time asking question in Stackoverflow. I've searched some rules for asking questions correctly here, but there should be something I missed. I welcome all feedback.
I'm currently solving algorithm problems to improve my skill, and I'm struggling with one question for three days. This question is from https://algospot.com/judge/problem/read/RESTORE , but since this page is in KOREAN, I tried to translate it in English.
Question
If there are 'k' pieces of partial strings given, calculate shortest string that includes all partial strings.
All strings consist only lowercase alphabets.
If there are more than 1 result strings that satisfy all conditions with same length, choose any string.
Input
In the first line of input, number of test case 'C'(C<=50) is given.
For each test case, number of partial string 'k'(1<=k<=15) is given in the first line, and in next k lines partial strings are given.
Length of partial string is between 1 to 40.
Output
For each testcase, print shortest string that includes all partial strings.
Sample Input
3
3
geo
oji
jing
2
world
hello
3
abrac
cadabra
dabr
Sample Output
geojing
helloworld
cadabrac
And here is my code. My code seems to work perfect with Sample Inputs, and when I made test inputs for my own and tested, everything worked fine. But when I submit this code, they say my code is 'wrong'.
Please tell me what is wrong with my code. You don't need to tell me whole fixed code, I just need sample inputs that causes error with my code. Added code description to make my code easier to understand.
Code Description
Saved all input partial strings in vector 'stringParts'.
Saved current shortest string result in global variable 'answer'.
Used 'cache' array for memoization - to skip repeated function call.
Algorithm I designed to solve this problem is divided into two function -
restore() & eraseOverlapped().
restore() function calculates shortest string that includes all partial strings in 'stringParts'.
Result of resotre() is saved in 'answer'.
For restore(), there are three parameters - 'curString', 'selected' and 'last'.
'curString' stands for currently selected and overlapped string result.
'selected' stands for currently selected elements of 'stringParts'. Used bitmask to make my algorithm concise.
'last' stands for last selected element of 'stringParts' for making 'curString'.
eraseOverlapped() function does preprocessing - it deletes elements of 'stringParts' that can be completly included to other elements before executing restore().
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
string answer; // save shortest result string
vector<string> stringParts;
bool cache[MAX + 1][(1 << MAX) + 1]; //[last selected string][set of selected strings in Bitmask]
void restore(string curString, int selected=0, int last=0) {
//base case 1
if (selected == (1 << k) - 1) {
if (answer.empty() || curString.length() < answer.length())
answer = curString;
return;
}
//base case 2 - memoization
bool& ret = cache[last][selected];
if (ret != false) return;
for (int next = 0; next < k; next++) {
string checkStr = stringParts[next];
if (selected & (1 << next)) continue;
if (curString.empty())
restore(checkStr, selected + (1 << next), next + 1);
else {
int check = false;
//count max overlapping area of two strings and overlap two strings.
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size()-i, i) == checkStr.substr(0, i)) {
restore(curString + checkStr.substr(i, checkStr.length()-i), selected + (1 << next), next + 1);
check = true;
break;
}
}
if (!check) { // if there aren't any overlapping area
restore(curString + checkStr, selected + (1 << next), next + 1);
}
}
}
ret = true;
}
//check if there are strings that can be completely included by other strings, and delete that string.
void eraseOverlapped() {
//arranging string vector in ascending order of string length
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
//deleting included strings
vector<string>::iterator iter;
for (int i = 0; i < vectorLen-1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C; // testcase
for (int testCase = 0; testCase < C; testCase++) {
cin >> k; // number of partial strings
memset(cache, false, sizeof(cache)); // initializing cache to false
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
eraseOverlapped();
k = stringParts.size();
restore("");
cout << answer << endl;
answer.clear();
stringParts.clear();
}
}
After determining which string-parts can be removed from the list since they are contained in other string-parts, one way to model this problem might be as the "taxicab ripoff problem" problem (or Max TSP), where each potential length reduction by overlap is given a positive weight. Considering that the input size in the question is very small, it seems likely that they expect a near brute-force solution, with possibly some heuristic and backtracking or other form of memoization.
Thanks Everyone who tried to help me solve this problem. I actually solved this problem with few changes on my previous algorithm. These are main changes.
In my previous algorithm I saved result of restore() in global variable 'answer' since restore() didn't return anything, but in new algorithm since restore() returns mid-process answer string I no longer need to use 'answer'.
Used string type cache instead of bool type cache. I found out using bool cache for memoization in this algorithm was useless.
Deleted 'curString' parameter from restore(). Since what we only need during recursive call is one previously selected partial string, 'last' can replace role of 'curString'.
CODE
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#define MAX 15
using namespace std;
int k;
vector<string> stringParts;
string cache[MAX + 1][(1 << MAX) + 1];
string restore(int selected = 0, int last = -1) {
if (selected == (1 << k) - 1) {
return stringParts[last];
}
if (last == -1) {
string ret = "";
for (int next = 0; next < k; next++) {
string resultStr = restore(selected + (1 << next), next);
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
string& ret = cache[last][selected];
if (!ret.empty()) {
cout << "cache used in [" << last << "][" << selected << "]" << endl;
return ret;
}
string curString = stringParts[last];
for (int next = 0; next < k; next++) {
if (selected & (1 << next)) continue;
string checkStr = restore(selected + (1 << next), next);
int check = false;
string resultStr;
for (int i = (checkStr.length() > curString.length() ? curString.length() : checkStr.length())
; i > 0; i--) {
if (curString.substr(curString.size() - i, i) == checkStr.substr(0, i)) {
resultStr = curString + checkStr.substr(i, checkStr.length() - i);
check = true;
break;
}
}
if (!check)
resultStr = curString + checkStr;
if (ret.empty() || ret.length() > resultStr.length())
ret = resultStr;
}
return ret;
}
void EraseOverlapped() {
int vectorLen = stringParts.size();
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].length() < stringParts[j].length()) {
string temp = stringParts[i];
stringParts[i] = stringParts[j];
stringParts[j] = temp;
}
}
}
vector<string>::iterator iter;
for (int i = 0; i < vectorLen - 1; i++) {
for (int j = i + 1; j < vectorLen; j++) {
if (stringParts[i].find(stringParts[j]) != string::npos) {
iter = stringParts.begin() + j;
stringParts.erase(iter);
j--;
vectorLen--;
}
}
}
}
int main(void) {
int C;
cin >> C;
for (int testCase = 0; testCase < C; testCase++) {
cin >> k;
for (int i = 0; i < MAX + 1; i++) {
for (int j = 0; j < (1 << MAX) + 1; j++)
cache[i][j] = "";
}
string inputStr;
for (int i = 0; i < k; i++) {
cin >> inputStr;
stringParts.push_back(inputStr);
}
EraseOverlapped();
k = stringParts.size();
string resultStr = restore();
cout << resultStr << endl;
stringParts.clear();
}
}
This algorithm is much slower than the 'ideal' algorithm that the book I'm studying suggests, but it was fast enough to pass this question's time limit.

Duplicates in X element array

I have an interval (m,n) and there I have to print out all the numbers which have different digits. I wrote this, but it only works for 2 digit numbers. I simply do not know how to make it work for anything but 2 digit numbers. I imagine that, if I added as much for loops as the digits of my number it would work, but the interval(m,n) isn't specified so it has to be something reliable. I've been trying to solve this problem on my own for 6 damn hours and I'm absolutely fed up.
Input 97,113;
Output 97,98,102,103,104,105,106,107,108,109
Numbers 99,100,101,110+ don't get printed, because they have 2 digits that are
the same.
#include<conio.h>
#include<math.h>
#include<stdio.h>
int main()
{
int m,n,test,checker=0;
scanf("%d%d",&m,&n);
if(m>n)
{
int holder=n;
n=m;
m=holder;
}
for(int start=m;start<=n;start++)
{
int itemCount=floor(log10(abs(start)))+1;
int nums[itemCount];
int index=0;
test=start;
do
{
int nextVal = test % 10;
nums[index++]=nextVal;
test = test / 10;
}while(test>0);
for (int i = 0; i < itemCount - 1; i++)
{ // read comment by #nbro
for (int j = i + 1; j < itemCount; j++)
{
if (nums[i] == nums[j])
{
checker++;
}
}
if(checker==0)printf("%d ",start);
}
checker=0;
}
}
Since you tagged this as C++, here is a very simple solution using simple modulus and division in a loop. No conversion to string is done.
#include <iostream>
#include <bitset>
bool is_unique_digits(int num)
{
std::bitset<10> numset = 0;
while (num > 0)
{
// get last digit
int val = num % 10;
// if bit is on, then this digit is unique
if (numset[val])
return false;
// turn bit on and remove last digit from number
numset.set(val);
num /= 10;
}
return true;
}
int main()
{
for (int i = 97; i <= 113; ++i)
{
if (is_unique_digits(i))
std::cout << i << "\n";
}
}
The is_unique_digit function simply takes the number and repeatedly extracts the digits from it by taking the last digit in the number. Then this digit is tested to see if the same digit appears in the bitset. If the number already exists, false is immediately returned.
If the number is not in the bitset, then the bit that corresponds to that digit is turned "on" and the number is divided by 10 (effectively removing the last digit from the number). If the loop completes, then true is returned.
Live Example
As an idea for a design:
print the number to a string, if it isn't a string already;
declare an array of int d[10]; and set it to all zeroes
for each ascii digit c of the string,
if (d[c-'0']==1) return 0; // this digit exists already in the number
else d[c-'0']= 1;
just put if(checker==0)printf("%d ",start); outside of second loop the loop
like this
for (int i = 0; i < itemCount - 1; i++)
{
for (int j = i + 1; j < itemCount; j++)
{
if (nums[i] == nums[j])
{
checker++;
break;
}
}
}
if(checker==0)
printf("%d ",start);
checker=0;
However instead of using two nested for loop you can use count array which is more efficient
to check 1 number, you can do
X=10; //number to analyze
char counts[10]; for int i=0;i<10;i++) counts[i]=0;
char number[10];
sprintf(&number,"%s",X); bool bad=false;
for(int i=0;i<strlen(number);i++)
{
if(++counts[number[i]-'0']>1) {bad=true;break;}
}`

Unicode rendering (Updated)

I posted my question couple days ago while i was still working on my code. I will restate my question so it would be clear for everyone.
Goal: print All of the Unicodes available using a loop.
Question: why I can only print them, as symbols, if they were hardcoded in a string rather then a variable.
Output:
U000000
U000001
U000002
...
U000017
U000018
#include <iostream>
#include <cmath>
using namespace std;
const int HexBase=16;
const int HexMax=15;
const int UniCharMaxPrint=1000;
const int ASCCIAlphaCapBase=48;
int main() {
int DecNum = 0;
int sizeHex= 3;
for (int j=0; j < UniCharMaxPrint; j++)//prints 100 unviersal Chars
{
int DecNumCopy = DecNum;
int resultDiv =0;
string HexChar=" ";
string HexNum ="X";
string UniNum ="u";
string BackSlash = "\\";
string full="HI ";
for (int i = sizeHex; i >=0; i--)
{
//Dec calcultion
resultDiv = (DecNumCopy/(int)(pow(HexBase,i)));
DecNumCopy = DecNumCopy - ((int)(pow(HexBase,i)) * resultDiv);
if ((i==0) && (resultDiv>HexMax)){cout <<"Error # is Too large"<<endl;}//Check if the number entered is big or not
//Get the equivalente Hex charcter
if ((resultDiv >= 0)&&(resultDiv <= 9))
{ HexChar = ASCCIAlphaCapBase + resultDiv;}
else if ((resultDiv >= 10)&&(resultDiv <= 15))
{ switch (resultDiv)
{ case 10 : {HexChar='a'; break;};
case 11 : {HexChar='b'; break;};
case 12 : {HexChar='c'; break;};
case 13 : {HexChar='d'; break;};
case 14 : {HexChar='e'; break;};
case 15 : {HexChar='f'; break;};
}
}
else {HexChar='*';};
//if(i==sizeHex){full.append(UniNum);};
//Add to the result string
//HexNum.append(HexChar);
UniNum.append(HexChar);
full = BackSlash+UniNum;
}//endfor
DecNum++;
cout<< full << endl;
}
return 0;
}

converting 128 bits from a character array to decimal without external libraries in C++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I had to convert a the 128 bits of a character array which has size 16 (1 byte each character), into a decimal and hexadecimal, without using any other libraries than included. Converting it to hexadecimal was easy as four bits were processed each time an the result was printed for each four bits as soon as it was generated.
But when it comes to decimal. Converting it in the normal mathematical way was not possible, in which each bit is multiplied by 2 to the power the index of the bit from left.
So I thought to convert it like I did with hexadecimal by printing digit by digit. But the problem is that in decimal it is not possible as the maximum digit is 9 and it needs 4 bits to represented while 4 bits can represent decimal numbers up to 15. I tried making some mechanism to carry the additional part, but couldn't find a way to do so. And I think, that was not going to work either. I have been trying aimlessly for three days as I have no idea what to do. And couldn't even find any helpful solution on the internet.
So, I want some way to get this done.
Here is My Complete Code:
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int strng = 128;
const int byts = 16;
class BariBitKari {
char bits_ar[byts];
public:
BariBitKari(char inp[strng]) {
set_bits_ar(inp);
}
void set_bits_ar(char in_ar[strng]) {
char b_ar[byts];
cout << "Binary 1: ";
for (int i=0, j=0; i<byts; i++) {
for (int k=7; k>=0; k--) {
if (in_ar[j] == '1') {
cout << '1';
b_ar[i] |= 1UL << k;
}
else if (in_ar[j] == '0') {
cout << '0';
b_ar[i] &= ~(1UL << k);
}
j++;
}
}
cout << endl;
strcpy(bits_ar, b_ar);
}
char * get_bits_ar() {
return bits_ar;
}
// Functions
void print_deci() {
char b_ar[byts];
strcpy(b_ar, get_bits_ar());
int sum = 0;
int carry = 0;
cout << "Decimal : ";
for (int i=byts-1; i >= 0; i--){
for (int j=4; j>=0; j-=4) {
char y = (b_ar[i] << j) >> 4;
// sum = 0;
for (int k=0; k <= 3; k++) {
if ((y >> k) & 1) {
sum += pow(2, k);
}
}
// sum += carry;
// if (sum > 9) {
// carry = 1;
// sum -= 10;
// }
// else {
// carry = 0;
// }
// cout << sum;
}
}
cout << endl;
}
void print_hexa() {
char b_ar[byts];
strcpy(b_ar, get_bits_ar());
char hexed;
int sum;
cout << "Hexadecimal : 0x";
for (int i=0; i < byts; i++){
for (int j=0; j<=4; j+=4) {
char y = (b_ar[i] << j) >> 4;
sum = 0;
for (int k=3; k >= 0; k--) {
if ((y >> k) & 1) {
sum += pow(2, k);
}
}
if (sum > 9) {
hexed = sum + 55;
}
else {
hexed = sum + 48;
}
cout << hexed;
}
}
cout << endl;
}
};
int main() {
char ar[strng];
for (int i=0; i<strng; i++) {
if ((i+1) % 8 == 0) {
ar[i] = '0';
}
else {
ar[i] = '1';
}
}
BariBitKari arr(ar);
arr.print_hexa();
arr.print_deci();
return 0;
}
To convert a 128-bit number into a "decimal" string, I'm going to make the assumption that the large decimal value just needs to be contained in a string and that we're only in the "positive" space. Without using a proper big number library, I'll demonstrate a way to convert any array of bytes into a decimal string. It's not the most efficient way because it continually parses, copies, and scans strings of digit characters.
We'll take advantage of the fact that any large number such as the following:
0x87654321 == 2,271,560,481
Can be converted into a series of bytes shifted in 8-bit chunks. Adding back these shifted chunks results in the original value
0x87 << 24 == 0x87000000 == 2,264,924,160
0x65 << 16 == 0x00650000 == 6,619,136
0x43 << 8 == 0x00004300 == 17,152
0x21 << 0 == 0x00000021 == 33
Sum == 0x87654321 == 2,271,560,481
So our strategy for converting a 128-bit number into a string will be to:
Convert the original 16 byte array into 16 strings - each string representing the decimal equivalent for each byte of the array
"Shift left" each string by the appropriate number of bits based on the index of the original byte in the array. Taking advantage of the fact that a left shift is equivalent of multiplying by 2.
Add all these shifted strings together
So to make this work, we introduce a function that can "Add" two strings (consisting only of digits) together:
// s1 and s2 are string consisting of digits chars only ('0'..'9')
// This function will compute the "sum" for s1 and s2 as a string
string SumStringValues(const string& s1, const string& s2)
{
string result;
string str1=s1, str2=s2;
// make str2 the bigger string
if (str1.size() > str2.size())
{
swap(str1, str2);
}
// pad zeros onto the the front of str1 so it's the same size as str2
while (str1.size() < str2.size())
{
str1 = string("0") + str1;
}
// now do the addition operation as loop on these strings
size_t len = str1.size();
bool carry = false;
while (len)
{
len--;
int d1 = str1[len] - '0';
int d2 = str2[len] - '0';
int sum = d1 + d2 + (carry ? 1 : 0);
carry = (sum > 9);
if (carry)
{
sum -= 10;
}
result.push_back('0' + sum);
}
if (carry)
{
result.push_back('1');
}
std::reverse(result.begin(), result.end());
return result;
}
Next, we need a function to do a "shift left" on a decimal string:
// s is a string of digits only (interpreted as decimal number)
// This function will "shift left" the string by N bits
// Basically "multiplying by 2" N times
string ShiftLeftString(const string& s, size_t N)
{
string result = s;
while (N > 0)
{
result = SumStringValues(result, result); // multiply by 2
N--;
}
return result;
}
Then to put it altogether to convert a byte array to a decimal string:
string MakeStringFromByteArray(unsigned char* data, size_t len)
{
string result = "0";
for (size_t i = 0; i < len; i++)
{
auto tmp = to_string((unsigned int)data[i]); // byte to decimal string
tmp = ShiftLeftString(tmp, (len - i - 1) * 8); // shift left
result = SumStringValues(result, tmp); // sum
}
return result;
}
Now let's test it out on the original 32-bit value we used above:
int main()
{
// 0x87654321
unsigned char data[4] = { 0x87,0x65,0x43,0x21 };
cout << MakeStringFromByteArray(data, 4) << endl;
return 0;
}
The resulting program will print out: 2271560481 - same as above.
Now let's try it out on a 16 byte value:
int main()
{
// 0x87654321aabbccddeeff432124681111
unsigned char data[16] = { 0x87,0x65,0x43,0x21,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x43,0x21,0x24,0x68,0x11,0x11 };
std::cout << MakeStringFromByteArray(data, sizeof(data)) << endl;
return 0;
}
The above prints: 179971563002487956319748178665913454865
And we'll use python to double-check our results:
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> int("0x87654321aabbccddeeff432124681111", 16)
179971563002487956319748178665913454865
>>>
Looks good to me.
I originally had an implementation that would do the chunking and summation in 32-bit chunks instead of 8-bit chunks. However, little-endian vs. big endian byte order issues get involved. I'll leave that potential optimization as an exercise to do another day.