Related
I'm practicing a coding problem on "Check if the frequency of all the digits in a number is same"
#include<bits/stdc++.h>
using namespace std;
// returns true if the number
// passed as the argument
// is a balanced number.
bool isNumBalanced(int N)
{
string st = to_string(N);
bool isBalanced = true;
// frequency array to store
// the frequencies of all
// the digits of the number
int freq[10] = {0};
int i = 0;
int n = st.size();
for (i = 0; i < n; i++)
// store the frequency of
// the current digit
freq[st[i] - '0']++;
for (i = 0; i < 9; i++)
{
// if freq[i] is not
// equal to freq[i + 1] at
// any index 'i' then set
// isBalanced to false
if (freq[i] != freq[i + 1])
isBalanced = false;
}
// return true if
// the string is balanced
if (isBalanced)
return true;
else
return false;
}
// Driver code
int main()
{
int N = 1234567890;
bool flag = isNumBalanced(N);
if (flag)
cout << "YES";
else
cout << "NO";
}
but I can't understand this code:
// store the frequency of
// the current digit
freq[st[i] - '0']++;
How this part actually working and storing frequency?
And instead of this line, what else I can write?
st is a string and thus, a sequence of chars. st[i] is the ith char in this string.
Chars are actually positive integers between 0 and 256, so you can use them with mathematical operations, such as -. These integers are assigned to characters according to the ASCII alphabet. For example: The char 0 is assigned to 48 and the char 7 to 55 (Note: in the following, I use x to denote the character).
Their order makes it possible that mathematical operations are sensible as follows: The char 7 and the char 0 are exactly 7 numbers apart, so 0 + 7 = 48 + 7 = 55 = 7. So: 7 - 0 = 7.
So, you get the position in the freq array according to the number, i.e., the position 0 for 0 or position 7 for 7. The ++ operator increments that value in-place.
This line is several things condensed into one expression
freq[st[i] - '0']++;
The individual part are rather simple and in total it also isn't too difficult:
st[i] - '0' - character digits do not map 1 to 1 to integers. There is an offset. The integer value of '1' is 1 + '0', '2' is 2 + '0'. Hence to get the integer from the digit you need to subtract '0'.
freq[ ... ] - accesses the element of the array. Element at index i stores frequency of digit i.
()++ - increments that frequency by one.
Subtracting the '0' character from the single string character results in the actual number you're looking for. This gives you the number whose frequency you are tracking in your code. This works because of the way characters are stored as ASCII values. Check out the table below. Say that the integer value N that is passed in is 1221. The first value observed in this example is '1' which corresponds to an ASCII value of 49. The ASCII value of '0' is 48. Subtracting the two: 49 - 48 = 1. This allows you to access each integer value individually as part of the array that was the result of the transformation of an 'int' value into a string.
ASCII Table
The code of
for (i = 0; i < n; i++)
// store the frequency of
// the current digit
freq[st[i] - '0']++;
traverses the string and for each item, it subtracts '0', which has a value of 48, because character code 48 represents 0, character code 49 represents 1 and so on.
This code however is superfluos, wastes memory in storing a string and wastes time converting a number to a string. This is better:
bool isNumBalanced(int N)
{
//We create an array of 10 for each digit
int digits[10];
//Initialize the difits
for (int i = 0; i < 10; i++) digits[i] = 0;
//If the input is 0, then we have a trivial case
if (N == 0) return true;
//We loop the digits
do {
//N % 10 is the last digit
//We increment the frequency of that digit
digits[N % 10]++;
} while ((N /= 10) != 0); //We don't stop until we reach the trivial case, see above
//Using the transitivity of equality, we compare all values to the first
//We return false upon the first difference
for (int j = 1; j < 10; j++)
if (digits[0] != digits[j]) return false;
//Otherwise we return true
return true;
}
For those who don't understand it.
int arr[5]={0} // it stores 0 in all places
for(int i=0;i<5;i++){
arr[i]++;
} // Now the array is [1 1 1 1 1]
what happened here is first i=0 then arr[0]++ "here arr[0] value was 0, ++, it increment 0 to 1"
now arr[0] value is 1.
Now `
let
st="1221";
for (i = 0; i < 4; i++) {
freq[st[i] - '0']++;
for i=0, the freq location is : freq[49-48]++ = freq[1]++ means value of freq[1] is 1
for i=1, the freq location is : freq[50-48]++ = freq[2]++ means value of freq[2] is 1
for i=2, the freq location is : freq[50-48]++ = freq[2]++ means value of freq[2] is 2
for i=3, the freq location is : freq[49-48]++ = freq[1]++ means value of freq[1] is 2
ASCII value of '0' is 48
ASCII value of '1' is 49
ASCII value of '2'is 50
My assignment:
The teacher has written down the sum of multiple numbers. Pupils should calculate the sum. To make the calculation easier, the sum only contains numbers 1, 2 and 3. Still, that isn't enough for Xenia. She is only beginning to count, so she can calculate a sum only if the summands follow in non-decreasing order. For example, she can't calculate sum 1+3+2+1 but she can calculate sums 1+1+2 and 3+3.
You've got the sum that was written on the board. Rearrange the summons and print the sum in such a way that Xenia can calculate the sum.
Input
The first line contains a non-empty string s — the sum Xenia needs to count. String s contains no spaces. It only contains digits and characters "+". Besides, string s is a correct sum of numbers 1, 2, and 3. String s is at most 100 characters long.
Output
Print the new sum that Xenia can count.
Examples:
Input
3+2+1
Output
1+2+3
Here is my solution:
#include<string>
#include <iostream>
using namespace std;
int main()
{
string su ;
cin >> su;
int n, temp ;
n = su.size();
for (int i = 0 ; i < n ; i+=2)
{
if (su[i]=='1')
{
su[i]-='0';
}
else if (su[i]=='2')
{
su[i]-='0';
}
else if ( su[i]== '3')
{
su[i]-='0';
}
}
for (int i =0 ; i <n ; i+=2)
{
for(int j = 0 ; j< n; j+=2 )
{
if (su[i]< su [j])
{
temp = su[i];
su[i]=su[j];
su[j]=temp;
}
}
}
for(int i = 0 ; i < n ; i++)
{
if(su[i]=='+')
{
cout<<su[i];
}
else
cout<<su[i];//this is the line I can't understand why the result like that;
}
}
the problem is when I run the code with input 3+2+1 i expect the output is 1+2+3+ but I get ?+?+? something like that and I can't understand the reason.
First doing the s[i] -= '0' is very dangerous as it is a string, you should do int myNum = s[i] - '0' instead and then try storing it inside of the string, because when you do s[i] -= '0' it is never casted into an integer, but it stays char all the time so if you do not cast it to integer, it will go ascii code of '1' - '0' okay that is 1, which symbol has an ascii code of one? Oh it's the SOH character... And it takes the SOH character and put it inside of your string, but you string does not know what SOH is so it goes ???..(just joking, strings do not have emotions). All jokes aside the strange behavior is probably caused by you trying to store an illegal character inside a string. I would convert the '1' - '0' to int first.... Then store it in a string.
Write a C++ program to perform addition of two hexadecimal numerals which are less than 100 digits long. Use arrays to store hexadecimal numerals as arrays of characters.the solution is to add the corresponding digits in the format of hexadecimal directly. From right to left, add one to the digit on the left if the sum of the current digits exceed 16. You should be able to handle the case when two numbers have different digits.
The correct way to get the input is to store as character array. You can either first store in a string and convert to character array, or you can use methods such as cin.getline(), getc(), cin.get() to read in the characters.
I don't know what is wrong with my program and it I don't know how to use the function getline() and eof()
char a[number1],b[number1],c[number2],h;
int m,n,p(0),q(0),k,d[number1],z[number1],s[number2],L,M;
cout<<"Input two hexadecimal numerals(both of them within 100 digits):\n";
cin.getline(a,100);
cin.getline(b,100);
int x=strlen(a) ;
int y=strlen(b);
for(int i=0;i<(x/2);i++)
{
m=x-1-i;
h=a[i];
a[i]=a[m];
a[m]=h;
}
for(int j=0;j<(y/2);j++)
{
n=y-1-j;
h=b[j];
b[j]=b[n];
b[n]=h;
}
if(x>y)
{
for(int o=0;o<x;o++)//calculate a add b
{
if(o>=(y-1))
z[o]=0;//let array b(with no character)=0
if(a[o]=='A')
d[o]=10;
else if(a[o]=='B')
d[o]=11;
else if(a[o]=='C')
d[o]=12;
else if(a[o]=='D')
d[o]=13;
else if(a[o]=='E')
d[o]=14;
else if(a[o]=='F')
d[o]=15;
else if(a[o]=='0')
d[o]=0;
else if(a[o]=='1')
d[o]=1;
else if(a[o]=='2')
d[o]=2;
else if(a[o]=='3')
d[o]=3;
else if(a[o]=='4')
d[o]=4;
else if(a[o]=='5')
d[o]=5;
else if(a[o]=='6')
d[o]=6;
else if(a[o]=='7')
d[o]=7;
else if(a[o]=='8')
d[o]=8;
else if(a[o]=='9')
d[o]=9;
if(b[o]=='A')
z[o]=10;
else if(b[o]=='B')
z[o]=11;
else if(b[o]=='C')
z[o]=12;
else if(b[o]=='D')
z[o]=13;
else if(b[o]=='E')
z[o]=14;
else if(b[o]=='F')
z[o]=15;
else if(b[o]=='0')
z[o]=0;
else if(b[o]=='1')
z[o]=1;
else if(b[o]=='2')
z[o]=2;
else if(b[o]=='3')
z[o]=3;
else if(b[o]=='4')
z[o]=4;
else if(b[o]=='5')
z[o]=5;
else if(b[o]=='6')
z[o]=6;
else if(b[o]=='7')
z[o]=7;
else if(b[o]=='8')
z[o]=8;
else if(b[o]=='9')
z[o]=9;
p=d[o]+z[o]+q;
if(p>=16)//p is the remained number
{
q=1;
p=p%16;
}
else
q=0;
if(p==0)
c[o]='0';
else if(p==1)
c[o]='1';
else if(p==2)
c[o]='2';
else if(p==3)
c[o]='3';
else if(p==4)
c[o]='4';
else if(p==5)
c[o]='5';
else if(p==6)
c[o]='6';
else if(p==7)
c[o]='7';
else if(p==8)
c[o]='8';
else if(p==9)
c[o]='9';
else if(p==10)
c[o]='A';
else if(p==11)
c[o]='B';
else if(p==12)
c[o]='C';
else if(p==13)
c[o]='D';
else if(p==14)
c[o]='E';
else if(p==15)
c[o]='F';
}
k=x+1;
if(q==1)//calculate c[k]
{
c[k]='1';
for(int f=0;f<=(k/2);f++)
{
m=k-f;
h=c[f];
c[f]=c[m];
c[m]=h;
}
}
else
{
for(int e=0;e<=(x/2);e++)
{
m=x-e;
h=c[e];
c[e]=c[m];
c[m]=h;
}
}
}
if(x=y)
{
for(int o=0;o<x;o++)//calculate a add b
{
if(a[o]=='A')
d[o]=10;
else if(a[o]=='B')
d[o]=11;
else if(a[o]=='C')
d[o]=12;
else if(a[o]=='D')
d[o]=13;
else if(a[o]=='E')
d[o]=14;
else if(a[o]=='F')
d[o]=15;
else if(a[o]=='0')
d[o]=0;
else if(a[o]=='1')
d[o]=1;
else if(a[o]=='2')
d[o]=2;
else if(a[o]=='3')
d[o]=3;
else if(a[o]=='4')
d[o]=4;
else if(a[o]=='5')
d[o]=5;
else if(a[o]=='6')
d[o]=6;
else if(a[o]=='7')
d[o]=7;
else if(a[o]=='8')
d[o]=8;
else if(a[o]=='9')
d[o]=9;
if(b[o]=='A')
z[o]=10;
else if(b[o]=='B')
z[o]=11;
else if(b[o]=='C')
z[o]=12;
else if(b[o]=='D')
z[o]=13;
else if(b[o]=='E')
z[o]=14;
else if(b[o]=='F')
z[o]=15;
else if(b[o]=='0')
z[o]=0;
else if(b[o]=='1')
z[o]=1;
else if(b[o]=='2')
z[o]=2;
else if(b[o]=='3')
z[o]=3;
else if(b[o]=='4')
z[o]=4;
else if(b[o]=='5')
z[o]=5;
else if(b[o]=='6')
z[o]=6;
else if(b[o]=='7')
z[o]=7;
else if(b[o]=='8')
z[o]=8;
else if(b[o]=='9')
z[o]=9;
p=d[o]+z[o]+q;
M=p;
if(p>=16)
{
q=1;
p=p%16;
}
else
q=0;
s[o]=p;
if(p==0)
c[o]='0';
else if(p==1)
c[o]='1';
else if(p==2)
c[o]='2';
else if(p==3)
c[o]='3';
else if(p==4)
c[o]='4';
else if(p==5)
c[o]='5';
else if(p==6)
c[o]='6';
else if(p==7)
c[o]='7';
else if(p==8)
c[o]='8';
else if(p==9)
c[o]='9';
else if(p==10)
c[o]='A';
else if(p==11)
c[o]='B';
else if(p==12)
c[o]='C';
else if(p==13)
c[o]='D';
else if(p==14)
c[o]='E';
else if(p==15)
c[o]='F';
}
k=x+1;
if(q==1)
{
c[k]='1';
for(int f=0;f<=(k/2);f++)
{
m=k-f;
h=c[f];
c[f]=c[m];
c[m]=h;
}
}
else
{
for(int e=0;e<=(x/2);e++)
{
m=x-e;
h=c[e];
c[e]=c[m];
c[m]=h;
}
}
}
Lets look at what cin.getline does:
Extracts characters from stream until end of line. After constructing
and checking the sentry object, extracts characters from *this and
stores them in successive locations of the array whose first element
is pointed to by s, until any of the following occurs (tested in the
order shown):
end of file condition occurs in the input sequence (in which case setstate(eofbit) is executed)
the next available character c is the delimiter, as determined by Traits::eq(c, delim). The delimiter is extracted (unlike basic_istream::get()) and counted towards gcount(), but is not stored.
count-1 characters have been extracted (in which case setstate(failbit) is executed).
If the function extracts no characters (e.g. if count < 1), setstate(failbit)
is executed. In any case, if count>0, it then stores a null character
CharT() into the next successive location of the array and updates
gcount().
The result of that is in all cases, s now points to a null terminated string, of at most count-1 characters.
In your usage, you have up to 99 digits, and can use strlen to count exactly how many. eof is not a character, nor it is a member function of char.
You then reverse in place the inputs, and go about your overly repetitious conversions.
However, it's much simpler to use functions, both those you write yourself and those provided by the standard.
// translate from '0' - '9', 'A' - 'F', 'a' - 'f' to 0 - 15
static std::map<char, int> hexToDec { { '0', 0 }, { '1', 1 }, ... { 'f', 15 }, { 'F', 15 } };
// translate from 0 - 15 to '0' - '9', 'A' - 'F'
static std::map<int, char> decToHex { { 0, '0' }, { 1, '1' }, ... { 15, 'F' } };
std::pair<char, bool> hex_add(char left, char right, bool carry)
{
// translate each hex "digit" and add them
int sum = hexToDec[left] + hexToDec[right];
// we have a carry from the previous sum
if (carry) { ++sum; }
// translate back to hex, and check if carry
return std::make_pair(decToHex[sum % 16], sum >= 16);
}
int main()
{
std::cout << "Input two hexadecimal numerals(both of them within 100 digits):\n";
// read two strings
std::string first, second;
std::cin >> first >> second;
// reserve enough for final carry
std::string reverse_result(std::max(first.size(), second.size()) + 1, '\0');
// traverse the strings in reverse
std::string::const_reverse_iterator fit = first.rbegin();
std::string::const_reverse_iterator sit = second.rbegin();
std::string::iterator rit = reverse_result.begin();
bool carry = false;
// while there are letters in both inputs, add (with carry) from both
for (; (fit != first.rend()) && (sit != second.rend()); ++fit, ++sit, ++rit)
{
std::tie(*rit, carry) = hex_add(*fit, *sit, carry);
}
// now add the remaining digits of first (will do nothing if second is longer)
for (; (fit != first.rend()); ++fit)
{
// we need to account for a carry in the last place
// potentially all the way up if we are adding e.g. "FFFF" to "1"
std::tie(*rit, carry) = hex_add(*fit, *rit++, carry);
}
// or add the remaining digits of second
for (; (sit != second.rend()); ++sit)
{
// we need to account for a carry in the last place
// potentially all the way up if we are adding e.g. "FFFF" to "1"
std::tie(*rit, carry) = hex_add(*sit, *rit++, carry);
}
// result has been assembled in reverse, so output it reversed
std::cout << reverse_result.reverse();
}
Regarding the text of your problem: “add one to the digit on the left if the sum of the current digits exceed 16” is wrong; it should be 15, not 16.
Regarding your code: I did not have the patience to read all your code, however:
I have noticed one long if/else. Use a switch (but you do not need one).
To find out if a character is a hex digit use isxdigit (#include <cctype>).
The user might input uppercase and lowercase characters: convert them to the same case using toupper/tolower.
To convert a hex digit to an integer:
if the digit is between ‘0’ and ‘9’ simply subtract ‘0’. This works because the codes for ‘0’, ‘1’… are 0x30, 0x31... (google ASCII codes).
if the digit is between ‘A’ and ‘F’, subtract ‘A’ and add 10.
Solving the problem:
“less than 100 digits long” This is a clear indication regarding how your data must be stored: a simple 100 long array, no std::string, no std::vector:
#define MAX_DIGITS 100
typedef int long_hex_t[MAX_DIGITS];
In other words your numbers are 100 digits wide, at most.
Decide how you store the number: least significant digit first or last? I would chose to store the least significant first. 123 is stored as {3,2,1,0,…0}
Use functions to simplify your code. You will need three functions: read, print and add:
int main()
{
long_hex_t a;
read( a );
long_hex_t b;
read( b );
long_hex_t c;
add( c, a, b );
print( c );
return 0;
}
The easiest function to write is add followed by print and read.
For read use get and putback to analyze the input stream: get extracts the next character from stream and putback is inserting it back in stream (if we do not know how to handle it).
Here it is a full solution (try it):
#include <iostream>
#include <cctype>
#define MAX_DIGITS 100
typedef int long_hex_t[MAX_DIGITS];
void add( long_hex_t c, long_hex_t a, long_hex_t b )
{
int carry = 0;
for ( int i = 0; i < MAX_DIGITS; ++i )
{
int t = a[i] + b[i] + carry;
c[i] = t % 16;
carry = t / 16;
}
}
void print( long_hex_t h )
{
//
int i;
// skip leading zeros
for ( i = MAX_DIGITS - 1; i >= 0 && h[i] == 0; --i )
;
// all zero
if ( i < 0 )
{
std::cout << '0';
return;
}
// print remaining digits
for ( i; i >= 0; --i )
std::cout << char( h[i] < 10 ? h[i] + '0' : h[i] - 10 + 'A' );
}
void read( long_hex_t h )
{
// skip ws
std::ws( std::cin );
// skip zeros
{
char c;
while ( std::cin.get( c ) && c == '0' )
;
std::cin.putback( c );
}
//
int count;
{
int i;
for ( i = 0; i < MAX_DIGITS; ++i )
{
char c;
if ( !std::cin.get( c ) )
break;
if ( !std::isxdigit( c ) )
{
std::cin.putback( c );
break;
}
c = std::toupper( c );
h[i] = c <= '9'
? ( c - '0' )
: ( c - 'A' + 10 );
}
count = i;
}
// reverse
for ( int i = 0, ri = count - 1; i < count / 2; ++i, --ri )
{
int t = h[i];
h[i] = h[ri];
h[ri] = t;
}
// fill the rest with zero
for ( int i = count; i < MAX_DIGITS; ++i )
h[i] = 0;
}
int main()
{
long_hex_t a;
read( a );
long_hex_t b;
read( b );
long_hex_t c;
add( c, a, b );
print( c );
return 0;
}
This is a long answer. Because you have much bug in your code. Your using of getline is ok. But your are calling a eof() like e.eof() which is wrong. If you have looked at your compilation error, you would see that it was complaining about calling eof() on the variable e because it is of non-class type. Simple meaning it is not an object of some class. You cannot put the dot operator . on primitive types like that. I think what you are wanting to do, is to terminate the loop when you have reached the end of line. So that index1 and index2 can get the length of the string input. If I were you, I would just use C++ builtin strlen() function for that. And in the first place, you should use C++ class string to handle strings. Also strings have a null - terminating character '\0' at the end of them. If you don't know about it, I suggest you take some time to read about strings.
Secondly, you have many bugs and errors in your code. The way you are reversing your string is not correct. Ask yourself, what are the contents of the arrays a and b at position which have higher index than the length of the string? You should use reverse() for reversing strings and arrays.
You have errors on adding loop also. Note, you are changing the arrays value when they are A, B, C, D, and so on for hexadecimal values with the corresponding decimal values 10,11,12,13 and so on. But you should change the values for the character '0' - '9' also. Because when the array holds '0' it is not integer 0. But is is ASCII '0' which has integer value of 48. And the character '1' has integer value of 49 and so on. You want to replace this values with corresponding integer values also. When you are also storing the result values in c, you are only handling only those values which are above 9 and replacing them with corresponding characters. You should also replace the integers 0 - 9 with there corresponding ASCII characters. Also don't forget to put a null terminating character at the end of the result.
Also, when p is getting larger than 15, you are only changing your carry, but you should also change p accordingly.
I believe you can reverse the result array c in a much more elegant way. By only reversing when the calculation has been performed totally. You can simple call reverse() for that.
I believe you can think hard a little bit more, and write the code in the right way. I have a few suggestions for you, don't use variable names like a,b,c,o. Try to name variables with what are they really doing. Also, you can improve your algorithm and shorten your code and headache with one simple change in the algorithm. First find the length of a and then find the length of b. If there lengths are unequal, find out which has lesser length. Then add 0s in front of it to make both lengths equal. Now, you can simply start from the back, and perform the addition. Also, you should use builtin methods like reverse() , swap() and also string class to make your life easier ;)
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main(){
string firstVal,secondVal;
cout<<"Input two hexadecimal numerals(both of them within 100 digits):\n";
cin >> firstVal >> secondVal;
//Adjust the length.
if(firstVal.size() < secondVal.size()){
//Find out the number of leading zeroes needed
int leading_zeroes = secondVal.size() - firstVal.size();
for(int i = 0; i < leading_zeroes; i++){
firstVal = '0' + firstVal;
}
}
else if(firstVal.size() > secondVal.size()){
int leading_zeroes = firstVal.size() - secondVal.size();
for(int i = 0; i < leading_zeroes; i++){
secondVal = '0' + secondVal;
}
}
// Now, perform addition.
string result;
int digit_a,digit_b,carry=0;
for(int i = firstVal.size()-1; i >= 0; i--){
if(firstVal[i] >= '0' && firstVal[i] <= '9') digit_a = firstVal[i] - '0';
else digit_a = firstVal[i] - 'A' + 10;
if(secondVal[i] >= '0' && secondVal[i] <= '9') digit_b = secondVal[i] - '0';
else digit_b = secondVal[i] - 'A' + 10;
int sum = digit_a + digit_b + carry;
if(sum > 15){
carry = 1;
sum = sum % 16;
}
else{
carry = 0;
}
// Convert sum to char.
char char_sum;
if(sum >= 0 && sum <= 9) char_sum = sum + '0';
else char_sum = sum - 10 + 'A';
//Append to result.
result = result + char_sum;
}
if(carry > 0) result = result + (char)(carry + '0');
//Result is in reverse order.
reverse(result.begin(),result.end());
cout << result << endl;
}
#include <iostream>
using namespace std;
Int main() {
cout<<"Give me a letter" <<endl;
char letter;
cin>>letter;
cout<<letter;
(Int)letter;
letter+=2;
cout<<(char)letter;
(Int)letter;
letter-=25;
cout<<(char)letter;
return 0;
}
How would I manipulate the numbers in a way so that the numbers will always output a letter.
ie: if the letter z was chosen and adding 2 is a symbol how would I manipulate it in a way so that it will always stay between the numbers for capital numbers and uncapitalized numbers. Thanks. Please try to keep answers at a beginner level please I am new to this.
if(letter > 'z') {
//do stuff
}
if(letter < 'a' && letter > 'Z') {
//do stuff
}
if(letter < 'A') {
//do stuff
}
It just depends on how you want to handle the character when it goes into one of the three ranges on the ASCII chart in which the characters are not letters.
As a side note, you don't have to cast a char to an int to do math with it.
char myChar = 'a' + 2;
cout << myChar;
This will print: c
c has an ASCII value of 2 more than a.
The surest method is to use a table for each category, and do
your arithmetic on its index, modulo the size of the table.
Thus, for just lower case letters, you might do something like:
char
transcode( char original )
{
char results = original;
static std::string const lower( "abcdefghijklmnopqrstuvwxyz" );
auto pos = std::find( lower.begin(), lower.end(), results );
if ( pos != lower.end() ) {
int index = pos - lower.begin();
index = (index + 2) % lower.size();
results = lower[ index ];
}
return results;
}
This solution is general, and will work regardless of the sets
of letters you want to deal with. For digits (and for upper and
lower case, if you aren't too worried about portability), you
can take advantage of the fact that the code points are
contiguous, and do something like:
char
transcode( char original )
{
char results = original;
if ( results >= '0' && results <= '9' ) {
char tmp = results - '0'
tmp = (tmp + 2) % 10;
results = tmp + '0';
}
return results;
}
An alternative implementation would be to use something like:
results = results + 2;
if ( results > '9' ) {
results -= 10;
}
in the if above. These two solutions are mathematically
equivalent.
This is only guaranteed to work for digits, but will generally
work for upper or lower case if you limit yourself to the
original ASCII character set. (Be aware that most systems today
support extended character sets.)
You can test directly against ASCII chars by using 'x' notation. Further, you can test things together using && ("and" respectively"):
if ('a' <= letter && letter <= 'z') {
// Letter is between 'a' and 'z'
} else if ('A' <= letter && letter <= 'Z')) {
// Letter is between 'A' and 'Z'
} else {
// Error! Letter is not between 'a' and 'z' or 'A' and 'Z'
}
Or you can use the standard library function std::isalpha which handles this for you:
if (std::isalpha(letter)) {
// Letter is between 'a' and 'z' or 'A' and 'Z'
} else {
// Error! Letter is not between 'a' and 'z' or 'A' and 'Z'
}
I came across a programming question of which I knew only a part of the answer.
int f( char *p )
{
int n = 0 ;
while ( *p != 0 )
n = 10*n + *p++ - '0' ;
return n ;
}
This is what I think the program is doing.
p is a pointer and the while loop is DE-refrencing the values of the pointer until it equals 0. However I don't understand the n assignment line, what is '0' doing? I am assuming the value of p is initially negative, that is the only way it will reach 0 after the increment.
You are confusing the number zero (none, nothing) with the character 0 (a circle, possibly with a slash through it). Notice that zero is in tick marks, so it's the character "0", not the number zero.
'0' - '0' = 0
'1' - '0' = 1
'2' - '0' = 2
...
So by subtracting the character zero from a digit, you get the number that corresponds to that digit.
So, say you have this sequence of digits: '4', '2', '1'. How do you get the number four-hundred and twenty-one from that? You turn the '4' into four. Then you multiply by ten. Now you have fourty. Convert the '2' into two and add it. Now you have fourty-two. Multiply by ten. Convert the '1' into one, and add, now you have four hundred and twenty one.
That's how you convert a sequence of digits into a number.
The n local variable accumulates the value of the decimal number that is passed to this function in the string. This is an implementation of atoi, without the validity checks.
Here is the workings of the loop body:
n = 10*n + *p++ - ‘0';
Assign to n the result of multiplying the prior value of n by ten plus the current character code at the pointer p less the code of zero; increment p after dereferencing.
Since digit characters are encoded sequentially, the *p-'0' expression represents a decimal value of a digit.
Let's say that you are parsing the string "987". As you go through the loop, n starts at zero; then it gets assigned the following values:
n = 10*0 + 9; // That's 9
n = 10*9 + 8; // That's 98
n = 10*98 + 7; // That's 987
It's poorly written, to say the least.
0) Use formatting!:
int f(char* p)
{
int n = 0;
while (*p != 0)
n = 10*n + *p++ - ‘0?;
return n;
}
1) ? there is syntactically invalid. It should probably be a ' as noted by chris (and your existing ‘ is wrong too, but that's probably because you copied it from a website and not a source file), giving:
int f(char* p)
{
int n = 0;
while (*p != 0)
n = 10 * n + *p++ - '0';
return n;
}
2) The parameter type isn't as contrained as it should be. Because *p is never modified (per our goals), we should enforce that to make sure we don't make any mistakes:
int f(const char* p)
{
int n = 0;
while (*p != 0)
n = 10 * n + *p++ - '0';
return n;
}
3) The original programmer was obviously allergic to readable code. Let's split up our operations:
int f(const char* p)
{
int n = 0;
for (; *p != 0; ++p)
{
const int digit = *p - '0';
n = 10 * n + digit;
}
return n;
}
4) Now that the operations are a bit more visible, we can see some independent functionality embedded in this function; this should be factored out (this is called reactoring) into a separate function.
Namely, we see the operation of converting a character to a digit:
int todigit(const char c)
{
// this works because the literals '0', '1', '2', etc. are
// all guaranteed to be in order. Ergo '0' - '0' will be 0,
// '1' - '0' will be 1, '2' - '0' will be 2, and so on.
return c - '0';
}
int f(const char* p)
{
int n = 0;
for (; *p != 0; ++p)
n = 10 * n + todigit(*p);
return n;
}
5) So now it's clear the function reads a string character by character and generates a number digit by digit. This functionality already exists under the name atoi, and this function is an unsafe implementation:
int todigit(const char c)
{
// this works because the literals '0', '1', '2', etc. are
// all guaranteed to be in order. Ergo '0' - '0' will be 0,
// '1' - '0' will be 1, '2' - '0' will be 2, and so on.
return c - '0';
}
int atoi_unsafe(const char* p)
{
int n = 0;
for (; *p != 0; ++p)
n = 10 * n + todigit(*p);
return n;
}
It's left as an exercise to the read to check for overflow, invalid characters (those that aren't digits), and so on. But this should make it much clearer what's going on, and is how such a function should have been written in the first place.
This is a string to number conversion function. Similar to atoi.
A string is a sequence of characters. So "123" in memory would be :
'1','2','3',NULL
p Points to it.
Now, according to ASCII, digits are encoded from '0' to '9'. '0' being assigned the value 48 and '9' being assigned the value 57. As such, '1','2','3',NULL in memory is actually : 49, 50, 51, 0
If you wanted to convert from the character '0' to the integer 0, you would have to subtract 48 from the value in memory. Do you see where this is going?
Now, instead of subtracting the number 48, you subtract '0', which makes the code easier to read.