So a bit ago I was warming up and doing some very simple challenges. I came across one on edabit where you need to make a function to add the digits of a number and tell if the resulting number is "Oddish" or "Evenish"
(ie oddishOrEvenish(12) -> "Oddish" because 1 + 2 = 3 and 3 is odd)
so I solved it with some simple code
# include <stdio.h>
# include <stdlib.h>
char* odOrEv(int num);
int main(int argc, char* argv[]) {
printf("%s", odOrEv(12));
}
char* odOrEv(int num) {
char* strnum = (char*) malloc(11);
char* tempchar = (char*) malloc(2); // ik i can declare on one line but this is neater
int total = 0;
sprintf(strnum, "%d", num);
for (int i = 0; i < sizeof strnum; i++) {
tempchar[0] = strnum[i];
total += (int) strtol(tempchar, (char**) NULL, 10);
}
if (total % 2 == 0) return "Evenish";
return "Oddish";
}
and it worked first try! Pretty rudimentary but I did it. i then thought hey this is fun howabout I make it better, so I got it down to
# include "includes.h"
char* odOrEv(int num);
int main(int argc, char* argv[]) {
printf("%s", odOrEv(13));
}
char* odOrEv(int num) {
char* strnum = (char*) malloc(11);
int total = 0;
sprintf(strnum, "%d", num);
while (*strnum) total += (int) *strnum++;
return total % 2 == 0 ? "Evenish" : "Oddish";
}
just 5 lines for the function. Since I'm so pedantic though, I hate that I have to define strnum on a different line than declaring it since I use sprintf. I've tried searching, but I couldn't find any functions to convert int to string that I could use while declaring the string (e.x. char* strnum = int2str(num);). So is there any way to cut off that one line?
srry if this was too big just tried to explain everything
P.S. don't tell to use atoi() or stoi or any of those since they bad (big reason long to eplain) also I'd prefer if I didn't have to include any more directories but it's fine if I do
EDIT: forgot quote added it
To be honest it the one of the weirdest functions I have ever seen in my life.
You do not need strings, dynamic allocations and monster functions like sprintf or strtol.
char* odOrEv(int num)
{
int sum = 0;
while(num)
{
sum += num % 10;
num /= 10;
}
return sum % 2 == 0 ? "Evenish" : "Oddish";
}
You don't actually have to add the digits. The sum of even digits is always even, so you can ignore them. The sum of an odd number of odd digits is odd, the sum of an even number of odd digits is even. So just loop through the digits, alternating between oddish and evenish every time you see an odd digit.
You can loop through the digits by dividing the number by 10 and then checking whether the number is odd or even.
char *OddorEven(int num) {
int isOdd = 0;
while (num != 0) {
if (num % 2 != 0) {
isOdd = !isOdd;
}
num /= 10;
}
return isOdd ? "Oddish" : "Evenish";
}
Related
I'm passing almost all leetCode tests with this, but not understanding why the output is wrong ("/0") when the input is:
a = "10100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101"
b = "110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011"
Anyone has an idea to what is not working ?
Thanks
#include <stdio.h>
#include <stdlib.h>
char * sumBinary(long int binary1, long int binary2, char * result);
char * addBinary(char * a, char * b)
{
char * result;
long int a_int;
long int b_int;
a_int = atoi(a);
b_int = atoi(b);
result = malloc(sizeof(*result) * 1000);
if (!result)
return (NULL);
sumBinary(a_int, b_int, result);
return (result);
}
char * sumBinary(long int binary1, long int binary2, char * result)
{
int i;
int t;
int rem;
int sum[1000];
i = 0;
t = 0;
rem = 0;
if ((binary1 == 0) && (binary2 == 0))
{
result[0] = '0';
result[1] = '\0';
}
else
{
while (binary1 != 0 || binary2 != 0)
{
sum[i++] = (binary1 %10 + binary2 % 10 + rem) % 2;
rem = (binary1 %10 + binary2 % 10 + rem) / 2;
binary1 = binary1 / 10;
binary2 = binary2 / 10;
}
if (rem != 0)
sum[i++] = rem;
--i;
while (i >= 0)
{
result[t] = sum[i] + '0';
t++;
i--;
}
result[t] = '\0';
}
return (result);
}
For a start, you should be using atol(3), not atoi(3) if you're using long int. But that's not the main issue here.
atol(3) and atoi(3) expect strings containing decimal numbers, not binary, so that's not going to work well for you. You would need strtol(3), which you can tell to expect a string in ASCII binary. But again, this is not the main issue.
You don't give the question text, but I'm guessing they want you to add two arbitrarily-long ASCII-binary strings, resulting in an ASCII-binary string.
I imagine their expectation, given it's arbitrarily-long, is that you would be working entirely in the string domain. So you'd allocate for a string whose length is two greater than the longer of the two you get as parameters (+1 for the terminal NUL, the other +1 for a potential overflow digit).
Then you start from the end, working back to the start, adding the corresponding digits of the parameter strings, placing the results into the result string starting from its end (allowing for that terminal NUL), adding as if you were doing it by hand.
Don't forget to add a leading zero to the result string, if you don't overflow into that position.
Note that I'm not going to write the code for you. This is either a learning exercise or a test: either way, you need to do the coding so you can learn from it.
As a C fresher, I am trying to write a recursive routine to convert a decimal number to the equivalent binary. However, the resultant string is not correct in the output. I think it has to be related to the Type casting from int to char. Not able to find a satisfactory solution. Can anyone help? Thanx in advance.
Code:
#include <stdio.h>
#include <conio.h>
int decimal, counter=0;
char* binary_string = (char*)calloc(65, sizeof(char));
void decimal_to_binary(int);
int main()
{
puts("\nEnter the decimal number : ");
scanf("%d", &decimal);
decimal_to_binary(decimal);
*(binary_string + counter) = '\0';
printf("Counter = %d\n", counter);
puts("The binary equivalent is : ");
puts(binary_string);
return 0;
}
void decimal_to_binary(int number)
{
if (number == 0)
return;
else
{
int temp = number % 2;
decimal_to_binary(number/2);
*(binary_string + counter) = temp;
counter++;
}
}
Should the casting store only the LSB of int in the char array each time?
Do not use global variables if not absolutely necessary. Changing the global variable in the function makes it very not universal.
#include <stdio.h>
char *tobin(char *buff, unsigned num)
{
if(num / 2) buff = tobin(buff, num / 2);
buff[0] = '0' + num % 2;
buff[1] = 0;
return buff + 1;
}
int main(void)
{
char buff[65];
unsigned num = 0xf1;
tobin(buff, num);
printf("%s\n", buff);
}
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int decimal, counter=0;
//char* binary_string = (char*)calloc(65, sizeof(char));
//C does not allow initialization of global variables with
//non constant values. Instead declare a static char array with 65 elements.
//Alternatively declare binary_string in the main function and allocate memory with calloc.
char binary_string[65];
void decimal_to_binary(int);
int main()
{
puts("\nEnter the decimal number : ");
scanf("%d", &decimal);
decimal_to_binary(decimal);
//*(binary_string + counter) = '\0';
// This is more readable:
binary_string[counter] = '\0';
printf("Counter = %d\n", counter);
puts("The binary equivalent is : ");
puts(binary_string);
return 0;
}
void decimal_to_binary(int number)
{
if (number == 0)
return;
else
{
int temp = number % 2;
//decimal_to_binary(number/2);
//you call decimal_to_binary again before increasing counter.
//That means every time you call decimal_to_binary, the value of count
//is 0 and you always write to the first character in the string.
//*(binary_string + counter) = temp;
//This is more readable
//binary_string[counter] = temp;
//But you are still setting the character at position counter to the literal value temp, which is either 0 or 1.
//if its 0, you are effectively writing a \0 (null character) which in C represents the end of a string.
//You want the *character* that represents the value of temp.
//in ASCII, the value for the *character* 0 is 0x30 and for 1 it is 0x31.
binary_string[counter] = 0x30 + temp;
counter++;
//Now after writing to the string and incrementing counter, you can call decimal_to_binary again
decimal_to_binary(number/2);
}
}
If you compile this, run the resulting executable and enter 16 as a number, you may expect to get 10000 as output. But you get00001. Why is that?
You are writing the binary digits to the string in the wrong order.
The first binary digit you calculate is the least significant bit, which you write to the first character in the string etc.
To fix that aswell, you can do:
void decimal_to_binary(int number){
if(number == 0){
return;
}
else{
int temp = number % 2;
counter++;
//Store the position of the current digit
int pos = counter;
//Don't write it to the string yet
decimal_to_binary(number/2);
//Now we know how many characters are needed and we can fill the string
//in reverse order. The first digit (where pos = 1) goes to the last character in the string (counter - pos). The second digit (where pos = 2) goes to the second last character in the string etc.
binary_string[counter - pos] = 0x30 + temp;
}
}
This is not the most efficient way, but it is closest to your original solution.
Also note that this breaks for negative numbers (consider decimal = -1, -1 % 2 = -1).
I have the following program that converts decimal to binary:
#include <stdio.h>
#include <string.h>
int main() {
printf("Number (decimal): ");
int no;
scanf("%d", &no);
char bin[64];
while (no > 0) {
for (int i = strlen(bin); i > 0; i--) {
bin[i] = bin[i - 1];
}
int bit = no % 2;
char digit = bit + '0';
bin[0] = digit;
no /= 2;
}
printf("%s", bin);
return 0;
}
The program works correctly, but randomly the string "ttime__vdso_get" gets appended on the end.
The numbers that make it happen are different every time I compile.
1: 1
2: 01ttime_vsdo_get
3: 10ttime_vsdo_get
It becomes a little different when the numbers get bigger:
100039: 11000011011000111ttime__vdso_getm#
10000000000000000000000000000: ttime
What is happening?
If I had to diagnose it I'd say that I've managed to make a compiling program that's pulling memory from the wrong places. I don't know how how I managed to do it, though.
I'm using GCC, if it matters.
Just do char bin[64] = "";, never forget that a valid string is nul terminatedM#��M#.
And strlen() return an size_t !
I can also advice you to use char bin[sizeof no * CHAR_BIT + 1] = ""; that will use a correct maximum size for your string.
It may be because of this line of code :
for (int i = strlen(bin); i > 0; i--) {
bin[i] = bin[i - 1];
}
Try replacing strlen(bin) with 63.
It may also be a good idea to initialize your array bin with 0s.
try filling varible
char bin[64]
with 0
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int myatoi(const char* string) {
int i = 0;
while (*string) {
i = (i << 3) + (i<<1) + (*string -'0');
string++;
}
return i;
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
long int dec = myatoi(decimal);
long int fraction;
long int remainder;
long int factor = 1;
long int fractionfactor = .1;
long int wholenum;
long int bin;
long int onechecker;
wholenum = (int) dec;
fraction = dec - wholenum;
while (wholenum != 0 ) {
remainder = wholenum % 2; // get remainder
bin = bin + remainder * factor; // store the binary as you get remainder
wholenum /= 2; // divide by 2
factor *= 10; // times by 10 so it goes to the next digit
}
long int binaryfrac = 0;
int i;
for (i = 0; i < 10; i++) {
fraction *= 2; // times by two first
onechecker = fraction; // onechecker is for checking if greater than one
binaryfrac += fractionfactor * onechecker; // store into binary as you go
if (onechecker == 1) {
fraction -= onechecker; // if greater than 1 subtract the 1
}
fractionfactor /= 10;
}
bin += binaryfrac;
*binary = bin;
free(decimal);
}
int main(int argc, char **argv) {
char *data;
data = malloc(sizeof(char) * 32);
int datai = 1;
if (argc != 4) {
printf("invalid number of arguments\n");
return 1;
}
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
free(data);
return 0;
}
In this problem, myatoi works fine and the decimal2binary algorithm is correct, but every time I run the code it gives my output as 0. I do not know why. Is it a problem with pointers? I already set the address of variable data but the output still doesn't change.
./dec2bin "-d" "23" "-b"
The line:
long int fractionfactor = .1;
will set fractionfactor to 0 because the variable is defined as an integer. Try using a float or double instead.
Similarly,
long int dec = myatoi(decimal);
stores an integer value, so wholenum is unnecessary.
Instead of
i = (i << 3) + (i<<1) + (*string -'0');
the code will be much more readable as
i = i * 10 + (*string - '0');
and, with today's optimizing compilers, both versions will likely generate the same object code. In general, especially when your code isn't working, favor readability over optimization.
fraction *= 2; // times by two first
Comments like this, that simply translate code to English, are unnecessary unless you're using the language in an unusual way. You can assume the reader is familiar with the language; it's far more helpful to explain your reasoning instead.
Another coding tip: instead of writing
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
you can refactor the nested if blocks to make them simpler and easier to understand. In general it's a good idea to check for error conditions early, to separate the error-checking from the core processing, and to explain errors as specifically as possible so the user will know how to correct them.
If you do this, it may also be easier to realize that both of the original conditions should be negated:
if (strcmp(argv[1], "-d") != 0) {
printf("Error: first parameter must be -d\n");
else if (strcmp(argv[3], "-b") != 0) {
printf("Error: third parameter must be -b\n");
} else {
decimal2binary(argv[2], &datai);
printf("Output is: %d\n" , datai);
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
...
}
The above lines of code allocate a new block of memory to decimal, which will then no longer point to the input data. Then the line
long int dec = myatoi(decimal);
assigns the (random values in the) newly-allocated memory to dec.
So remove the line
decimal = malloc(sizeof(char) * 32);
and you will get the correct answer.
if(!strcmp(argv[3] , "-b"))
if(!strcmp(argv[3] , "-d"))
The result of the string compare function should be negated so that you can proceed. Else it will print invalid parameter. Because the strcmp returns '0' when the string is equal.
In the 'decimal2binary' function you are allocating a new memory block inside the function for the input parameter 'decimal',
decimal = malloc(sizeof(char) * 32);
This would actually overwrite your input parameter data.
I am trying to create a function that will take an int and separately return the leftmost digit and the rest of the number.
int idigitizer(int *number) {
int i = 1;
int head = 0;
int tmp = 0;
tmp = *number;
while (tmp > 9) {
if ((tmp/i) < 10) {
head = tmp/i;
*number = *number - (head*i);
return head;
} else {
i = i*10;
}
}
number = 0;
return tmp;
}
idigitizer returns the leftmost part of the number and *number will carry the rest.
I will have a loop in my main that will keep calling idigitizer until all the digits of the number get separated.
The thing is I don't know how to handle zeroes and how to make this process terminate correctly when it is done with the last digit. Any help is welcome. Thanks in advance.
EDIT : To make it clearer. I don't want the possible zeroes in the middle of a number to get lost. If i get the number 100047 as input I want idigitizer to return:
return - *number
100047
1 00047
0 0047
0 047
0 47
4 7
7
I would use something like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int getFirstDigit( int number );
int getRestOfNumber( int number );
int getNumberOfMissingZeros (int number, int restOfNumber);
int main(int argc, char* argv[]){
int x = 500574;
int firstDigit;
int restOfNumber;
int n; /* loop index */
firstDigit = getFirstDigit(x);
restOfNumber = getRestOfNumber(x);
printf("The first digit of %d is %d.\n",x,firstDigit);
printf("The rest of the number is ");
for( n = 0; n<getNumberOfMissingZeros(x,restOfNumber); ++n ){
printf("0");
}
printf("%d.",restOfNumber);
return EXIT_SUCCESS;
}
int getFirstDigit( int number ){
return number / (int)floor( pow(10,floor(log10( (double)number ))) );
}
int getRestOfNumber( int number){
return number % (int)floor( pow(10,floor(log10( (double)number ))) );
}
int getNumberOfMissingZeros (int number, int restOfNumber){
int digitsOriginally;
int digitsInRestOfNumber;
digitsOriginally = floor(log10( (double)number ) );
digitsInRestOfNumber = floor(log10( (double)restOfNumber ) );
return digitsOriginally - digitsInRestOfNumber - 1;
}
The magic is in the expression (int)floor( pow(10,floor(log10( (double)number ))) ); This gets the size of the value, like for 52330, it would return 10000, since there are five digits in 52330. This makes it easy to extract the highest digit.
Given the precisely worded constraints of the problem: a function that will take an int and separately return the leftmost digit and the rest of the number it cannot be done, because it is impossible to represent the leading zeros in an integer, so passing back the "rest of the number" is bound to cause permanent loss of information
As the robot in Lost in Space would say, "It does not compute."
Putting an appropriate loop around something like this should work if I understand the question correctly.
//! Given a number return the least significant digit.
//! Return true if all went well. False otherwise. (Clearly we
//! can handle errors better.)
/*!
\param[in/out] n
The number to strip the least significant digit from.
\param[out] d
The least significant digit of n.
*/
bool digitize(int& n, int& d)
{
if ( n == 0 )
return false
else
{
d = n % 10;
n = n / 10;
return true;
}
}