Using chars into an int datatype - c

Using C, One array with 5 memory spaces
int call[5]
I'm trying to figure out how to use the first 3 spaces of the array to make a base-36 conversion (meaning 1K0 base-36 equals to 2040 in base-10), the other 2 spaces would be filled with data (probably more ints).
However... does 1K0 look actually like an int? (to me K looks like a char and in theory, char should be enough -127 to 127 for the conversion using base-36)
however what would happen if i try to do this using int instead of char?
is there any alternative to use a base-36 conversion in the first array only mixed with ints for the rest of the spaces in memory
does it matter? (since the array was declared int)
EDIT: to be clear i just want to know if i can declare an int array and fill it with chars, and if i cant, how can i achieve this?

I'm not exactly sure if you can tell the compiler that, you can signal Hex (0x), octal (o) Binary (b) but base 36 is odd enough to not be standard.
You can always make a function (and maybe embed it in a class) that does the string-to-base10 conversion of base 36
I'll do my best in C terms
int base10Number = 0
int base36StringLenght = strlen(base35String);
for( int i = base36StringLenght - 1; i <= 0; i--){ //count from the end of the string back
char c = base36String[i];
if(c <= '9'){
c -= '0' //gives a 0 to 9 range
}
else{ //assuming that the string is perfect and has no extra characters is safe to just do this
c = tolower(c); //first make sure it's lowercase
c -= 'a' + 10 // this will make the letters start at 10 dec
}
base10Number += c * pow(36, base36StringLenght - 1 - i) // the power function specifies which 'wheel' you're turning (imagine an old analog odometer) and then turns the wheel c times, then adds it to the overall sum.
}
This whole code works by the theory that every digit starting from the last is worth its base 10 number multipled by 36 to the power of its position from last.
So last digit is c * 36^0 which is one, the c*36^1 and so on. similar on how 2*10^1 equals 20 if the 2 is in second-to-last position.
Hope that some of this makes sense to you, and dont forget to make your base36 number a string
EDIT:
I saw your edit to the answer and the short asnwer is yes, you can totally do that, it would be a waste of space since you'll have a whole 3 bytes unused at all times, you can simply make a char array. Besides, all string functions will demand you to feed them a char array (you can cast it) but if you're storing one digit per array space char will do the trick. If your array is dynamic and/or you need to make some math on it the base 36 to base 10 conversion will allow you to do math and to blow the whole array for a single int or float type. But if you're just going to store it to display it later or to feed it to another function in the same format the conversion is not necessary at all. (If you're working with a big ammount of this numbers and you need to put them in a database converting to base10 and storing in a single in will save tons of space)
PS: also edited the code to use ' ' enclosed chars instead of ascii numbers, thanks for the request!

Related

Is it possible to calculate with ASCII numbers that are temporarily bigger than 127?

First of all, im new to coding and I thought sometime about the problem and I tried to google it.
I already have a workaround I just want to know if it is possible in another way.
Im taking the cs50 course and I should write an encryption function.
My problem is, that my char gets temporarily bigger then 127 and then gets truncated.
So is it nevertheless possible to calculate with a certain char temporarily before I save it it
into a memory address and truncate it?
The part where I think the problem should be:
for
(int i = 0; i < strlen(ui); i++)
{
if
(isupper(ui[i]))
{
ui[i] += key;
if
(ui[i] > 90)
{
ui[i] -= 26;
}
}
if
(islower(ui[i]))
{
ui[i] += key;
if
(ui[i] > 122)
{
ui[i] -= 26;
}
}
and it gets truncated e.g. if the key gets bigger then 6 for an input of z.
So can I write it somehow, that the 26 gets subtracted before it gets into storage or is (what I think atm) not possible because as soon as it gets bigger then 127 even if it is in one line, it gets truncated?
Workaround ( I thought about writing now):
I will subtract 96 before so I get calculate with numbers between 1 and 27 and add it after.
thank you for advice in advance.
My problem is, that my char gets temporarily bigger then 127 and then gets truncated. So is it nevertheless possible to calculate with a certain char temporarily before I save it it into a memory address and truncate it?
Yes, it is possible, and you do not have to do anything special to achieve it. In a C expression, all arithmetic operands of integer types narrower than int are converted to int or wider, and the computation is performed in that wider type, producing a result of that type. It is then narrowed again if necessary for assignment to an object of narrower type.
Note, however, that
A narrowing conversion to a signed integer type has implementation-defined behavior if the initial value cannot be represented in the target type. That can include raising an implementation-defined signal. It is not safe to assume that the most-significant bytes will just be chopped off when they contain values other than zero.
What you describe is not what the code presented actually does. In particular, I take you to be talking about this:
ui[i] += key;
It is not a problem to compute ui[i] + key in this case, but there is no particular delay there before writing the result to memory. That's what the assignment part of += does.
You would be better off avoiding the situation altogether. For instance,
if (islower((unsigned char) ui[i])) {
ui[i] = (((ui[i] - 'a') + key) % 26) + 'a';
}
Do also note, however, that that (and your original) assumes that the numeric values of the lower-case letters for a contiguous block. That is frequently true, but not universally so.
A possible overflow bug was mentioned in the comments, however, there's probably another bug in the code, maybe, I don't know what your algorithm should be.
Consider when ui[i] is 'Z' (90 ASCII) and the key ':' (58 ASCII). 'Z' is uppercase so the body of the first if statement is executed, resulting in ui[] being 90 + 58 - 26 = 122 which is now 'z', N.B. lowercase.
Now z is lowercase, so the body of the second if also executes which results in ui[] now being 122 + 58 - 26 = 154. This is outside the ASCII range so you get overflow there.
Another example is ui[] = 'A' and key 70. The first if changes ui[] to 65 + 70 - 26 = 109 which is 'm'. This will also trigger the second if statement with overflow resulting again.
I doubt that both if bodies are supposed to be executed on the same value. If not then you need to add an else before the second if.
}
else if (islower(ui[i])) {
...

How to increase the speed of computed Fibonacci caluculations - C

I wrote a small program to compute Fibonacci numbers:
#include <stdio.h>
int main()
{
int first, second, final;
first = 0;
second = 1;
printf("0\n1\n"); /* I know this is a quick fix, but the program still works */
while (final <= 999999999999999999) {
final = first + second;
first = second;
second = final;
printf("%d\n", final);
}
}
Is there any way to increase the speed in which this program computes these calculations? Could you possible explain the solution to me (if it exists)?
Thanks.
Of course it's possible! :)
First of all, please note you're using signed int for your variables, and max int on a 32 bit machine is 2,147,483,647 which is approx. 10^8 times smaller than the max number you're using, which is 999,999,999,999,999,999.
I'll recommend to change the max num to INT_MAX (You'll need to include "limits.h")
Edit:
In addition, as said in the comments to my answer, consider changing to unsigned int. you need only positive values, and the max number will be twice higher.
2nd Edit:
That being said, when final will reach the closest it can to the limit in the condition, the next time its promoted, it'll exceed INT_MAX and will result in an overflow. That means here, that the condition will never be met.
Better to just change the condition to the times you want the loop to run. Please note though, that any fibonacci number larger than the max numder that can be stored in your variable type, will result in an overflow.
Secondly, final isn't initialized. Write final = 0 to avoid errors.
I recommend turning on all the warnings in your compiler. It could catch many errors before they compile :)
Also, I see no reason not to initialize the variables when you declare them. The value is already known.
Now for the speed of the program:
I'm not sure to which extent you're willing to change the code, but the simplest change without changing the original flow, is to make less calls to printf().
Since printf() is a function that will wait for a system resource to become available, this is probably the most time consuming part in your code.
Maybe consider storing the output in a string, and lets say every 100 numbers print the string to the screen.
Try maybe to create a string, with a size of
(10 (num of chars in an int) + 1 (new line char) )* 100 (arbitrary, based on when you'll want to flush the data to the screen)
Consider using sprintf() to write to a string in the inner loop, and strcat() to append a string to another string.
Then, every 100 times, use printf() to write to the screen.
As already stated in other answers, you have obvious two problems. 1) The missing initialization of final and 2) that your loop condition will result in an endless loop due to 999999999999999999 being larger than any integer value.
The real problem here is that you use a fixed number in the condition for the while.
How do you know which number to use so that you actually calculates all the Fibonacci numbers possible for the used integer type? Without knowing the numbers in advance you can't do that! So you need a better condition for stopping the loop.
One way of solving this to check for overflow instead - like:
while (second <= (INT_MAX - first)) { // Stop when next number will overflow
The above approach prevents signed overflow by checking whether the next first + second will overflow before actually doing the first+second. In this way signed overflow (and thereby UB) is prevented.
Another approach is to use unsigned integers and deliberately make an overflow (which is valid for unsigned int). Using unsigned long long that could look like:
unsigned long long first, second, next;
first = 1;
second = 1;
printf("1\n1\n");
next = first + second;
while (next > second) { // Stop when there was an overflow
printf("%llu\n", next);
first = second;
second = next;
next = first + second;
}
Speed isn't your problem. You have an infinite loop:
while (final <= 999999999999999999) {
final has type int. Most likely int is 32-bit on your system, which means the maximum value it can hold is 2147483647. This will always be smaller than 999999999999999999 (which is a constant of type long long), so the loop never ends.
Change the datatype of your variables to long long and the loop will terminate after about 87 iterations. Also, you'll need to change your printf format specifier from %d to %lld to match the datatype printed.
Why are you asking this question?
If it's the intention to increase the performance, you might go for the formula of the n-th Fibonacci number, which is something like:
((1+v5)/2)^n + ((1-v5)/2)^n, something like that (v5 being the square root of 5).
If it's about learning to increase performance, you might do a code review or use performance diagnostics tools.

How do I display an integer with a function that only accepts a char in C?

I'm going to do my best to explain exactly what my problem is. I'm currently taking an embedded systems class and I'm really struggling with this portion of the project. I have a small STM32 board with a simple LCD screen connected to it. I have a function already written that will take a single char and write it to the LCD. Now, I often use that function to write char's but there is one scenario in which I need to write an int between 0 and 99 to the screen. The int variable is always changing because it is based on the value in a timer when a user presses the button on the board. I have been stumped by this for hours and I could really use some help. I have emailed my teacher but he isn't replying. Any help is greatly appreciated.
Also, the LCD_write function is already provided to me by my teacher so I can't just create a version of it that will accept an int.
If I haven't given enough detail just let me know.
You just need to convert your int to two chars:
char ch0 = i % 10 + '0'; // convert least significant digit to char
char ch1 = i / 10 + '0'; // convert most significant digit to char
Note: this assumes that you can guarantee that the int is always in the range 0..99.

Variable length arithmetic calculator WITHOUT using strings?

I'm trying to create a calculator that solves arithmetic expressions of different lengths (e.g. 2+3/4 or 7*8/2+12-14), and I was wondering if it was possible to do so without the use of strings.
I've found countless tutorials explaining how to make a simple calculator with only two numbers and an operator, and I've also found examples using sscanf and strings to get the input.
However, my question is: Is there a way (is it even possible) to get variable length inputs without using strings?
At first I thought i could simply add more specifiers:
int num1 , num2, num3;
char op1, op2;
printf("Please enter your equation to evaluate: ");
scanf("%d%c%d%c%d", &num1, &op1, &num2, &op2, &num3);
but obviously, that doesn't work for equations longer than 3 numbers or less than 3 numbers.
I was also thinking of perhaps using some sort of recursive function, but I'm not sure how I would do that if I need to ask for the entire equation up front?
If you intend to read ASCII from user input, or from command line arguments, then you're pretty inescapably in the world of strings. What you can do is convert them into something else as early as possible.
You could abandon ASCII altogether and define a binary file format.
For example, you might say that each pair of two bytes is a token. The first byte is an element type ( signed integer, unsigned integer, float, operator), the second byte is the value.
Pseudocode:
while(!done) {
int type = read(f);
int value = read(f);
switch(type) {
case TYPE_INTEGER:
push_to_stack(value);
break;
case TYPE_FLOAT:
push_to_stack_as_float(value);
break;
case TYPE_OPERATOR:
execute_operator(value);
break;
}
}
Quite why you would force yourself down this route, I don't know. You'd probably find yourself wanting to write a program to convert ASCII input into your binary file format; which would use strings. So why did you run away from strings in the first place?
you can create a list of struct, every struct will have to contains a value OR a sub list, an operator (char?) and a reference to the next (and or before) char.
Then you just ask the user for a number (or "("/")"), and a operator sign. Every number + operator is a new element in list, every ( is a sub list, every ) is a return to superior list (you can even don't create a sublist, but elaborate it on the fly and return just the result, like a recursive function)
Also struct and code can be elaborated to support multiple parameter.

C - need to detect presence of digit in a number (hw)

I'm trying to write a function that'll detect if a digit is found in a number:
// returns 1 if source contains num, 0 otherwise
int contains_num(source, num);
for example, contains_num(12345, 3) returns 1 and contains_num(12345, 6) returns 0.
I'm not sure how to go about solving this. Probably can't use pointers, arrays and such.
Any ideas? thanks.
Since this is homework, I don't want to give you the entire answer right away. Instead, I'll ask a series of questions, and let you answer in the comments, so I'll simply be guiding you to the correct answer rather than giving it to you outright.
So, you have a number, and you want to break it down into individual digits. Can you think of a way of extracting one digit from the number, say, the last one? Think about what each digit represents, and how you might be able to isolate one digit from the rest of them.
An alternative way of looking at the problem is:
Does the string representation of the number contain a specific digit?
It is relatively easy to convert the number to a string; there are string searching functions to find whether a specific character appears in the string.
And this has the merit of working on negative numbers whereas some of the suggestions I've seen fail on negative numbers (and most of the rest do not address the issue explicitly). (Question for you: why?)
This should work:
int Contains_Num(int source, int num)
{
if (source == 0 && num == 0) return 1;
int tmpSource = source;
while (tmpSource != 0)
{
if (tmpSource % 10 == num) return 1;
tmpSource /= 10;
}
return 0;
}
Your answer is dependent on the base a number is represented in. For example, the number 255 contains 5 when written in base 10, but in base 16, it does not. Your base seems to be 10.
So what you want to do is to look at the last digit of a number, and see if it is the digit you want. The last digit can be easily found using the modulo operator (%). If it is the digit you want, you're done. If not, and if there are more digits, you can discard the last digit and repeat the process again for the number obtained by dividing the original number by 10 and discarding the fractional part. In C, the division operator, /, does this for you automatically if both the operands of it are of integer type.
When you run out of digits because division gives you 0, you are sure that the number doesn't contain the digit you wanted.

Resources