Why are these two values not equal on arduino? - c++

I am making a little arduino binary calculator.
I have the code run some little math problem: ✓
I convert the answer from decimal to binary: ✓
I loop through the binary answer with a for loop and power on LEDs on a bread board to display the answer: ✗
//First led in pin 2
void setup()
{
Serial.begin(9600);
}
//I have the code run some little math problem:Check
int a=2;
int b=5;
int answer=b-a;
int myNum = answer;
void loop(){
//I convert the answer from decimal to binary:Check
int zeros = 8 - String(myNum,BIN).length();
String myStr;
for (int i=0; i<zeros; i++) {
myStr = myStr + "0";
}
myStr = myStr + String(myNum,BIN);
Serial.println(myStr);
//I loop through the binary answer with a for loop
//and power on LEDs on a bread board to display the answer:Not check
for(int i=2;i<=9;i=i+1){
//This part doesn't work
if(int(myStr[i-2])==1){
digitalWrite(int(i), HIGH);
}else{Serial.println(myStr[i-2]);}
}
while(true){}
}
for some reason it says int(myStr[i-2]) is never equal to 1.
Thanks in advance for the help.

The int() conversion is likely not doing what you think it does. It does not convert the value from a numerical string to a binary value. Instead you probably want to check to see if the values in the string are ascii digits.
if(myStr[i - 2] == '1')
// ^^^ single quotes to specify character value.
{
digitalWrite(int(i), HIGH);
}
else
{
Serial.println(myStr[i - 2]);
}

You should consider that in C a char is nothing more than an alias of an int so casting a char to int is a no-op. So the problem is that you are casting the character '1' or '0' to its int equivalent (its ascii code in fact). You should convert the char to a valid int (by subtracting 48 to a char in the range 48 - 57 you obtain the decimal conversion of the char) or simply checking it against a char value (so myStr[i-2] == '1')

Related

Trying to cast an integer to a char

So I am trying to do a code that will work as a cypher. It will take in the word to cypher as input and output (print) the coded word. The problematic snippet of my code is the for loop.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
char input[] = "hello";
printf("hello\n");
printf("ciphertext: ");
for (int i = 0; i < 5; i++)
{
if(isalpha(input[i]))
{
int current = input[i];
int cypher = ((current + 1) % 26 )+current;
char out = (char)cypher;
printf("%c", out);
}
else
{
printf("%c", input[i]);
}
}
printf("\n");
}
The problem that I run into when debugging is that the value that ends up being stored in "out" seems correct, however whn it comes to printing it, it shows somehthing else entirely. I did look up quite a few things that I found on here , such as writing the code as such:
char out = (char)cypher;
char out= cypher + '0';
and so on but to no avail. The output should be ifmmp but rather i get j~rrx
Anything would help! thanks :)
You're getting the correct answer. 105 is the ASCII value 'i'. There is no difference. More precisely, the char type is defined as an integer. On virtually all compilers it is 8 bits in size. So an unsigned char can have a value between 0 and 255; a signed char can have a value between -128 and +127.
So when your out variable has the value 105, it has the value 'i'.
The output of your printf will be:
i
But if you look at the out variable in a debugger, you might see 105, depending on the debugger.

Returning a big number in for loop

I was working on a problem and got stuck into this silly error and I can't solve it.
Basically I am using a for loop and reading a character from stream. When the character is '-' I am decreasing my integer by one and when it is '+' I am increasing it by one.
I used an unsigned int because I don't want negative numbers. Here is an example of code:
char x;
unsigned int number = 0;
for (int i = 0; i < n; i++){
cin >> x;
if (x == '-'){
number--;
}else if (x == '+'){
number++;
}
}
cout << number;
And it shows a number something like this 4294967293.
Where is the problem?
If your problem statement says that final resultant number will not be negative, it does not mean that the intermediate numbers will also be positive only. Because, there can be a sequence of streams with characters like - + + which leads to values like: 0, -1, 0, 1. Here, final answer is positive but intermediate numbers are still negative.
Now, you are trying to hold both positive and negative numbers in unsigned int datatype which is leads to wrong output here in above example. Because, if number is 0 and you try to apply negation, it will be 4294967295 (maximum value for a variable of type unsigned int) instead of being -1.
So, instead of using unsigned int datatype , you can use int datatype as suggested by Kaidul.
This is due to wrapping around of unsigned data type. Since it's unsigned, it can't be negative. So negation operation wraps around and yields boundary values of 32 bit integer.
Replace
unsigned int number = 0;
with
int number = 0;

Converting from base 10 to any base between 2 and 36

I'm writing a C++ code that converts an unsigned base 10 integer to any other base between 2 and 36. I haven't coded in a while so I'm kind of re-learning everything. My questions are: how can I keep it to just printf, without the cout at the end, and still display the ascii value. And is it possible to make it simple(basic).Sorry if I didn't format properly.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
using namespace std;
int main()
{
int InitialNum, BaseNum, Num, x;
string FinalNum, Temp;
printf("Enter an unsigned integer of base ten: \n");//Prompt user for input
scanf_s("%d", &InitialNum);
printf("Enter the base you want to convert to (min2, max36): \n");
scanf_s("%d", &BaseNum);
x = InitialNum; //save the base 10 number to display at the end
while (InitialNum != 0) //continue dividing until original input is 0
{
Num = InitialNum % BaseNum; //save remainder to Num
int ascii = 48; //declare conversion variable (from int to char)
for (int i = 0; i < 32; ++i)//for loop converts Num from int 0-15 to char '0'-'9', 'A'-'F'
{
if(Num == i)
Temp = ascii;
ascii += 1;
if (ascii == 58)//skip from 9 to A on the ascii table and continue
ascii = 65;
}
FinalNum = Temp + FinalNum;//add to the final answer(additions to the left)
InitialNum /= BaseNum; //the initial base10 number gets divided by the base and saved as the quotient
}
printf("The number %d converted to base %d is:", x, BaseNum);
cout<<(FinalNum);
system("PAUSE");
return 0;
}
In order to output a std::string with printf you have to serve it to printf as a null-terminated string, the C style string. Or, well, you don't absolutely have to: you could print one character at a time. But it's most easy and practical to serve it as a null-terminated string.
You can do that via the .c_str() member function, hence:
printf( "%s\n", FinalString.c_str() );
Note that using std::string can be expensive at this low level of things, due to the dynamic allocation(s). E.g., (http://www.strudel.org.uk/itoa/), timing various implementations of itoa, found a 40x penalty.

converting number characters in a char array to binary

char *toBin(unsigned long long num)
{
char s[9999];
const int size= 9999;
char *temp = new char[size];
int i, j;
int binBase = 2;
for(i=0; num!= 0; i++)
{
s[i] = num % binBase + '0';
num /= binBase;
}//get backwards binary
for(j=0; i>=0; j++)
{
i--;
temp[j]=s[i];
}//reverse binary sequence
//increments one more so need to decrement
temp[--j] = '\0';
return temp;
delete temp;
}
If I had "82" in a char array, I first converted the "82" to the decimal 82 and gave 82 to the function above to convert to binary. This only works within a certain limit of digits.
I think my problem is that unsigned long long can only hold a certain amount of digits so when it exceeds that limit, some random stuff sent to the function, which prints out the wrong binary.
The above function converts a unsigned long long num to binary. I realized that a better approach would be to look at each character in the char array, rather than converting it to a number first, and and use those values to convert to binary. However, I'm having a hard time trying to put it to code. Any suggestions or help would be appreciated.
the GNU Multiple Precision (GMP) library has the functionality to print any size number in any base. The following is an example.
#include <iostream>
#include <gmpxx>
int main()
{
std::string numstr = "1234123412341234123412341234";
// initialize mpz_class to have numstr in it (given in base 10)
mpz_class bigint(numstr, 10);
// convert to binary (base 2)
std::string binstr = bigint.get_str(2);
std::cout << numstr << " -> " << binstr << std::endl;
return 0;
}
output of program
1234123412341234123412341234 -> 111111110011010111110011000011110100100000101001110100011000000101000011000000000111110010
Allocating an array of 9999 char on the stack is ill-advised because it might be too big for your platform. Anyway, you can easily calculate the maximum number of digits (+terminator) needed: CHAR_BIT*sizeof num+1.
Also, there is no need to allocate an equal amount on the heap.
Do not be afraid of pointers:
Init a pointer to the last byte
Set that to zero
Add all digits beginning with the smallest (at least one, even if the number is 0).
Return a copy of the finished number.

Simplifying my program to convert numbers to from one base to another

I'm taking a beginner C++ course. I received an assignment telling me to write a program that converts an arbitrary number from any base between binary and hex to another base between binary and hex. I was asked to use separate functions to convert to and from base 10. It was to help us get used to using arrays. (We already covered passing by reference previously in class.) I already turned this in, but I'm pretty sure this wasn't how I was meant to do it:
#include <iostream>
#include <conio.h>
#include <cstring>
#include <cmath>
using std::cout;
using std::cin;
using std::endl;
int to_dec(char value[], int starting_base);
char* from_dec(int value, int ending_base);
int main() {
char value[30];
int starting_base;
int ending_base;
cout << "This program converts from one base to another, so long as the bases are" << endl
<< "between 2 and 16." << endl
<< endl;
input_numbers:
cout << "Enter the number, then starting base, then ending base:" << endl;
cin >> value >> starting_base >> ending_base;
if (starting_base < 2 || starting_base > 16 || ending_base < 2 || ending_base > 16) {
cout << "Invalid base(s). ";
goto input_numbers;
}
for (int i=0; value[i]; i++) value[i] = toupper(value[i]);
cout << "Base " << ending_base << ": " << from_dec(to_dec(value, starting_base), ending_base) << endl
<< "Press any key to exit.";
getch();
return 0;
}
int to_dec(char value[], int starting_base) {
char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
long int return_value = 0;
unsigned short int digit = 0;
for (short int pos = strlen(value)-1; pos > -1; pos--) {
for (int i=0; i<starting_base; i++) {
if (hex[i] == value[pos]) {
return_value+=i*pow((float)starting_base, digit++);
break;
}
}
}
return return_value;
}
char* from_dec(int value, int ending_base) {
char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char *return_value = (char *)malloc(30);
unsigned short int digit = (int)ceil(log10((double)(value+1))/log10((double)ending_base));
return_value[digit] = 0;
for (; value != 0; value/=ending_base) return_value[--digit] = hex[value%ending_base];
return return_value;
}
I'm pretty sure this is more advanced than it was meant to be. How do you think I was supposed to do it?
I'm essentially looking for two kinds of answers:
Examples of what a simple solution like the one my teacher probably expected would be.
Suggestions on how to improve the code.
I don't think you need the inner loop:
for (int i=0; i<starting_base; i++) {
What is its purpose?
Rather, you should get the character at value[ pos ] and convert it to an integer. The conversion depends on base, so it may be better to do it in a separate function.
You are defining char hex[ 16 ] twice, once in each function. It may better to do it at only one place.
EDIT 1:
Since this is "homework" tagged, I cannot give you the full answer. However, here is an example of how to_dec() is supposed to work. (Ideally, you should have constructed this!)
Input:
char * value = 3012,
int base = 4,
Math:
Number = 3 * 4^3 + 0 * 4^2 + 1 * 4^1 + 2 * 4^0 = 192 + 0 + 4 + 2 = 198
Expected working of the loop:
x = 0
x = 4x + 3 = 3
x = 4x + 0 = 12
x = 4x + 1 = 49
x = 4x + 2 = 198
return x;
EDIT 2:
Fair enough! So, here is some more :-)
Here is a code sketch. Not compiled or tested though. This is direct translation of the example I provided earlier.
unsigned
to_dec( char * inputString, unsigned base )
{
unsigned rv = 0; // return value
unsigned c; // character converted to integer
for( char * p = inputString; *p; ++p ) // p iterates through the string
{
c = *p - hex[0];
rv = base * rv + c;
}
return rv;
}
I would stay away from GOTO statements unless they are absolutely necessary. GOTO statements are easy to use but will lead to 'spaghetti code'.
Try using a loop instead. Something along the lines of this:
bool base_is_invalid = true;
while ( base_is_invalid ) {
cout << "Enter the number, then starting base, then ending base:" << endl;
cin >> value >> starting_base >> ending_base;
if (starting_base < 2 || starting_base > 16 || ending_base < 2 || ending_base > 16)
cout << "Invalid number. ";
else
base_is_invalid = false;
}
You can initialize arrays by string literals (notice that the terminating \0 is not included because the size of the array doesn't permit that):
char const hex[16] = "0123456789ABCDEF";
Or just use a pointer to the string literal for the same effect:
char const* hex = "0123456789ABCDEF";
to_dec() looks to complicated, here is my shot at it:
int to_dec(char* value, int starting_base)
{
int return_value = 0;
for (char* cur = value + strlen(value) - 1; cur >= value; cur--) {
// assuming chars are ascii/utf: 0-9=48-57, A-F=65-70
// faster than loop
int inval = *cur - 48;
if (inval > 9) {
inval = *cur - 55;
if (inval > 15) {
// throw input error
}
}
if (inval < 0) {
// throw input error
}
if (inval >= starting_base) {
// throw input error
}
// now the simple calc
return_value *= starting_base;
return_value += inval;
}
return return_value;
}
for the initial conversion from ascii to an integer, you can also use a lookup table (just as you are using a lookuptable to to the conversion the other way around) , which is much faster then searching through the array for every digit.
int to_dec(char value[], int starting_base)
{
char asc2BaseTab = {0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15, //0-9 and A-F (big caps)
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //unused ascii chars
10,11,12,13,14,15}; //a-f (small caps)
srcIdx = strlen(value);
int number=0;
while((--srcIdx) >= 0)
{
number *= starting_base;
char asciiDigit = value[srcIdx];
if(asciiDigit<'0' || asciiDigit>'f')
{
//display input error
}
char digit = asc2BaseTab[asciiDigit - '0'];
if(digit == -1)
{
//display input error
}
number += digit;
}
return number;
}
p.s. excuses if there are some compile errors in this...I couldn't test it...but the logic is sound.
In your description of the assignment as given it says:
"I was asked to use separate functions to convert to and from base 10."
If that is really what the teacher meant and wanted, which is doubtful, your code doesn't do that:
int to_dec(char value[], int starting_base)
is returning an int which is a binary number. :-) Which in my opinion does make more sense.
Did the teacher even notice that?
C and C++ are different languages, and with different styles of programming. You better not to mix them. (Where C and C++ differ)
If you are trying to use C++, then:
Use std::string instead of char* or char[].
int to_dec(string value, int starting_base);
string from_dec(int value, int ending_base);
No any mallocs, use new/delete. But actually C++ manages memory automatically. The memory is freed as soon as variable is out of scope (unless you are dealing with pointers). And pointers are the last thing you need to deal with.
We don't need here any lookup tables, just a magic string.
string hex = "0123456789ABCDEF";//The index of the letter is its decimal value. A is 10, F is 15.
//usage
char c = 'B';
int value = hex.find( c );//works only with uppercase;
The refactored to_dec can be like that.
int to_dec(string value, int starting_base) {
string hex = "0123456789ABCDEF";
int result = 0;
for (int power = 0; power < value.size(); ++power) {
result += hex.find( value.at(value.size()-power-1) ) * pow((float)starting_base, power);
}
return result;
}
And there is a more elegant algorithm to convert from base 10 to any other
See there for example. You have the opportunity to code it yourself :)
In your from_dec function, you're converting the digits from left to right. An alternative is to convert from right to left. That is,
std::string from_dec(int n, int base)
{
std::string result;
bool is_negative = n < 0;
if (is_negative)
{
n = - n;
}
while (n != 0)
{
result = DIGITS[n % base] + result;
n /= base;
}
if (is_negative)
{
result = '-' + result;
}
return result;
}
This way, you won't need the log function.
(BTW, to_dec and from_dec are inaccurate names. Your computer doesn't store numbers in base 10.)
Got this question on an interview once and brainfarted and spun wheels for a while. Go figure. Anyway, a couple years later I'm going through Math and Physics for Programmers to brush up for positions that are more math intensive than what I've been doing. CH1 "assignment" has
// Write a function ConvertBase(Number, Base1, Base2) which takes a
// string or array representing an integer in Base1 and converts it
// into base Base2, returning the new string.
So, I took an approach mentioned above: I convert string in arbitrary base to UINT64, then I convert UINT64 back to arbitrary base:
CString ConvertBase(const CString& strNumber, int base1, int base2)
{
return ValueToBaseString(BaseStringToValue(strNumber, base1), base2);
}
Each of the subfunctions has a recursive solution. Here's one for example:
UINT64 BaseStringToValue(const CString& strNumber, int base)
{
if (strNumber.IsEmpty())
{
return 0;
}
CString outDigit = strNumber.Right(1);
UINT64 output = DigitToInt(outDigit[0]);
CString strRemaining = strNumber.Left(strNumber.GetLength() - 1);
UINT64 val = BaseStringToValue(strRemaining, base);
output += val * base;
return output;
}
I find the other one slightly harder to grasp mentally, but it works roughly the same way.
I also implemented DigitToInt and IntToDigit which work just like they sound. You can take some neat shortcuts there, by the way, if you realize that chars are ints then you don't need huge switch statements:
int DigitToInt(wchar_t cDigit)
{
cDigit = toupper(cDigit);
if (cDigit >= '0' && cDigit <= '9')
{
return cDigit - '0';
}
return cDigit - 'A' + 10;
}
and unit tests are really your friend here:
typedef struct
{
CString number;
int base1;
int base2;
CString answer;
} Input;
Input input[] =
{
{ "345678", 10, 16, "5464E"},
{ "FAE211", 16, 8, "76561021" },
{ "FAE211", 16, 2, "111110101110001000010001"},
{ "110110111", 2, 10, "439" }
};
(snip)
for (int i = 0 ; i < sizeof(input) / sizeof(input[0]) ; i++)
{
CString result = ConvertBase(input[i].number, input[i].base1, input[i].base2);
printf("%S in base %d is %S in base %d (%S expected - %s)\n", (const WCHAR*)input[i].number,
input[i].base1,
(const WCHAR*) result,
input[i].base2,
(const WCHAR*) input[i].answer,
result == input[i].answer ? "CORRECT" : "WRONG");
}
And here's the output:
345678 in base 10 is 5464E in base 16 (5464E expected - CORRECT)
FAE211 in base 16 is 76561021 in base 8 (76561021 expected - CORRECT)
FAE211 in base 16 is 111110101110001000010001 in base 2 (111110101110001000010001 expected - CORRECT)
110110111 in base 2 is 439 in base 10 (439 expected - CORRECT)
Now I took some shortcuts in coding by using CString types, etc. I was giving no consideration to efficiency or performance, I just wanted to solve the algorithm with easiest coding possible.
It can help to understand how these algorithms are recursive if you write them like so: Say you want to determine the "value" of the "string" B4A3, which is in base 13. You know it's 3 + 13(A) + 13(13)(4) + 13(13)(13)(B) Another way to write that is: 0+3+13(A+13(4+13(B))) - and voila! Recursion.
Apart from the things already mentioned, I would suggest using the new-operator instead of free. The advantages of new are that it also does call constructors - which is irrelevant here since you're using a POD type, but important when it comes to objects such as std::string or your own custom classes - and that you can overload the new operator to suit your specific needs (which is irrelevant here, too :p). But don't go ahead using malloc for PODs and new for classes, since mixing them is considered bad style.
But okay, you got yourself some heap memory in from_dec... but where is it freed again? Basic rule: memory that you malloc (or calloc etc) must be passed to free at some point. The same rule applies to the new-operator, just that the release-operator is called delete. Note that for arrays, you need new[] and delete[]. DON'T ever allocate with new and release with delete[] or the other way around, since the memory won't be released correctly.
Nothing evil will happen when your toy program won't release the memory... I guess your PC has got enough RAM to cope with it and when you shut down your program, the OS releases the memory anyway.. but not all programs are (a) that tiny and (b) shut down often.
Also I'd avoid conio.h, since this is not portable. You're not using the most complicated IO, so the standard headers (iostream etc) should do.
Likewise, I think most programmers using modern languages follow the rule "Only use goto if other solutions are really crippled or tons of more work". This is a situation that can be easily solved by using loops, as shown by emceefly. In your program the goto is easy to handle, but you won't be writing such small programs forever, will you? ;)
I, for example, was presented with some legacy code recently.. 2000 lines of goto-littered code, yay! Trying to follow the code's logical flow was almost impossible ("Oh, jump ahead 200 lines, great... who needs context anyway"), even harder was to rewrite the damn thing.
So okay, your goto doesn't hurt here, but where's the benefit? 2-3 lines shorter? Doesn't really matter overall (if you're paid by lines of code, this could also be a major disadvantage ;)). Personally I find the loop version more readable and clean.
As you see, most of the points here can be ignored easily for your program, since it's a toy program. But when you think of larger programs, they make more sense (hopefully) ;)