Template<> not working or for ints [duplicate] - c++

This question already has answers here:
Why does division result in zero instead of a decimal?
(5 answers)
Closed 7 years ago.
Here is the code I am having trouble with it seems to work logically but perhaps I am missing a small detail as it doesn't work for chars or ints.
Whenever I run it I get weird output like all Fs or all As.
#include <iostream>
template<class T>
char gradeIt(T mark,T maxMark){
T grade =(mark/maxMark)*100;
if(grade > 79)
return 'A';
else if(grade<=79 && grade >= 69) {
return 'B';
}
else if(grade<=69 && grade>59)
return 'C';
else if(grade>50 && grade <=59)
return 'D';
else
return 'F';
}
template<>
char gradeIt<char>(char mark,char maxMark){
return mark;
}

T grade =(mark/maxMark)*100;
When the template parameter T is int this is performing integer division. For example, 80 / 100 = 0.
You could instead do.
T grade = mark * 100 / maxMark;

It looks like
(mark/maxMark)*100
is performing integer division, which will round to 0 every time.
You should static_cast<double>(mark)/maxMark to first convert to floating point so you don't lose any digits after the decimal place.

This isn't doing what you want for integers.
T grade =(mark/maxMark)*100;
In the case of integer division (int and char have the same behavior in this) maxMark is greater than mark then the result will just be 0.
For example
int x = 100;
int y = 5;
int z = y/x;
assert(z==0);

Related

hexa-decimal to decimal conversion (using implicit type casting)

I think there's some problem in my vs code I am new to this coding stuff even after writing the correct code it gives me wrong results in almost every second code I write i get uncertain results Plz guys help me with this , plz check running this code in your machine....
#include <iostream>
using namespace std;
int main()
{
char a[30];
cout << "enter the hexadecimal";
cin >> a;
int i = 0, c, digit, decimal = 0, p = 1;
while (a[i] != '\0') {
i++;
}
for (int j = i; j >= 0; j--) {
c = a[j];
if (c >= 48 && c <= 57) {
digit = c - 48;
}
else if (c >= 97 && c <= 112) {
digit = c - 87;
}
decimal += digit * p;
p *= 8;
}
cout << "\ndecimal is " << decimal;
return 0;
}
while entering hexa decimal plz only enter small alphabets i have not taken capital letters into consideration
for cheking hexadecimal to decimal use this site https://www.rapidtables.com/convert/number/hex-to-decimal.html?x=146
There are several problems with the code, but I think that the main one is that you are multiplying p by 8 when it should be 16 (as hex is base-16, not base-8).
You also should take care with invalid inputs. What happens if someone enters an invalid letter 'j' for instance?
Besides, when you calculate the initial length of the string, you are setting ito the position of the array with a '\0' value so when you start processing the input, a[i] is 0 and that leads to using an uninitialized variable (digit has not been assigned a value, this is related to the previous "invalid input" issue).
By the way, I would also use chars in the comparisions instead of ASCII codes, it's easier to see what you are looking for:
if (c >= '0' && c <= '9') {
digit = c - '0';
}
and so on...

Hexadecimal to decimal conversion problem.Also, how to convert a char number to an actual int number

Please help me to identify the error in this program, as for me it's looking correct,I have checked it,but it is giving wrong answers.
In this program I have checked explicitly for A,B,C,D,E,F,and according to them their respective values.
[Edited]:Also,this question relates to how a character number is converted to actual integer number.
#include<iostream>
#include<cmath>
#include<bits/stdc++.h>
using namespace std;
void convert(string num)
{
long int last_digit;
int s=num.length();
int i;
long long int result=0;
reverse(num.begin(),num.end());
for(i=0;i<s;i++)
{
if(num[i]=='a' || num[i]=='A')
{
last_digit=10;
result+=last_digit*pow(16,i);
}
else if(num[i]=='b'|| num[i]=='B')
{
last_digit=11;
result+=last_digit*pow(16,i);
}
else if(num[i]=='c' || num[i]=='C')
{
last_digit=12;
result+=last_digit*pow(16,i);
}
else if(num[i]=='d'|| num[i]=='D' )
{
last_digit=13;
result+=last_digit*pow(16,i);
}
else if(num[i]=='e'|| num[i]=='E' )
{
last_digit=14;
result+=last_digit*pow(16,i);
}
else if(num[i]=='f' || num[i]=='F')
{
last_digit=15;
result+=last_digit*pow(16,i);
}
else {
last_digit=num[i];
result+=last_digit*pow(16,i);
}
}
cout<<result;
}
int main()
{
string hexa;
cout<<"Enter the hexadecimal number:";
getline(cin,hexa);
convert(hexa);
}
Your code is very convoluted and wrong.
You probably want this:
void int convert(string num)
{
long int last_digit;
int s = num.length();
int i;
long long int result = 0;
for (i = 0; i < s; i++)
{
result <<= 4; // multiply by 16, using pow is overkill
auto digit = toupper(num[i]); // convert to upper case
if (digit >= 'A' && digit <= 'F')
last_digit = digit - 'A' + 10; // digit is in range 'A'..'F'
else
last_digit = digit - '0'; // digit is (hopefully) in range '0'..'9'
result += last_digit;
}
cout << result;
}
But this is still not very good:
the function should return a long long int instead of printing the result
a few other thing can be done mor elegantly
So a better version would be this:
#include <iostream>
#include <string>
using namespace std;
long long int convert(const string & num) // always pass objects as const & if possible
{
long long int result = 0;
for (const auto & ch : num) // use range based for loops whenever possible
{
result <<= 4;
auto digit = toupper(ch);
long int last_digit; // declare local variables in the inner most scope
if (digit >= 'A' && digit <= 'F')
last_digit = digit - 'A' + 10;
else
last_digit = digit - '0';
result += last_digit;
}
return result;
}
int main()
{
string hexa;
cout << "Enter the hexadecimal number:";
getline(cin, hexa);
cout << convert(hexa);
}
There is still room for more improvements as the code above assumes that the string to convert contains only hexadecimal characters. Ideally a check for invalid characters should be done somehow. I leave this as an exercise.
The line last_digit = digit - 'A' + 10; assumes that the codes for letters A to F are contiguous, which in theory might not be the case. But the probability that you'll ever encounter an encoding scheme where this is not the case is close to zero though. The vast majority of computer systems in use today use the ASCII encoding scheme, some use EBCDIC, but in both of these encoding schemes the character codes for letters A to F are contiguous. I'm not aware of any other encoding scheme in use today.
Your problem is in the elsecase in which you convert num[i] from char to its ascii equivalent. Thus, for instance, if you try to convert A0, the 0is converted into 48 but not 0.
To correct, you should instead convert your num[i] into its equivalent integer (not in asci).
To do so, replace :
else {
last_digit=num[i];
result+=last_digit*pow(16,i);
with
else {
last_digit = num[i]-'0';
result+=last_digit*pow(16,i);
}
In the new line, last_digit = num[i]-'0'; is equivalent to last_digit = (int)num[i]-(int)'0';which substracts the representation code of any one-digit-number from num[i] from the representation code of '0'
It works because the C++ standard guarantee that the number representation of the 10 decimal digits are contiguous and in incresing order (official ref iso-cpp and is stated in chapter 2.3 and paragraph 3
Thus, if you take the representation (for instance the ascii code) of any one-digit-number num[i] and substract it with the representation code of '0' (which is 48 in ascii), you obtain directly the number itself as an integer value.
An example of execution after the correction would give:
A0
160
F5
245
A small codereview:
You are repeating yourself with many result+=last_digit*pow(16,i);. you may do it only once at the end of the loop. But that's another matter.
You are complicating the problem more than you need to (std::pow is also kinda slow). std::stoul can take a numerical base and automatically convert to an integer for you:
#include <string>
#include <iostream>
std::size_t char_count{0u};
std::string hexa{};
std::getline(std::cin, hexa);
hexa = "0x" + hexa;
unsigned long value_uint = std::stoul(hexa, &char_count, 16);

How to convert from Hexadecimal to Decimal in C++ Recursively?

*NOTE: there is a similar question on here but it did not help me because my friend straight up copy pasted it on to her code and I don't want to do that (plus it made in zero way any sense to me personally so why would I so much as refer to it in the first place if I don't follow the method used for it). I need some help with the LOGIC essentially, not even exactly the code written out line by line.
I have a function for my char to decimal already:
void CharToDec(char hexVal)
{
if(hexVal >= '0' && hexVal <= '9')
hexVal = hexVal - '0';
else
{
hexVal = hexVal - 'A' + 10;
}
}
Not sure if those lines are right but it's what I got from my professor. I need to get a decimal conversion from hexadecimal using recursion. No exception. Can anyone please give me a pseudo-code to follow or a logic stream for dummies? I'm not smart nor do I understand recursion at all. Professor skimmed and sincerely didn't sound interested at all in helping us deal with this. Plus we don't have a textbook. And since the whole school is closed due to the pandemic, I am having an extra hard time to reach out to him.
My base switch code has to be a different function that's recursive. I'm using this block of code just to convert the characters into decimals in the hex chain.
Example output:
Enter hex value: 7F
Decimal value: 127
Like so.
Thank you.
Please see the below code.
Only a minimal version is added . You can customize this code based on your requirement
#include <iostream>
#include <string.h>
using namespace std;
void CharToDec(char hexVal[]) {
int len = strlen(hexVal);
// Initializing base value to 1, i.e 16^0
int base = 1;
int dec_val = 0;
// Extracting characters as digits from last character
for (int i = len - 1; i >= 0; i--) {
// if character lies in '0'-'9', converting
// it to integral 0-9 by subtracting 48 from
// ASCII value.
if (hexVal[i] >= '0' && hexVal[i] <= '9') {
dec_val += (hexVal[i] - 48) * base;
// incrementing base by power
base = base * 16;
}
// if character lies in 'A'-'F' , converting
// it to integral 10 - 15 by subtracting 55
// from ASCII value
else if (hexVal[i] >= 'A' && hexVal[i] <= 'F') {
dec_val += (hexVal[i] - 55) * base;
// incrementing base by power
base = base * 16;
}
}
cout << "Decimal value=" << dec_val << endl;
}
int main() {
CharToDec("7F");
return 0;
}
The output will be
Decimal value=127

Issue with base converter function [duplicate]

This question already has answers here:
Strange behaviour of the pow function
(5 answers)
Closed 6 years ago.
I'm helping a friend with a C++ assignment. There is an issue with the folowing base converter function:
#include <iostream>
#include <cmath>
using namespace std;
int strToInt(string num, unsigned base){
int result = 0;
for (int i=0; i<num.length(); i++) {
if (num[i]>='0' && num[i]<='9')
result += (num[i]-'0')*pow(base,num.length()-i-1);
else if (num[i]>='A' && num[i]<='F')
result += (num[i]-'A'+10)*pow(base,num.length()-i-1);
else if (num[i]>='a' && num[i]<='f')
result += (num[i]-'a'+10)*pow(base,num.length()-i-1);
}
return result;
}
int main()
{
string number;
int base;
while(number.compare("exit")!=0){
cin>>number;
cin>>base;
cout<<strToInt(number,base)<<"\n\n";
}
return 0;
}
For some inexplicable reason every time I enter 3 and 5 digit decimals and chose base 10 I am getting the proper number -1.
E.g.
100
10
99
10000
10
9999
I've been going over this function for the last 5-6 hours and adding all types of debug code, but for the good of me I can't figure out what the hell is wrong.
Code style remarks are also very appreciated.
Cheers
std::pow does floating-point math. You're probably getting a round-off error somewhere. The usual way to accumulate values is to multiply and add each time through the loop:
result *= base;
result += ch - '0';

C++:How to convert string into integer without using any built in functions [duplicate]

This question already has answers here:
How compiler is converting integer to string and vice versa
(3 answers)
Closed 7 years ago.
I am trying to convert a string to a integer and carry out some arithmetic after that.
char string[10];
If the string has only one word I can do this:
string[0]-'0'
How can I convert it into an integer if the string has more than one character.
Better to use a built-in function, but if you want to do it by hand, you need to loop through all of the characters in the string that are actually digits. Since this is in base-10, you simply multiply an accumulator by 10 every time through the loop:
int strToInt (const char *str) {
int accumulator = 0;
int sign = 1;
if (*str == '-') {
str++;
sign = -1;
}
while (*str >= '0' && *str <= '9') {
accumulator *= 10;
accumulator += *str - '0';
str++;
}
return accumulator * sign;
}
int i,ans;
char num[] = "5678";
int l = strlen(num);
ans = 0;
for(i=0;i<l;i++)
ans = ans*10 + (num[i]-'0');
printf("%d\n",ans);