I am a novice programmer trying to understand arrays in C. Specifically I want to take the numeric value of a variable and feed it into an array. I tried to assign the value to the array, but failed with error messages. Can someone explain, simplistically, how to push a value into an array and then be able to just access the last digit?
My last attempt:
#include <stdio.h>
unsigned int TMR0 = 158;
int main(void)
{
unsigned int V = TMR0;
unsigned int Random[2] = {V};
printf("%d \n" , *(Random+2));
return 0;
Thanks.
unsigned int Random[2];
Array will be declared with two positions.
Random[0] Random[1] // two accessible positions in that array.
When you are assigning the value to the array,
unsigned int Random[2] = { V} ;
Value will be stored in the first position of array. Random[0].
*(Random+2) will access the position Random[2]. Which is not accessible position for this array. It will lead to undefined behaviour.
Another thing is if you need to assign the values to both the position you have to do like this.
unsigned int Random[2] = {V,V} ;
To access the last element in your array,
*(Random+1) or Random[1]
May this link will help.
You don't actually need an array to access digits of your number -- you just need math.
It's important to realise that "digit" implies a particular numeric base. In the computer, numbers are represented in binary. For convenience, they can be represented in our code using common bases: decimal, hexadecimal, and octal are the ones we generally use in languages like C.
So, to get the last digit in base 10, you would take the value modulo 10:
int val = 158;
int last_digit = val % 10;
printf( "%d\n", last_digit );
If you need to find digits other than the last, you can first perform integer division and then modulo:
int second_to_last_digit = (val / 10U) % 10;
Alternatively you can convert the number into a string, and then look at each character in that string. But I'm not going to go into that here, since it can be confusing to provide too much information to new programmers.
Related
I'm making a function that takes a value using scanf_s and converts that into a binary value. The function works perfectly... until I put in a really high value.
I'm also doing this on VS 2019 in x64 in C
And in case it matters, I'm using
main(int argc, char* argv[])
for the main function.
Since I'm not sure what on earth is happening, here's the whole code I guess.
BinaryGet()
{
// Declaring lots of stuff
int x, y, z, d, b, c;
int counter = 0;
int doubler = 1;
int getb;
int binarray[2000] = { 0 };
// I only have to change things to 1 now, am't I smart?
int binappend[2000] = { 0 };
// Get number
printf("Gimme a number\n");
scanf_s("%d", &getb);
// Because why not
printf("\n");
// Get the amount of binary places to be used (how many times getb divides by 2)
x = getb;
while (x > 1)
{
d = x;
counter += 1;
// Tried x /= 2, gave me infinity loop ;(
x = d / 2;
}
// Fill the array with binary values (i.e. 1, 2, 4, 8, 16, 32, etc)
for (b = 1; b <= counter; b++)
{
binarray[b] = doubler * 2;
doubler *= 2;
}
// Compare the value of getb to binary values, subtract and repeat until getb = 0)
c = getb;
for (y = counter; c >= 1; y--)
{
// Printing c at each subtraction
printf("\n%d\n", c);
// If the value of c (a temp variable) compares right to the binary value, subtract that binary value
// and put a 1 in that spot in binappend, the 1 and 0 list
if (c >= binarray[y])
{
c -= binarray[y];
binappend[y] += 1;
}
// Prevents buffer under? runs
if (y <= 0)
{
break;
}
}
// Print the result
for (z = 0; z <= counter; z++)
{
printf("%d", binappend[z]);
}
}
The problem is that when I put in the value 999999999999999999 (18 digits) it just prints 0 once and ends the function. The value of the digits doesn't matter though, 18 ones will have the same result.
However, when I put in 17 digits, it gives me this:
99999999999999999
// This is the input value after each subtraction
1569325055
495583231
495583231
227147775
92930047
25821183
25821183
9043967
655359
655359
655359
655359
131071
131071
131071
65535
32767
16383
8191
4095
2047
1023
511
255
127
63
31
15
7
3
1
// This is the binary
1111111111111111100100011011101
The binary value it gives me is 31 digits. I thought that it was weird that at 32, a convenient number, it gimps out, so I put in the value of the 32nd binary place minus 1 (2,147,483,647) and it worked. But adding 1 to that gives me 0.
Changing the type of array (unsigned int and long) didn't change this. Neither did changing the value in the brackets of the arrays. I tried searching to see if it's a limit of scanf_s, but found nothing.
I know for sure (I think) it's not the arrays, but probably something dumb I'm doing with the function. Can anyone help please? I'll give you a long-distance high five.
The problem is indeed related to the power-of-two size of the number you've noticed, but it's in this call:
scanf_s("%d", &getb);
The %d argument means it is reading into a signed integer, which on your platform is probably 32 bits, and since it's signed it means it can go up to 2³¹-1 in the positive direction.
The conversion specifiers used by scanf() and related functions can accept larger sizes of data types though. For example %ld will accept a long int, and %lld will accept a long long int. Check the data type sizes for your platform, because a long int and an int might actually be the same size (32 bits) eg. on Windows.
So if you use %lld instead, you should be able to read larger numbers, up to the range of a long long int, but make sure you change the target (getb) to match! Also if you're not interested in negative numbers, let the type system help you out and use an unsigned type: %llu for an unsigned long long.
Some details:
If scanf or its friends fail, the value in getb is indeterminate ie. uninitialised, and reading from it is undefined behaviour (UB). UB is an extremely common source of bugs in C, and you want to avoid it. Make sure your code only reads from getb if scanf tells you it worked.
In fact, in general it is not possible to avoid UB with scanf unless you're in complete control of the input (eg. you wrote it out previously with some other, bug free, software). While you can check the return value of scanf and related functions (it will return the number of fields it converts), its behaviour is undefined if, say, a field is too large to fit into the data type you have for it.
There's a lot more detail on scanf etc. here.
To avoid problems with not knowing what size an int is, or if a long int is different on this platform or that, there is also the header stdint.h which defines integer types of a specific width eg. int64_t. These also have macros for use with scanf() like SCNd64. These are available from C99 onwards, but note that Windows' support of C99 in its compilers is incomplete and may not include this.
Don't be so hard on yourself, you're not dumb, C is a hard language to master and doesn't follow modern idioms that have developed since it was first designed.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have two functions which supposedly can convert decimals to binary, however I can't seem to get them to work if the decimal is above 3 (I get weird negative numbers). I can't fully understand the code in the functions as I've only just started to learn C, however I was hoping if someone could tell me if the functions work, or if I am just not doing something right i.e. should I be using int32_t type as the value to pass into the function?
uint8_t dec_to_bin(int decimal){
int n = decimal, i, j, binno=0,dn;
dn=n;
i=1;
for(j=n;j>0;j=j/2)
{
binno=binno+(n%2)*i;
i=i*10;
n=n/2;
}
return binno;
}
uint8_t dec_to_bin2(int decimal){
long long binaryNumber = 0;
int remainder, i = 1;
while (decimal!=0){
remainder = decimal%2;
decimal /= 2;
binaryNumber += remainder*i;
i *= 10;
}
return binaryNumber;
}
Unfortunately I have no way to find out the values of the binary numbers as a uint_8 type as I am doing this on a micro-controller and there is no way to debug or print values anywhere (I have posted numerous threads asking how to do this, with no luck). We have however been provided with another function:
int bin_to_dec(uint64_t binary) {
int result = 0;
for ( int i = 7; i >= 0; i-- ) {
result = result * 10 + ((binary >> i) & 1);
}
return result;
}
This function converts the binary number back to an integer so I can display it on the screen with a library function (the library function can only display integers or strings). If I pass 10 into either of the decimal to binary converter functions, then pass the uint_8 value from either function to the binary to decimal converter and print to the LCD, I get -3110. This should just be 1010.
I'm sorry to say, but your dec_to_bin and dec_to_bin2 functions are meaningless. Throw them away. They might -- might -- have a tiny bit of value as a teaching exercise. But if you're trying to write actual code for a microcontroller to actually do something, you don't need these functions, and you don't want these functions. (Also you need to understand why you don't need these functions.)
The problem is not that they're implemented wrongly. They're fundamentally flawed in their very intent.
These functions seem to convert, for example, the integer 5 to the integer 101, and at first glance that might look like "decimal to binary conversion", but it's not. You've just converted the number five to the number one hundred and one.
Let's look at this a different way. If I say
int i = 17;
and if I then call
printf("%d\n", i);
I see the value "17" printed, as I expect. But I can also call
printf("%x\n", i);
and this prints i's value in hexadecimal, so I see "11". Did I just convert i from decimal to hexadecimal? No, I did not! I took the same number, "seventeen", and I printed it out in two different ways: in decimal, and in hexadecimal.
For all practical purposes, unless you're designing the actual hardware a program will run on, it really doesn't make sense to ask what base a number is stored in. A variable like int i is just a number, an integer. (Deep down inside, of course, on a conventional processor we know it's stored in binary all the time.)
The only time it makes sense to explicitly convert a number to binary is if you want to print it out in a human-readable text representation, in binary. In that case, you're converting from an integer to a string. (The string will consist of the characters '0' and '1'.)
So if you want to write a meaningful decimal-to-binary converter (which will actually be an anything-to-binary converter), either have it print the binary number out to the screen, or store it in a string (an array of characters, or char []).
And if you're in a class where you're being asked to write uint8_t dec_to_bin(int decimal) (or where your instructor is giving you examples of such functions), I can't help you, and I'm afraid you're doomed. Half of what this instructor is teaching you is wrong or badly misleading, will seriously handicap you from ever being a successful C programmer. Of course I can't tell you which half, because I don't know what other lies you're being taught. Good luck -- you'll need it! -- unlearning these false facts later.
I don't know why you're trying to store binary data as base 10 numbers instead of just printing or storing (as a char[]) the bits of an int (get kth bit of n as (n >> k) & 1 then print/store), but I'll assume it's necessary.
Your solution could be prone to overflowing the uint8_t as mentioned in the comments. Even a uint64_t can only hold 19 bits of binary data in the format you're using, less than the 32 of typical ints. The return type of your second function is still uint8_t, this might just be a typo, but it means the internal representation of long long will be implicitly cast on return.
I've written some functions based on yours, but with a little more bit manipulation that work for me.
uint64_t dec_to_bin (int n)
{
uint64_t result = 0;
int k, i;
// 64 bits can only hold 19 (log10(2^64)) bits in this format
for (i = 0, k = n; k && i < 19; i++) {
// Because the loop is limited to 19 we shouldn't need to worry about overflowing
result *= 10;
result += (n >> i) & 1;
k /= 2;
}
return result;
}
int bin_to_dec (uint64_t n)
{
int result = 0;
while (n) {
result <<= 1;
result += n % 2;
n /= 10;
}
return result;
}
I tested your functions on the input 43 on my system and got
43 // Original Input
101011 // dec_to_bin2 with long long return type
10010011 // bin_to_dec
With an appropriately sized output, your dec_to_bin2 function does work as expected.
And my functions:
43 // Original Input
110101 // dec_to_bin
43 // bin_to_dec
The endianness may not be what you're expecting, but that can be changed if necessary.
Alright, soo the task at hand is to compute 10^10 where the first 10 is an integer called "base" and the second 10 is an unsigned integer called "exponent".
int base = 10; unsigned int exponent = 10; int i = 1; long long result = 1;
while(i<=exponent){
result = result*base;
i++;
}
printf("X^y = %ld\n\n", result);
Now I've tried this with a for loop, while loop, recursive functions etc. And my "result" value is still 1410065400 for some reason? It should be just a one with a bunch of zeros. If anyone got a simple solution to this problem I would be very happy to hear it. And if this has been posted before (didn't find anything on here about it tho) then I would gladly accept the link to that solution.
As sad in comment, your format specifier is wrong in printf function. It should be like:
printf("X^y = %lli\n", result);
lli is the correct format specifier. Result:
X^y = 10000000000
Integer values in C programming language are 32 bits and it can hold values that contains 10 digits but 10^10 is 11 digit so it overflows.
You can learn about more from this question:
What is the maximum value for an int32?
C : convert to integer using bits
I need to get integer value from bit arrays of 0, 1.
I want to pass integer arrays and get the decimal number using bit operator.
The following is what I tried but does not work when I tried to pass int arrays, it works with char* array. Is there any way that I can pass int arrays and convert it to decimal number? I want to use bit operator.
int toInt(int* bin_arr) {
int val = 0;
while (*bin_arr)
val = (val << 1) | (*bin_arr++ == '1');
return val;
}
Thanks in advance.
Your loop condition assumes that the array is 0-terminated, which is valid for strings, but not integer arrays. One way to fix this would be to pass a length parameter along with the int pointer, so you know when to stop iterating.
Also, in this expression:
(*bin_arr++ == '1')
you should remove the single quotes, if you're passing integers rather than characters.
I would like to copy the contents of a char array to int variables or an array. For example, the first five values have to go to an int array (int x):
char a[] = "123456";
I saw in other threads that to change a char to an int, I need to do this:
int x = a[0] - '0';
Is there other ways of doing it?
What if I wanted to the values in groups of two or more, such as 12, 34 and 56?
And what if I didn't what to save them as ints, but floats or other types instead?
Copy properly sized portions of the string to a separate buffer and use strtol() or strtod().
You are on write track, however if you want to convert into integer array then you
should use something like
int x[MAX_ELEM];
for(int i =0; i<sizeof(a)/sizeof(char); i++)
{
x[i] = a[i] -'0';
}
For other cases you will need to deal separately.
The reason you have to do int x = a[0] - '0'; is because of the character encoding in C. What is happening is you are subtracting the encoding offset from the character. Here is a table with all the encoding values: UTF-8 encodings. So int x = a[0] - '0'; is equivalent in your case to int x = 49 - 48; which has the correct value you were looking for. By using '0' instead of 0 you are using the char value of 0.
There are other ways of doing it, but this way works well. To use other types, just do type casting after you create the int.
John's way of getting two digit numbers works well. Reposted here, it was number = 10 * digit1 + digit2.
To answer your questions:
Sure, there are other ways of doing it. The way you've shown converts the ASCII value to the digit it represents, but there are other ways.
Read in the number of characters you want, convert each character to a digit, and construct the integer from those digits like number = 10 * digit1 + digit2.
Do type casting after you construct the integers.