Way to scanf binary number? - c

I am trying to write a small bit of code where i can scan a binary digit, like 00110011, and get this into an integer as a number. So 00110011 would be 51.
The code i made for this goes like this
int main()
{
unsigned char byte;
int d;
scanf("%8s", &byte);
d = byte;
printf("%d,%c",d, byte);
return 0;
}
This however, give me an output of 48. 00000001 also gives me 48 and so does anything else.
I know whats going wrong, it sees the string of zeros and ones as a single 0 and since its character is 0x30, or 0d48, it outputs 48. I wont to know if there is a way to get around this adn scan this in as the binary equivelent.

Your code does not work at all:
you scan up to 8 characters plus a null terminator, passing the address of a single byte variable: this has undefined behavior.
d = byte does not perform any conversion. the character '0' was read into byte and its ASCII value is stored into d, namely 48 as output by your program.
Furthermore, there is no standard conversion specifier for binary encoding in scanf(). Reading a string is a good approach, but you should pass a larger buffer and use a loop to convert to binary:
#include <ctype.h>
#include <stdio.h>
int main() {
char buf[100];
/* read a sequence of at most 99 binary digits into buf */
if (scanf(" %99[01]", buf) == 1) {
unsigned int d = 0;
/* convert the binary digits one at a time into integer d */
for (int i = 0; buf[i]; i++) {
d = (d << 1) | (buf[i] - '0');
}
/* print value as a number */
printf("%s -> %d\n", buf, d);
if (d == (unsigned char)d && isprint(d)) {
/* print value as a character if printable */
printf("%s -> %c\n", buf, d);
}
}
return 0;
}
You can also use strtoul() to convert a number expressed as a string of binary digits (or in any other base up to 36):
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char buf[100];
/* read a sequence of at most 99 binary digits into buf */
if (scanf(" %99[01]", buf) == 1) {
unsigned long d = strtoul(buf, NULL, 2);
/* print value as a number */
printf("%s -> %lu\n", buf, d);
if (d == (unsigned char)d && isprint((unsigned char)d)) {
/* print value as a character if printable */
printf("%s -> %c\n", buf, (unsigned char)d);
}
}
return 0;
}
Note however that the behavior of strtoul() will differ from the first code: strtoul() will return ULONG_MAX on overflow, whereas the first example would just compute the low order bits of the binary string.

I found this simple function that should be easy to understand and it does the trick. Its a algorithm that follows how you would naturally do it in real life with a pen and paper however you're gonna need -lm when you compile it(the gcc command) to include the math library, however you can get around the pow() and include problems if you just do a for loop.
#include <stdio.h>
#include <math.h>
int todecimal(long bno){
int dno = 0, i = 0, rem;
while (bno != 0) {
rem = bno % 10;
bno /= 10;
dno += rem * pow(2, i);
++i;
}
return dno;
}

Related

Repetition code in C isn't working for large numbers

I'm writing a code in C to find the digits that repeat in a given number, and the one that I wrote works fine for small numbers, but the output gets messed up if I input a large value, N < 1000.
Here is my code; please help me out!
For the input:
1839138012980192380192381090981839
I get this output:
0 2 3 5 7 8
#include <stdio.h>
int main()
{
int digit, digits[10], flag = 0, i;
long long num;
scanf("%lld", &num);
while (num)
{
digit = num % 10;
if (digits[digit])
flag = 1;
digits[digit]++;
num /= 10;
}
if (flag)
{
for (i = 0; i < 10; i++)
{
if (digits[i] > 1)
printf("%d ", i);
}
printf("\n");
}
else
printf("The are no repeated digits.\n");
return 0;
}
The long long type can only represent a limited range of numbers. In your C implementation, 1839138012980192380192381090981839 is too big for long long, and scanf("%lld", &num) does not work.
Instead, read each character of input using c = getchar();, where c is declared as an int. If, after getchar, c is EOF, stop looping and print the results. If c is not EOF, then check whether it is a digit using if (isdigit((unsigned char) c)). The isdigit function is defined in <ctype.h>, so include that header.
If the character is a digit, then convert it from a character to the number it represents using c - '0'. You can use int d = c - '0'; to store the number in d. Then increment the count for the digit d.
If the character is not a digit, you can decide what to do:
There will likely be a new-line character, '\n', at the end of the line the user entered. You may want to ignore it. When you see the new-line, you could end the loop and print the results, you could continue reading to see if there are any other digits or characters before EOF is seen and report a problem to the user if there are, or you could ignore it and continue looping.
There could be spaces in the input. You might want to ignore them, or you might want to report a problem to the user.
If there are other characters, you might want to report a problem to the user.
Here's another approach, which you could use with a string of some maximum length (defined by the constant MAX_LEN).
A string made up of a bunch of char will use one byte per character, so you can define MAX_LEN up to how many bytes you have in system memory, generally, although in practice you probably would use a much smaller and more reasonable number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 12345
int main()
{
int digit, digits_checker[10] = {0}, flag = 0, i;
char* num;
/* set aside space for the string and its terminator */
num = malloc(MAX_LEN + 1);
/* read num from input */
scanf("%s", num);
/* get the string length */
size_t num_length = strlen(num);
/* walk over every character in num */
for (size_t position = 0; position < num_length; position++)
{
/*
We assume that the value of num[position] is an
ASCII character, from '0' to '9'. (If you can't make
that assumption, check the input and quit with an
error, if a non-digit character is found.)
If the input is valid, the digits 0-9 in the ASCII
table start at 48 ('0') and end at 57 ('9'). Subtracting
48, therefore, gives you the integer value at each digit
in num.
*/
digit = num[position] - 48;
/*
Increment a counter for each digit
*/
digits_checker[digit]++;
}
/* num is no longer needed, so we free its memory */
free(num);
/* check each digit */
for (i = 0; i < 10; i++)
{
if (digits_checker[i] > 1) {
printf("%d ", i);
flag = 1;
}
}
if (!flag) {
printf("The are no repeated digits.\n");
}
else {
printf("\n");
}
return 0;
}
The suggestion to check input is a good one. You can't necessarily assume that what someone enters will be entirely made up of digit characters.
But hopefully this demonstrates how to set aside space for a string, and how to read through it, one character at a time.

working with methods to take in strings in C

I'm new to C and am having a lot of issues with arrays that keeps coming up. I'm trying to write a method that takes in a string ("1234") and returns the odd digits, however it keeps printing 49 and I don't know why? Does it have something to do with how I'm assigning the arrays?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int print_odd_digits(char number[100]) {
int size = sizeof(number[100]);
for (int i = 0; i < size; i++) {
if (number[i] % 2 == 1) {
printf("%d\n", number[i]);
}
}
return 0;
}
int main(void) {
print_odd_digits("1234");
}
sizeof(number[100]) is equivalent to sizeof(char), which is 1. What you want seems strlen(number).
Elements of number are not values of digits but character codes of digits. To convert number characters to values, you can subtract '0'. (character codes for 0 to 9 are defined to be continuous in C).
%d is for printing integer and 49 is ASCII code for the character 1. Use %c to print character corresponding to passed integer.
You may want newline only on end of the characters.
Try this:
#include <stdio.h>
#include <string.h> /* for using strlen() */
int print_odd_digits(char number[100]) {
int size = strlen(number);
for(int i = 0; i < size; i++){
if((number[i] - '0') % 2 == 1){
printf("%c",number[i]);
}
}
printf("\n");
return 0;
}
int main(void) {
print_odd_digits("1234");
}
You have a type error here. You are working with the ascii codes for the text characters for digits. You need to use the atoi(char* str)
function to convert the digits to a corresponding number and use math to determine a particular digit or loop over the characters and subtract -'0' the ascii code for the digit zero as digits are sequential.
#include <stdlib.h>
#include <stdio.h>
int main() {
char* digit_one_str = "1";
char digit_9 = '9';
printf("digit one ascii value: %d\n", digit_one_str[0]); // first char in string digit one
int number_one = atoi(digit_one_str);
printf("digit one parsed from sttring by atoi: %d\n", number_one);
printf("digit 9 as char converted with -'0' trick: %d", (int)(digit_9 - '0'));
}
Further it is better practice to take in a char* and a length than to work with fixed sized arrays or using strlen() where you don't actually have to. In C a string ends in a terminating '\0' character which might not even be present if the code calling your function is buggy or malicious.

How to convert int into char* in C (without sprintf)

some day, i wanted to convert in C an integer into a char *, this int can be negative.
I wasn't able to use sprintf ,snprintf neither, so how do i do that ?
To roll one's own itoa()-like function, first one must address how to handle memory. The easiest is to use a large-enough memory for all possible int values (INT_MIN).
The buffer required size is mathematically ceiling(log10(-INT_MIN))+3. This can be approximated with:
#include <limits.h>
#define INT_STR_SIZE (sizeof(int)*CHAR_BIT/3 + 3)
Then build the digits up one-by-one starting with the least significant digit using %10 and then /10 to reduce the value.
By using a do loop, code catches the corner case of x==0 as at least one digit is made.
This code avoids if (x < 0) { x = -x; ... as negating INT_MIN (or multiplying by -1 leads to int overflow, which is UB.
#include <limits.h>
#define INT_STR_SIZE (sizeof(int)*CHAR_BIT/3 + 3)
char *my_itoa(char *dest, size_t size, int x) {
char buf[INT_STR_SIZE];
char *p = &buf[INT_STR_SIZE - 1];
*p = '\0';
int i = x;
do {
*(--p) = abs(i%10) + '0';
i /= 10;
} while (i);
if (x < 0) {
*(--p) = '-';
}
size_t len = (size_t) (&buf[INT_STR_SIZE] - p);
if (len > size) {
return NULL; // Not enough room
}
return memcpy(dest, p, len);
}
With C99 or later, code can handle the buffer creation with a compound literal allowing separate buffers for each mt_itoa() call.
// compound literal C99 or later
#define MY_ITOA(x) my_itoa((char [INT_STR_SIZE]){""}, INT_STR_SIZE, x)
int main(void) {
printf("%s %s %s %s\n", MY_ITOA(INT_MIN), MY_ITOA(-1), MY_ITOA(0), MY_ITOA(INT_MAX));
return (0);
}
Output
-2147483648 -1 0 2147483647
to convert from integer to char* use the function itoa().
/* itoa example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i;
char buffer [33];
printf ("Enter a number: ");
scanf ("%d",&i);
itoa (i,buffer,10);
printf ("decimal: %s\n",buffer);
itoa (i,buffer,16);
printf ("hexadecimal: %s\n",buffer);
itoa (i,buffer,2);
printf ("binary: %s\n",buffer);
return 0;
}

Error in implementing a basic string to integer converter

I am writing a basic C program which will take the input of a string, then convert it to an integer. I am aware of the standard atoi() function, this is purely an exercise I set myself. The code for the program is as follows:
#include <stdio.h>
#include <string.h>
int main (void) {
char input[20];
int counter, temp, magnitude = 0, value = 0;
scanf("%s", input); //takes user input for string to convert
for (counter = strlen(input); counter >= 0; counter--) { //from last to first char of input
temp = input[counter] - '0'; //converts from ASCII to actual value and stores in int
value += temp * magnitude * 10; //temp to correct magnitude and adds to total
magnitude++; //increments magnitude counter
}
printf("%d\n", value); //prints result
return 0;
}
I am trying to iterate backwards from the end of the string, then convert each character to it's actual value from ASCII, then convert it to the correct magnitude, before finally adding it to the final value. It is giving me values which are generally close although wrong.
For example 256 gives 220 and 90 gives 180.
You have two problems. Firstly, you're also trying to convert the terminating NUL byte, which doesn't make sense. Start iterating at strlen(input) - 1.
Second, for the magnitude you want to exponentiate, not multiply, i.e. 10, 100, 1000 rather than 10, 20, 30. For this, you can use pow(), for example:
for (counter = strlen(input) - 1; counter >= 0; counter--) { //from last to first char of input
temp = input[counter] - '0'; //converts from ASCII to actual value and stores in int
value += temp * pow(10, magnitude); //temp to correct magnitude and adds to total
magnitude++; //increments magnitude counter
}
counter = strlen(input)
should be
counter = strlen(input) - 1
so you're using the last valid character of the string.
Two problems here.
1) You should ignore the string null-terminator, so going from strlen(input)-1 will do
2) Your calculation is wrong. You should not multiply by magnitude, but raise 10 to it's power. Or simpler, it itself the required 10's power:
#include <stdio.h>
#include <string.h>
int main (void) {
char input[20];
int counter, temp, magnitude = 1, value = 0;
scanf("%s", input); //takes user input for string to convert
for (counter = strlen(input)-1; counter >= 0; counter--) { //from last to first char of input
temp = input[counter] - '0'; //converts from ASCII to actual value and stores in int
value += temp * magnitude ; //temp to correct magnitude and adds to total
magnitude*=10; //increments magnitude counter
}
printf("%d\n", value); //prints result
return 0;
}
strlen gives the total length of the string. So you have to use
counter = strlen(input)-1
In your for loop. This is because arrays in C start from 0 and end at strlen -1.
While your approach should work (after the issues noted in other answers have been fixed, anyway), it's probably simpler to take this approach:
value = 0;
for (char *p = input; *p; ++p)
value = value * 10 + (*p - '0');
That eliminates a couple unnecessary extra variables, and is probably a bit more efficient. It might not hurt to change the for loop termination condition to *p && isdigit(*p) - that would terminate the conversion on the first non-digit character seen, which might be a desirable approach for dealing with invalid input...
here is a complete answer,
that includes good programming paradigm practices
and defensive coding against user input problems
and results in the right answer
#include <stdio.h> // fgets(), exit(), printf()
#include <stdlib.h> // EXIT_FAILURE, perror()
#include <string.h> // strlen()
#include <ctype.h> // isdigit()
int main () // <-- do not use void
{
char input[20] = {'\0'};
int counter; // index into input array
int value = 0; // initialize the converted int from string
if( NULL != fgets(input, sizeof(input), stdin) )
{ // fgets failed
perror( "fgets failed for string input");
exit( EXIT_FAILURE );
}
// implied else, fgets successful
// note no need to replace trailing '\n' in following code block
for( counter=0; isdigit(input[counter]); counter++)
{
value = value*10 + (input[counter]-'0');
} // end for
printf("the converted value from %s is: %d\n", input, value); //prints result
return 0;
} // end function: main

Addition of numbers from string delimited by ' . '

I want to write a C program which will take an IP address from the user like "112.234.456.789" in a string and give formatted output in addition of each block in string, e.g., "04.09.15.24" for the above IP address. Here's what I have so far:
#include<stdio.h>
#include<string.h>
#include<conio.h>
main()
{
char s[15],d[11];
int i=0,c = 0, sum[4] = {0};
d[i]=sum[c]/10;
printf("Enter ip address:");
gets(s);
printf("\n \n %s",s);
i=0;
for(c=0;c<15;c++)
{
if(s[c]!='.'||s[c]!='\0')
sum[i]=(s[c]-48)+sum[i];
else
i++;
}
for(i=0,c=0;c<4;c++,i+=3)
{
d[i]=(sum[c]/10)+48;
d[i+1]=sum[c]%10+48;
d[i+2]='.';
}
printf("\n \n %s",d);
getch();
}
The input should be an IP address like "112.234.546.234", and the output should be the result of adding the digits in each block, "04.09.15.06". The input and output should be in strings.
The problem with your code is that s[c]!='.'||s[c]!='\0' is going to evaluate true for any character in the input -- even '.'. This means i is never incremented, and ot only is every digit is summed to sum[0], but so is '.' - 48.
What you meant was s[c] != '.' && s[c] != '\0'.
I wrote the function you desire here.
#include <stdio.h>
#include <ctype.h>
void convert(const char *in, char *out) {
unsigned int sum = 0;
char ch;
do {
ch = *in++;
if (isdigit(ch)) {
sum += ch - '0';
} else {
*out++ = sum / 10 + '0';
*out++ = sum % 10 + '0';
if (ch == '.') {
*out++ = '.';
sum = 0;
}
}
} while (ch);
}
By the way, each "block" of the IPv4 address is an octet, and what you are doing is replacing each with its digit sum.
I just code you a simple example of how to "discard" unwanted characters.
#include <studio.h>
main ()
{
int add1, add2, add3, add4;
printf("enter an ip in the form xxx.xxx.xxx.xxx: )";
scanf("%d%*c%d%*c%d%*c%d", &add1, &add2, &add3, &add4);
printf("add1 = %d add2 = %d add3 = %d add4 = %d\n\n", add1, add2, add3, add4);
return 0;
}
console output:
enter a ip in the form xxx.xxx.xxx.xxx: 123.321.456.654
add1 = 123 add2 = 321 add3 = 456 add4 = 654
EDIT: you just have to play along with the "add#" variables to do your math thing.
It looks like homework (if this is the case, please tag it as homework), so I am going to give a few pointers:
Use fgets to read the input from the user. Read the input into a string.
Use sscanf to parse the string. Since you know there will be four positive integers, use "%u.%u.%u.%u" as the format string.
For each one of the four integers, compute the sum of the digits (using division by 10 and remainder by 10, as you just did).
Print the formatted output using printf (or snprintf to print to a string). If you want each sum to be formatted as a two-digits integer, with leading 0, use "%02u" as format specifier.
P.S. Be careful with snprintf, it might bite.
Other tips
Focus on one step at a time. Divide and conquer. Write a digit_sum function, taking an integer as argument, which computes the sum of its digits:
unsigned int digit_sum(unsigned int n)
{
unsigned int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
Once your digit_sum function is working well, proceed with the main task.

Resources