K&R C Book: Exercise 3-5 itob function - c

In the following function itob() what does the snippet j + 'A' - 10 do? I don't get why we subtract 10:
/* itob: convert n to characters in s - base b */
void itob(int n, char s[], int b) {
int i, j, sign;
i = 0;
if ((sign = n) < 0)
n = -n;
do {
j = n % b;
s[i++] = (j <= 9) ? j + '0' : j + 'A' - 10;
} while ((n /= b) != 0);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}

Related

Fibonacci number program crashes with exit code 139

I am testing edge cases in my Fibonacci number program. It runs fine if the input value for first variable is 999999 or below. It crashes when the value is anything bigger. I am already using long int somewhere, really no clue what am I doing wrong.
#include <stdio.h>
#include <stdlib.h>
long ft(long num, int m) {
long arr[num];
int i;
int j = 0;
i = 3;
arr[0] = 0;
arr[1] = 1;
arr[2] = 1;
while (i <= num && j != 1) {
arr[i] = 0;
if ((arr[i - 1] + arr[i - 2]) < m) {
arr[i] = arr[i - 1] + arr[i - 2];
} else {
arr[i] = (arr[i - 1] + arr[i - 2]) % m;
}
if (arr[i] == 1 && arr[i - 1] == 1 && arr[i - 2] == 0)
j = 1;
i++;
}
if (i < num)
return arr[num % (i - 3)];
else
return arr[i - 1];
}
int main() {
long n = 0;
int m = 0;
scanf("%ld %d", &n, &m);
printf("%ld", ft(n, m));
return 0;
}
That's too much stack. Please allocate arr with malloc() and please check for allocation failures. Don't forget to free arr.
long *arr = malloc(sizeof(long) * (size_t)(num + 1));
if (!arr) return -1; // Error
//...
long r;
if (i < num) r= arr[num%(i-3)];
else r= arr[i-1];
free(arr);
return r;
Your program computes Fibonacci numbers modulo a given number.
The reason it crashes for values above 999999 is you allocate a variable length array of long with automatic storage (aka on the stack), that exceeds the available space in this segment (4 or 8 MB). Your program has undefined behavior and causes a stack overflow.
You should instead allocate this array from the heap with malloc or calloc and free it before leaving the function.
Note also these other problems:
arr should have a length of num + 1 because you store the result in arr[num].
the result is incorrect for num == 0 and for m == 1.
the function has undefined behavior for m == 0.
negative values of m and num should return an error result such as -1.
the test for cycle detection can be simplified.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
long ft(long num, int m) {
long *arr;
int i;
long res;
if (m < 0 || num < 0 || (arr = calloc(sizeof(*arr), num + 1)) == NULL)
return -1;
if (m == 1)
return 0;
arr[0] = 0;
arr[1] = 1;
arr[2] = 1;
res = arr[num];
for (i = 3; i <= num; i++) {
res = arr[i - 1] + arr[i - 2];
if (res >= m)
res -= m;
arr[i] = res;
if (res == 0 && arr[i - 1] == 1) { // handle cycle
res = arr[num % i];
break;
}
}
free(arr);
return res;
}
int main(int argc, char *argv[]) {
long n, n2;
int m = 0;
char *p;
if (argc > 1) { // command line arguments: start[..end] [mod]
n = n2 = strtol(argv[0], &p, 0);
if (*p == '.' && p[1] == '.')
n2 = strtol(p + 2, NULL, 0);
if (argc > 2)
m = strtol(argv[0], NULL, 0);
} else {
if (scanf("%ld %d", &n, &m) != 2)
return 1;
n2 = n;
}
while (n <= n2)
printf("%ld\n", ft(n++, m));
return 0;
}

How to fix the output of the following C program?

I have a problem with output of the following C program. It does not get me the correct output.I transform this program from the sum of two big numbers.
So I get the output with some "errors" like "232423-3-4-34--3424" instead of "23242334343424". How do i fix this?
#include<stdio.h>
int main() {
int num1[255], num2[255], dif[255];
char s1[255], s2[255];
int l1, l2;
printf("Enter Number1:\n");
scanf("%s", &s1);
printf("Enter Number2:\n");
scanf("%s", &s2);
for (l1 = 0; s1[l1] != '\0'; l1++)
num1[l1] = s1[l1] - '0';
for (l2 = 0; s2[l2] != '\0'; l2++)
num2[l2] = s2[l2] - '0';
int carry = 0;
int k = 0;
int i = l1 - 1;
int j = l2 - 1;
for (; i >= 0 && j >= 0; i--, j--, k++) {
dif[k] = (num1[i] - num2[j] - carry) % 10;
carry = (num1[i] - num2[j] - carry) / 10;
}
if (l1 > l2) {
while (i >= 0) {
dif[k++] = (num1[i] - carry) % 10;
carry = (num1[i--] - carry) / 10;
}
} else if (l1 < l2) {
while (j >= 0) {
dif[k++] = (num2[j] - carry) % 10;
carry = (num2[j--] - carry) / 10;
}
} else {
if (carry > 0)
dif[k++] = carry;
}
printf("Result:");
for (k--; k >= 0; k--)
printf("%d", dif[k]);
return 0;
}
Your result includes negative numbers because the code doesn't correctly implement modulo-10 arithmetic. In lines like this:
dif[k] = (num1[i] - num2[j] - carry) % 10;
If subtraction num1[i] - num2[j] - carry is less than 0, you want to store the result of 10-subtraction. There are languages where the % operator works like that in, but in C it returns a negative number, so -1 % 10 yields -1 and not 9.
To fix the issue, the code needs to be more explicit, e.g.:
int sub = num1[i] - num2[j] - carry;
if (sub >= 0) {
dif[k] = sub;
carry = 0;
} else {
dif[k] = 10 - sub;
carry = 1;
}

C - Print all numbers with same count of set and unset bits

I have to print numbers with max N bits where count of bits set to 1 = count of bits set to 0. I ignoring leading zeros. I thinking that this applies only when count of bits is even.
My code:
int power(k) {
return 1 << k;
}
void print_numbers(int n){
n -= (n % 2); // FOR EVEN COUNT OF BITS
int exp = 1; // EXPONENTS WILL BE ODD (2^1, 2^3, 2^5, ...)
while (exp < n) {
int start = power(exp);
int end = power(exp + 1);
int ones = (exp + 1) / 2; // ALLOWED COUNT OF 1
for (int i = start; i < end; i++) {
int bits_count = 0;
for (int j = 0; j <= exp; j++){ // CHECK COUNT OF 1
bits_count += ((i >> j) & 1);
}
if (bits_count == ones){
printf("%d\n", i);
}
}
exp += 2;
}
For N = 12 this function print 637 numbers. Is this solution correct or am i wrong? Any idea for more efficient or better solution?
I came up with this, which is a totally different approach (and perfectible) but works:
#include <stdio.h>
void checker(int number)
{
int c;
int zeros = 0;
int ones = 0;
for (c = 31; c >= 0; c--)
{
if (number >> c & 1)
{
ones++;
}
else if(ones > 0)
{
zeros++;
}
}
if(zeros == ones)
{
printf("%i\n", number);
}
}
int main()
{
int c;
for (c = 4095; c >= 0; c--)
{
checker(c);
}
return 0;
}
Which get me 638 values (including 0)

convert negative decimal number to binary number

I tried to convert a negative decimal number into a binary number and this code perfectly works on my computer, but the code doesn't work another computer.
I didn't get how it is possible. What is wrong in my code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void decTobin(int dec, int s)
{
int b[s], i = 0;
while (dec >= 0 && i != s - 1) {
b[i] = dec % 2;
i++;
dec /= 2;
}
int j = i;
printf("%d", dec);
for (j = i - 1; j >= 0; j--) {
if (b[j] == NULL)
b[j] = 0;
printf("%d",b[j]);
}
}
void ndecTobin(int dec, int s)
{
int b[s], i = 0, a[s], decimal, decimalvalue = 0, g;
while (dec >= 0 && i != s-1) {
b[i] = dec % 2;
i++;
dec /= 2;
}
int j = i;
printf("%d",dec);
for (j = i - 1; j >= 0; j--) {
if (b[j] == NULL)
b[j] = 0;
printf("%d",b[j]);
}
printf("\n");
a[s - 1] = dec;
for (j = s - 2; j >= 0; j--) {
a[j] = b[j];
}
for (j = s - 1; j >= 0; j--) {
if (a[j] == 0)
a[j] = 1;
else
a[j] = 0;
printf("%d",a[j]);
}
for (g = 0; g < s; g++) {
decimalvalue = pow(2, g) * a[g];
decimal += decimalvalue;
}
decimal = decimal + 1;
printf("\n%d\n", decimal);
decTobin(decimal, s);
}
int main()
{
int a, b;
printf("enter a number: ");
scanf(" %d", &a);
printf("enter the base: ");
scanf("%d", &b);
ndecTobin(a, b);
}
decimal and int b[s] not initialized.
By not initializing decimal to 0, it might have the value of 0 on a machine one day and quite different results otherwise.
void decTobin(int dec, int s) {
// while loop does not set all `b`,but following for loop uses all `b`
// int b[s], i = 0;
int b[s] = { 0 }; // or int b[s]; memset(b, 0, sizeof b);
int i = 0;
}
void ndecTobin(int dec, int s) {
int b[s], i = 0, a[s], decimal, decimalvalue = 0, g;
decimal = 0;
...
decimal += decimalvalue;
}
Minor points:
1) if (b[j] == NULL) b[j] = 0; is strange. NULL is best used as a pointer, yet code is comparing b[j], an int to a pointer. Further, since NULL typically has the arithmetic value of 0, code looks like if (b[j] == 0) b[j] = 0;.
2) decTobin() is challenging to follow. It certainly is only meant for non-negative dec and s. Candidate simplification:
void decTobin(unsigned number, unsigned width) {
int digit[width];
for (unsigned i = width; i-- > 0; ) {
digit[i] = number % 2;
number /= 2;
}
printf("%u ", number); // assume this is for debug
for (unsigned i = 0; i<width; i++) {
printf("%u", digit[i]);
}
}
It looks like you are just printing the number as a binary representation. If so this version would work.
void print_binary(size_t n) {
/* buffer large enough to hold number to print */
unsigned buf[CHAR_BIT * sizeof n] = {0};
unsigned i = 0;
/* handle special case user calls with n = 0 */
if(n == 0) {
puts("0");
return;
}
while(n) {
buf[i++] = n % 2;
n/= 2;
}
/* print buffer backwards for binary representation */
do {
printf("%u", buf[--i]);
} while(i != 0);
}
If you don't like the buffer, you can also do it using recursion like this:
void using_recursion(size_t n)
{
if (n > 1)
using_recursion(n/2);
printf("%u", n % 2);
}
Yet another way is to print evaluating most significant bits first. This however introduces issue of leading zeros which in code below are skipped.
void print_binary2(size_t n) {
/* do not print leading zeros */
int i = (sizeof(n) * 8)-1;
while(i >= 0) {
if((n >> i) & 1)
break;
--i;
}
for(; i >= 0; --i)
printf("%u", (n >> i) & 1);
}
Different OS/processor combinations may result in C compilers that store various kinds of numeric variables in different numbers of bytes. For instance, when I first learned C (Turbo C on a 80368, DOS 5) an int was two bytes, but now, with gcc on 64-bit Linux, my int is apparently four bytes. You need to include some way to account for the actual byte length of the variable type: unary operator sizeof(foo) (where foo is a type, in your case, int) returns an unsigned integer value you can use to ensure you do the right number of bit shifts.

Donald Knuth algorithm for Mastermind

I'm working onto the Donald Knuth 1977 algorithm for Mastermind (here). I've implemented some steps, but I don't know how to calculate the number of possibilites that would be eliminated for each possible score.
Integer Bulls <- 0
WHILE Bulls <= 4
Integer Cows <- 0
WHILE Cows <= 4
Integer CurrentSetSize <- 0
WHILE CurrentSetSize <= Set.size
// Now, I should know if this possibility can be eliminated. But how ?
END WHILE
END WHILE
END WHILE
Do you have any way to do this ?
Thanks.
Edit : I did it with C. It isn't Mastermind in reality but Bulls & Cows, but it's the same.
// ASCII-compatible
#define POSSIBILITIES 6720
struct Guess {
int i[5];
};
struct Answer {
int bulls;
int cows;
};
static struct Set {
struct Guess value;
int score;
} *CurrentSet;
void
initSet(void)
{
for (int i = 'a'; i <= 'h'; ++i) {
for (int j = 'a'; j <= 'h'; ++j) {
if (j == i) continue;
for (int k = 'a'; k <= 'h'; ++k) {
if (k == j || k == i) continue;
for (int l = 'a'; l <= 'h'; ++l) {
if (l == k || l == j || l == i) continue;
for (int m = 'a'; m <= 'h'; ++m) {
if (m == l || m == k || m == j || m == i) continue;
CurrentSet->value.i[0] = i;
CurrentSet->value.i[1] = j;
CurrentSet->value.i[2] = k;
CurrentSet->value.i[3] = l;
CurrentSet->value.i[4] = m;
CurrentSet->score = 0;
}
}
}
}
}
}
void
computeScore(int index)
{
struct answer p;
for (p.bulls = 0; p.bulls <= 4; ++p.bulls) {
for (p.cows = 0; p.cows <= 4; ++p.cows) {
for (int i = 0; i < POSSIBILITIES; ++i) {
}
}
}
}
void
updateSet(void)
{
for (int i = 0; i < POSSIBILITIES; ++i)
computeScore(i);
}

Resources