This is my program to convert a binary to a decimal value.
#include <stdio.h>
#include <string.h>
#include <math.h>
void con(){
unsigned long long int dec = 0, bin;
int i;
printf ("\n Binary : ");
scanf("%lld",&bin);
for (i = strlen(bin) - 1; i <= 0; --i){ // Warning in here
dec = dec + (bin[i] * pow (2, i)); // Error in here
}
printf(" Decimal : %lld",dec);
con();
}
int main(){
con();
return 0;
}
When i compile the code, this error shows up ," Subscripted value is neither array nor pointer nor vector". And this warning also ," Passing argument 1 of strlen makes pointer from integer without a cast".
Why am i getting these and how can i fix them?
There are a number of problems with your code.
Most important is the variable bin. You probably want it to be a string like "1001001001" but you define it as unsigned long long int. Instead you should do:
char bin[100];
scanf("%s", bin); // Note: Not recommended! Use fgets instead.
Here scanf is not recommended as the user may overflow your buffer. Please use fgets instead.
As suggested by #MayurK: If you want to use scanf then at least do:
scanf("%99s", bin);
to prevent buffer from overflow.
Then this part:
dec = dec + (bin[i] * pow (2, i));
is wrong as bin[i] is not a number but a char.
You could do:
dec = 2 * dec + (bin[i] - '0'); // Note: No error checks which is bad
It will work as long as the user only inputs 0 and 1. In real code you should check that the user actually did so.
Finally you should not call con at the end of the function as it will give an endless loop. So delete that call:
printf(" Decimal : %lld",dec);
// DELETE THIS con();
}
dec = dec + (bin[i] * pow (2, i)); //bin is a numeric type
In this line you are trying to use a variable of unsigned long long type as array. Every numeric type is taken as a full value, you can't use array indexing to access separate digits. If you want to use it as a array use a char* or character array.
And you are also passing a unsigned long long to strlen(const char * str) function.
Related
I'm trying to convert a hexadecimal INT to a char so I could convert it into a binary to count the number of ones in it. Here's my function to convert it into char:
#include <stdio.h>
#include <stdlib.h>
#define shift(a) a=a<<5
#define parity_even(a) a = a+0x11
#define add_msb(a) a = a + 8000
void count_ones(int hex){
char *s = malloc(2);
sprintf(s, "0x%x", hex);
free(s);
printf("%x", s);
};
int main() {
int a = 0x01B9;
shift(a);
parity_even(a);
count_ones(a);
return 0;
}
Every time I run this, i always get different outputs but the first three hex number are always the same. Example of outputs:
8c0ba2a0
fc3b92a0
4500a2a0
d27e82a0
c15d62a0
What exactly is happening here? I allocated 2 bytes for the char since my hex int is 2 bytes.
It's too long to write a comment so here goes:
I'm trying to convert a hexadecimal INT
int are stored as a group of value, padding (possible empty) and sign bits, so is there no such thing as a hexadecimal INT but you can represent (print) a given number in the hexadecimal format.
convert a ... INT to a char
That would be lossy conversion as an int might have 4 bytes of data that you are trying to cram into a 1 byte. char specifically may be signed or unsigned. You probably mean string (generic term) or char [] (standard way to represent a string in C).
binary to count the number of ones
That's the real issue you are trying to solve and this is a duplicate of:
How to count the number of set bits in a 32-bit integer?
count number of ones in a given integer using only << >> + | & ^ ~ ! =
To address the question you ask:
Need to allocate more than 2 bytes. Specifically ceil(log16(hex)) + 2 (for 0x) + 1 (for trailing '\0').
One way to get the size is to just ask snprintf(s, 0, ...)
then allocate a suitable array via malloc (see first implementation below) or use stack allocated variable length array (VLA).
You can use INT_MAX instead of hex to get an upper
bound. log16(INT_MAX) <= CHAR_BIT * sizeof(int) / 4 and the
latter is a compile time constant. This means you can allocate your string on stack (see 2nd implementation below).
It's undefined behavior to use a variable after it's deallocated. Move free() to after the last use.
Here is one of the dynamic versions mentioned above:
void count_ones(unsigned hex) {
char *s = NULL;
size_t n = snprintf(s, 0, "0x%x", hex) + 1;
s = malloc(n);
if(!s) return; // memory could not be allocated
snprintf(s, n, "0x%x", hex);
printf("%s (size = %zu)", s, n);
free(s);
};
Note, I initialized s to NULL which would cause the first call to snprintf() to return an undefined value on SUSv2 (legacy). It's well defined on c99 and later. The output is:
0x3731 (size = 7)
And the compile-time version using a fixed upper bound:
#include <limits.h>
// compile-time
void count_ones(unsigned hex) {
char s[BIT_CHAR * sizeof(int) / 4 + 3];
sprintf(s, "0x%x", hex);
printf("%s (size = %zu)", s, n);
};
and the output is:
0x3731 (size = 11)
Your biggest problem is that malloc isn't allocating enough. As Barmar said, you need at least 7 bytes to store it or you could calculate the amount needed. Another problem is that you are freeing it and then using it. It is only one line after the free that you use it again, which shouldn't have anything bad happen like 99.9% of the time, but you should always free after you know you are done using it.
I am learning C in school, and I am having a little difficulty on my project.
Basically, I am writing a function that gets a string containing a positive integer. The function subtracts 1 from that integer and puts the obtained value in the string.
So , if I have this ;
char nums[] = "2462";
how do I write a function that will subtract 1 from the integer, so that the result is "2461"??
First, convert the character array into an integer.
You can use atoi (ASCII to Integer), but because it returns 0 on error there's no way to tell the difference between successfully converting "0" and an error.
Instead use strtol (STRing TO Long integer).
// end stores where parsing stopped.
char *end;
// Convert nums as a base 10 integer.
// Store where the parsing stopped in end.
long as_long = strtol(nums, &end, 10);
// If parsing failed, end will point to the start of the string.
if (nums == end) {
perror("Parsing nums failed");
}
Now you can subtract, turn the integer back into a string with sprintf, and put it in nums.
sprintf(nums, "%ld", as_long - 1);
This is not entirely safe. Consider if nums is "0". It only has 1 byte of space. If we subtract 1 then we have "-1" and we're storing 2 characters where we only have memory for 1.
For the full explanation of how to do this safely, see How to convert an int to string in C?.
Alternatively, don't store it, just print it.
printf("%ld", as_long - 1);
One way is to convert string -> int -> string.
You can do this by using atoi and sprintf.
Simple implementation (far from perfect):
#include <stdlib.h>
#include <stdio.h>
int main()
{
int a;
char b[5];
a = atoi("2462");
a--;
sprintf(b, "%d", a);
printf("%s\n", b);
return 1;
}
I want to extract a number from an array I introduce in the keyboard and convert it into one integer. My code is:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int r, t, i;
char expressio[t];
char vector[50];
char rpn[t][4];
printf("Introduce the expresssion");
fgets(expressio, t, stdin);
t = strlen(expressio);
for (i = 0; i <= t; i++) {
if (isdigit(expressio[i])) {
r = atoi(expressio[i]);
vector[i] = rpn[0][r];
}
return 0;
}
}
I have this warning:
passing argument 1 of 'atoi' makes pointer from integer without a cast
How can i solve it?
Also, when I execute this program, it does nothing and it doesn't even print the "Introduce the expression". Why is this happening?
That warning means that you are passing a bad argument to the function. "atoi" is expecting an array of chars as argument, but you are passing a single char as argument here:
r = atoi(expressio[i]);
If you want to convert a single char into a number, you can do:
r = expressio[i] - '0';
If you look at the ascii table, you will notice that the ascii value of 0 is 48. If you substract 48 (or, like i did, the ascii value of 0) to your char expressio[i], you will get the corresponding number as an integer. Like this, if expressio[i] equals '8', then r will equal 8.
I have different hexadecimal data are coming and stored into an integer type register.
When I use fprint I can see the following:
0x3076
0x307c
.
.
.
However, I would like to show a Decimal version of above-mention Hex data as follows.
12406
12412
.
.
.
In theory, let's say for the first value you do the following to convert it to decimal.
(6* 16^0)+(7 * 16^1)+(0*16^2)+(3*16^3)=6 + 112+ 0 + 12288 = 12406
So IF I have the character-based version of "0x3076" and also, IF I am able to get each single characters 6 - 7 - 0 - 3, I can calculate the decimal amount!
So, I decided to divide "3076" by 1000. I was expected to get 3, but I got TWO characters instead! however, if I was able to get 3 for the remainder of "307c" I am not able to get "C". If it was decimal this might work not hex!
Also, I tried "strtol" command. As I use Cygwin to compile my code, I am not sure where the error is! What did I do wrong?
So, I just need to find a way to get EACH SINGLE character out of the HEX data!
Any idea please?
P.S.
Here is my code in order to help you to give me an idea.
int get_readings(int source, int phase, int max_tries)
{
uint8_t buf[MAX_IEC1107_MSG_BODY];
uint8_t inbuf[MAX_IEC1107_MSG_BODY];
int inlen;
uint8_t *s;
int32_t value;
int status;
double voltage;
double current;
double active_power;
double reactive_power;
double apparent_power;
double power_factor;
double frequency;
s = buf;
*s++ = HOST_CMD_GET_READINGS_PHASE_1 + phase;
*s++ = 0x00;
if (max_tries != 1)
meter_set_max_tries(&emeter[source].meter_msg, max_tries);
if (meter_exchange(&emeter[source].meter_msg, buf, 2, inbuf, &inlen)
&&
inbuf[1] != 0xFF)
{
emeter[source].no_response = FALSE;
s = inbuf;
/* Get current readings */
value = (s[3] << 8) | s[2];
fprint(stderr, "value:" %p\n, value); // this give me HEX code
.
.
.
When reading in a string representing a number in hexadecimal, use strtol() to convert it to a long. Then if you want to print the number in decimal, use printf() with a %d format specifier.
char num[]="0x3076";
long n = strtol(num, NULL, 16);
printf("n=%ld\n", n); // prints 12406
Once you read in the strings as longs using strtol and operate on the longs, the math should work itself out.
unsigned n;
sscanf("0x3076", "%x", &n);
printf("%u\n", n);
Only with the following line I could solve the issue!
fprintf(stderr, "Voltage: %.2f\n", value/100.00);
value was shown as HEX as I used to use %p! Then I changed to x! and as I need to have 124.06 not 12406, in other words 2 decimal points, I added .2f!
Thank you all!
1) for printing only:
#include <stdio.h>
#include <stdlib.h>
int main(){
int a=0;
scanf("%x",&a);
printf("%d\n",a);
system("pause");
return 0;
}
2) for calculation use:
#include<stdio.h>
#include<stdlib.h>
int CharToDec(char c){
if(c>='0' && c<='9') return c-'0';
if(c>='a' && c<='f') return c-'a'+10;
if(c>='A' && c<='F') return c-'A'+10;
return 0;
}
int main(int argc, char *argv[]){
char H[10];
char *P;
int p=1,d=0;
printf("Entrez Hexadecimale nombre:");
scanf("%s",H);
for(P=H;*P;P++);
for(P--;P>=H;P--){
d = d + (CharToDec(*P) * p);
p = p*16;
}
printf("%d\n",d);
system("pause");
return 0
}
You are confusing "integer" and "decimal" -- an "integer" is a number stored in a register or variable, while a "decimal" is a string of characters that represent a number in base 10.
So converting from hexadecimal to decimal is a two-step process. You first convert the hexadecimal to integer (which you appear to have done, with your "In theory" equation). You then convert the integer to decimal.
There are lots of ways to do either of these tasks, strtol and scanf will convert either hexadecimal or decimal to integer. printf can convert integer to either hexedecimal or decimal. Or you can write your own routines that manipulate characters to do either of these things.
I have a pointer lpBegin pointing to a string "1234". Now i want this string compare to an uint how can i make this string to unsigned integer without using scanf? I know the string number is 4 characters long.
You will have to use the atoi function. This takes a pointer to a char and returns an int.
const char *str = "1234";
int res = atoi(str); //do something with res
As said by others and something I didn't know, is that atoi is not recommended because it is undefined what happens when a formatting error occurs. So better use strtoul as others have suggested.
Definitely atoi() which is easy to use.
Don't forget to include stdlib.h.
You can use the strtoul() function. strtoul stands for "String to unsigned long":
#include <stdio.h>
#include <stdlib.h>
int main()
{
char lpBegin[] = "1234";
unsigned long val = strtoul(lpBegin, NULL, 10);
printf("The integer is %ul.", val);
return 0;
}
You can find more information here: http://www.cplusplus.com/reference/clibrary/cstdlib/strtoul/
You could use strtoul(lpBegin), but this only works with zero-terminated strings.
If you don't want to use stdlib for whatever reason and you're absolutely sure about the target system(s), you could do the number conversion manually.
This one should work on most systems as long as they are using single byte encoding (e.g. Latin, ISO-8859-1, EBCDIC). To make it work with UTF-16, just replace the 'char' with 'wchar_t' (or whatever you need).
unsigned long sum = (lpbegin[0] - '0') * 1000 +
(lpbegin[1] - '0') * 100 +
(lpbegin[2] - '0') * 10 +
(lpbegin[3] - '0');
or for numbers with unknown length:
char* c = lpBegin;
unsigned long sum = 0;
while (*c >= '0' && *c <= '9') {
sum *= 10;
sum += *c - '0';
++c;
}
I think you look for atoi()
http://www.elook.org/programming/c/atoi.html
strtol is better than atoi with better error handling.
You should use the strtoul function, "string to unsigned long". It is found in stdlib.h and has the following prototype:
unsigned long int strtoul (const char * restrict nptr,
char ** restrict endptr,
int base);
nptr is the character string.
endptr is an optional parameter giving the location of where the function stopped reading valid numbers. If you aren't interested of this, pass NULL in this parameter.
base is the number format you expect the string to be in. In other words, 10 for decimal, 16 for hex, 2 for binary and so on.
Example:
#include <stdlib.h>
#include <stdio.h>
int main()
{
const char str[] = "1234random rubbish";
unsigned int i;
const char* endptr;
i = strtoul(str,
(char**)&endptr,
10);
printf("Integer: %u\n", i);
printf("Function stopped when it found: %s\n", endptr);
getchar();
return 0;
}
Regarding atoi().
atoi() internally just calls strtoul with base 10. atoi() is however not recommended, since the C standard does not define what happens when atoi() encounters a format error: atoi() can then possibly crash. It is therefore better practice to always use strtoul() (and the other similar strto... functions).
If you're really certain the string is 4 digits long, and don't want to use any library function (for whatever reason), you can hardcode it:
const char *lpBegin = "1234";
const unsigned int lpInt = 1000 * (lpBegin[0] - '0') +
100 * (lpBegin[1] - '0') +
10 * (lpBegin[2] - '0') +
1 (lpBegin[3] - '0');
Of course, using e.g. strtoul() is vastly superior so if you have the library available, use it.