Abnormal Behaviour of Array - arrays

This Code convert a decimal number i to its binary ... Along with storing its value in a array ans.
In This below code i used ans size 100 . Now when i enter input as 0.5 it gives a weird output . But if i change the size of Array to 1000 the it's giving correct output can anyone explain this behaviour.
Code with ans Size 100
#include <stdio.h>
int main() {
float n;
printf ("Enter Decimal Number:");
scanf("%f", &n);
// Integer Part of Number
int ip = n;
// To store the Binary Number
char ans[100];
// Index of array
int i = 0;
// For integer part
while(ip != 1 && ip != 0) {
if ((ip % 2) == 0) {
ans[i] = '0';
}
else {
ans[i] = '1';
}
i++;
ip /= 2;
}
if (ip) {
ans[i++] = '1';
}
else{
ans[i++] = '0';
}
// Reverse the Integer Part
for (int j = 0; j < (i/2); j++) {
char temp = ans[j];
ans[j] = ans[i - j - 1];
ans[i - j - 1] = temp;
}
ans[i++] = '.';
ans[i] = '0';
// Flaoting Part of Number
float fp = n - (int) n;
// For floating Part
if (fp) {
for (int j = 0; j < 5; j++) {
fp *= 2;
// Integer part of fp
int x = fp;
// floating part of new fp
fp = fp - x;
if (x) {
ans[i++] = '1';
}
else {
ans[i++] = '0';
}
if(!fp){
break;
}
}
}
printf("%f in Binary is %s", n, ans);
return 0;
}
OUTPUT
Enter Decimal Number:0.5
0.500000 in Binary is 0.1�
[Program finished]
Code with ans size 1000
#include <stdio.h>
int main() {
float n;
printf ("Enter Decimal Number:");
scanf("%f", &n);
// Integer Part of Number
int ip = n;
// To store the Binary Number
char ans[1000];
// Index of array
int i = 0;
// For integer part
while(ip != 1 && ip != 0) {
if ((ip % 2) == 0) {
ans[i] = '0';
}
else {
ans[i] = '1';
}
i++;
ip /= 2;
}
if (ip) {
ans[i++] = '1';
}
else{
ans[i++] = '0';
}
// Reverse the Integer Part
for (int j = 0; j < (i/2); j++) {
char temp = ans[j];
ans[j] = ans[i - j - 1];
ans[i - j - 1] = temp;
}
ans[i++] = '.';
ans[i] = '0';
// Flaoting Part of Number
float fp = n - (int) n;
// For floating Part
if (fp) {
for (int j = 0; j < 5; j++) {
fp *= 2;
// Integer part of fp
int x = fp;
// floating part of new fp
fp = fp - x;
if (x) {
ans[i++] = '1';
}
else {
ans[i++] = '0';
}
if(!fp){
break;
}
}
}
printf("%f in Binary is %s", n, ans);
return 0;
}
OUTPUT
Enter Decimal Number:0.5
0.500000 in Binary is 0.1
[Program finished]

Your ans string in not null-terminated, so printing a string that is not null-terminated causes UB (undefined behavior). As to why it works when the size is 1000 vs. 100 I cannot say, but the bottom line is that undefined bahavior is undefined... anything could happen. So fix the bug as follows:
:
:
// Flaoting Part of Number
float fp = n - ip;
// For floating Part
if (fp) {
for (int j = 0; j < 5; j++) {
fp *= 2;
// Integer part of fp
int x = (int)fp;
// floating part of new fp
fp -= x;
ans[i++] = x ? '1' : '0';
if(!fp)
break;
}
} else i++;
ans[i] = '\0';
printf("%f in Binary is %s", n, ans);
return 0;
}

I am turning my comment into an answer.
Your ans array is not null terminated, hence printf("%s", arr) doesn't know where to stop reading and keeps printing whatever garbage follows. If you are going to print it with %s append a null terminator at the end of your data in the array before printing it, or print it character by character in a loop.
You can also initialize your array as char ans[100] = { 0 }, which assigns all elements 0. Which also is the ASCII code for the null terminator, hence when you are done writing your characters, the next character will be a null terminator. This however, doesn't work if you re-write a smaller data to your array, previous characters that are not overwritten will still be printed. You can consider using memset to clean you array with 0 before each time you re-write it.
When it comes to the difference between 100 and 1000 element array, I guess your compiler happens to allocate 100 element array in a part of the memory containing garbage, and 1000 element array in a part that happens to contain 0. This is unpredictable and as you can see, can mislead you. Never, ever use your variables uninitialized.

Related

How can print string num?

Problem:
How can print string num? It seems that final statement cannot execute?
Question desciptions:
Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!
Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.
/* Have Fun with Numbers */
#include <stdio.h>
#include <string.h>
int book[10] = { 0 };
int main(int argc, char* argv[])
{
char num[22];
int temp = 0;
scanf_s("%s", num, 1);
// Length of numbers
int len = strlen(num);
int flag = 0;
for (int i = len - 1; i >= 0; --i) {
// Convert an ASCII value of a digit into an integer
temp = num[i] - '0';
// Add 1 each time read a digit
++book[temp];
temp = temp * 2 + flag;
flag = 0;
if (temp >= 10) {
temp -= 10;
flag = 1;
}
// Convert an integer into an ASCII value of a digit
num[i] = (temp + '0');
// Subtract 1 each time generate a digit
--book[temp];
}
int flag1 = 0;
for (int i = 0; i < 10; ++i) {
if (book[i] != 0) {
flag1 = 1;
}
}
printf("%s", (flag == 1 || flag1 == 1) ? "No\n" : "Yes\n");
if (flag == 1) {
printf("1");
}
printf("%s", num);
return 0;
}
In this like
scanf_s("%s", num, 1);
You are reporting the buffer size as 1 to scanf_s() while the actual size is 22.
Use correct buffer size.
scanf_s("%s", num, 22);
or
scanf_s("%s", num, (unsigned)(sizeof(num) / sizeof(*num)));

C how to convert to hexadecimal integer

im writing a code for converting a number to hexadecimal and im getting a random numbers as result.
at first i succeed to convert the number but it was in a reversed order (the first mod needs to be the last number or letter).
the code is a part (for cases of %x) from a big project that is kind of implementation of sprintf (so sprintf or printf are not allowed obviously). so the buffer is for composing a string without any placeholders.
thank u in advance.
here's my code:
int num = *(int*)ptrs[counter];
int tempnum=num;
int mod=0;
int length =0;
for(int i=0;tempnum !=0;i++)
{
length++;
tempnum /= 16;
}
int array[length];
for(int i= length; i>0;i--)
{
mod = num%16;
num = num/16;
array[i] = mod;
}
for(int i=0;i<length;i++)
{
if(array[i]<10)
*buffer = array[i]+ '0';
else
*buffer = array[i] -10 + 'a';
buffer++;
}
The for loop of calculating array[i] should change to:
for(int i = length-1; i>=0;i--) // i from (length - 1) to 0 instead of from length to 1.
{
mod = num%16;
num = num/16;
array[i] = mod;
}
You do not need to change the buffer pointer. You can use:
for(int i=0;i<length;i++)
{
if(array[i]<10)
buffer[i] = array[i]+ '0';
else
buffer[i] = array[i] + 55;
}
then do not forget at the null character at the end of buffer:
buffer[length] = '\0';
I do not see the declaration of buffer in your code, so i propose the solution above for the declaration:
char buffer[length+1];
for(int i= length; i>0;i--)
{
mod = num%16;
num = num/16;
array[i] = mod;
}
mistakes at array[i] to array[i-1].
buffer = array[i] + '87';
I suggest you use:
buffer = array[i]-10 + 'a';
printf("%i", (int)[any hexadecimal number]);
would print the integer form of this '[any hexadecimal number]' number

How can I multiply two strings containing 'huge numbers' (over 30 digits)?

I'm doing school project which I'm needed to first receive 2 huge numbers (unlimited size, for the sake of example, lets say over 30 digits), second step is to take the 2 input numbers the create new number of the multiplication of the two, which I'm really breaking a sweat trying to do so.
My code so far:
Type definition to making sure I'm handling the right variables:
typedef char* verylong;
#define MAX_SIZE 100
Input method:
verylong input_long() {
int i, len; //i for loop, len for strlen - using integer for it to avoid invoking the method more than 1 time
verylong number;
char temp_str[MAX_SIZE]; //the input from user - limited to 100
gets(temp_str); //user input
len = strlen(temp_str); //saving the length of the input
number = (char*)calloc(len + 1, sizeof(char)); //allocating memory for the verylong and saving space for \0
for (i = 0; i < len; i++) {
if (temp_str[i] - '0' < 0 || temp_str[i] - '0' > 9) { //the input is not a digit
printf("\nBad input!\n");
return NULL;
}
number[i] = temp_str[i]; //all is good -> add to the verylong number
}
number[i] = '\0'; //setting last spot
return number;
}
My sad attempt of completing my task:
verylong multiply_verylong(verylong vl1, verylong vl2) {
verylong mult;
int cur, i, j, k, lrg, sml, temp_size;
char *temp;
j = 1;
temp = (char*)calloc(lrg + sml + 1, sizeof(char)); //maximum amount of digits
if (strlen(vl1) > strlen(vl2)) {
lrg = strlen(vl1);
sml = strlen(vl2);
}
else {
lrg = strlen(vl2);
sml = strlen(vl1);
}
cur = 0;
for (i = sml-1; i >= 0; i--) {
k = 0;
temp_size = 0;
cur = (vl1[i] - '0')*(vl2[i] - '0');
printf("\ncur=%d", cur);
if (cur > 9)
temp_size = 2;
else
temp_size = 1;
while (k < temp_size) {
if (cur > 9)
temp[j++] = (cur % 10) + '0';
else
temp[j++] = cur + '0';
cur /= 10;
k++;
}
}
mult = (char*)calloc(j + 1, sizeof(char));
for (i = 0; i < j; i++) {
mult[i] = temp[i];
}
mult[i] = '\0';
free(temp);
return mult;
}
Long story short, I know I'm doing mistake at my multiplication method since I'm adding the numbers by simply adding the mult of 2 digits at a time, over that I truly am lost.
Thanks.
My advice would be to break the task into a number of simpler task.
How would you do the multiplication on paper?
123 * 456 -> 1 * (456 * 100) + 2 * (456 * 10) + 3 * (456 * 1)
or written differently
3 * ( 1 * 456)
+ 2 * ( 10 * 456)
+ 1 * (100 * 456)
---------------
SUM TO GET RESULT
or
3 * 456
+ 2 * 4560
+ 1 * 45600
---------------
SUM TO GET RESULT
From this you can identify 3 tasks
Multiplying with powers of 10, i.e. 1, 10, 100, etc. (i.e. add zeros to the end)
Multiplying a string-number with a single digit
Adding two string-numbers.
Write simple functions for each of these steps.
char* mulPowerOf10(char* sn, unsigned power)
{
...
}
char* mulDigit(char* sn, char digit)
{
...
}
char* addNumbers(char* snA, char* snB)
{
...
}
Using these 3 simple functions you can put the real multiplication together. In psedo-code:
char* mulNumbers(char* snA, char* snB)
{
char* result = malloc(2);
strcpy(result, "0");
unsigned power = 0;
for_each_digit D in snA
{
char* t1 = mulPowerOf10(snB, power)
char* t2 = mulDigit(t1, D)
result = addNumbers(result, t2)
++power;
}
free(.. what needs to be freed ..);
return result;
}
Here is a code example.
I found it simpler to store the number as a sequence of digits along with the length in a struct. The number may have leading zeros.
#define MAX_SIZE 1024
typedef struct Number {
int len;
char digits[];
} Number;
// Instantiate a number with room for len digits.
Number *newNumber(int len) {
Number *n = malloc(sizeof(Number)+len);
n->len = len;
memset(n->digits, 0, len);
return n;
}
// inputNumber reads a number from stdin. It return NULL if the input
// is invalid, otherwise it returns a Number containing the given digits.
Number *inputNumber() {
char temp[MAX_SIZE];
if (fgets(temp, sizeof temp, stdin) == NULL)
return NULL; // use fgets because gets is deprecated since C11
// remove trailing \n if any
int len = strlen(temp);
if (len > 0 && temp[len-1] == '\n')
temp[--len] = '\0';
// check input validity
if (len == 0)
return NULL;
for (int i = 0; temp[i] != '\0'; i++)
if (temp[i] < '0' || temp[i] > '9')
return NULL;
Number *n = newNumber(len);
for (int i = 0; temp[i] != '\0'; i++)
n->digits[i] = temp[i] - '0';
return n;
}
To multiply two numbers n1 and n2, we multiply n1 with each digit of n2, and accumulate the result shifted on the left by the position of the n2 digit in the final result.
For instance, to multiply 123*456, we compute 123*4 + 123*5*10 + 123*6*100. Note that *10 and *100 are simply left shifts.
We thus need a function that multiplies a number with a digit, and another function that accumulates a number with a left shift in a result number.
// multiply stores the result of n time digit in result.
// Requires the len of result is the len of n + 1.
void multiplyNumber(Number *n, char digit, Number *result) {
char carry = 0;
for (int i = r->len-1, j = n->len-1; i > 0; i--, j--) {
char x = n->digits[j] * d + carry;
r->digits[i] = x%10;
carry = x/10;
}
r->digits[0] = carry;
}
// accumutateNumber adds n with the left shift s to the number r.
// Requires the len of r is at least len of n + s + 1.
void accumulateNumber(Number *n, int s, Number *r) {
char carry = 0;
for (int i = r->len-1-s, j = n->len-1; j >= 0; i--, j--) {
char x = r->digits[i] + n->digits[j] + carry;
r->digits[i] = x%10;
carry = x/10;
}
r->digits[r->len-1-s-n->len] = carry;
}
Finally, we also need a function to print the number
void printNumber(Number *n) {
int i = 0;
// skip 0 at the front
while (i < n->len && n->digits[i] == 0)
i++;
if (i == n->len) {
printf("0\n");
return;
}
while (i < n->len)
putchar(n->digits[i++] + '0');
putchar('\n');
}
And this is it. We can now write the main function with the input of the numbers, the multiplication of number 1 with each digit of number 2 and accumulate the result with a shift to get the final result.
int main() {
printf("number 1: ");
Number *n1 = inputNumber();
if (n1 == NULL) {
printf("number 1 is invalid\n");
return 1;
}
printf("number 2: ");
Number *n2 = inputNumber();
if (n2 == NULL) {
printf("number 2 is invalid\n");
return 1;
}
Number *r = newNumber(n1->len+n2->len);
Number *tmp = newNumber(n1->len+1);
for (int i = 0; i < n2->len; i++) {
multiplyNumber(n1, n2->digits[n2->len-1-i], tmp);
accumulateNumber(tmp, i, r);
}
printf("result: ");
printNumber(r);
return 0;
}
Here you may have a look at a 'string only' version, multiplying like you would do with a pencil.
It works with 2 loops. The outer loop takes the digits of value2 from the right and multiplies in the inner loop with every digit of value1 from right. The right digit of the multiplication is stored in result, the rest goes in carry for the next inner loop.
At the end of the inner loop, carry is added to result.
After the first outer loop, we have to add previous results to our multiplication.
This is done in if(!first && *lresp) r += toI(*lresp)
The final loop moves the result to the start of the char array.
#include <stdio.h>
#include <stdlib.h>
#define toI(x) ((x)-'0')
#define toC(x) ((x)+'0')
#define max(a,b) ((a)>(b)) ? (a):(b)
char *mul(char *buf1, char *buf2) {
int size, v1, v2, r, carry=0, first=1;
char *startp1, *endp1, *lendp1, *startp2, *endp2;
char *startres, *endres, *resp, *lresp, *result;
for(endp1 = startp1 = buf1; *endp1; endp1++); // start and endpointer 1st value
for(endp2 = startp2 = buf2; *endp2; endp2++); // start and end pointer 2nd value
size = endp2-startp2 + endp1-startp1; // result size
startres = endres = resp = result = malloc(size+10); // some reserve
endres += size+10-1; // result end pointer
for(resp = startres; resp <= endres; resp++) *resp = '\0'; // init result
for(endp1--, endp2--, resp-=2; endp2>=startp2; endp2--, resp--, first=0) {
v2 = toI(*endp2); // current digit of value2
for(lresp = resp, lendp1 = endp1; lendp1 >= startp1; lendp1--, lresp--) {
v1 = toI(*lendp1); // current digit of value1
r = v1 * v2 + carry; // multiply + carry
if(!first && *lresp) r += toI(*lresp); // add result of previous loops
*lresp = toC(r%10); // store last digit
carry = r/10;
}
for( ; carry != 0; carry /= 10)
*lresp-- = toC(carry%10);
}
// we began right with reserve, now move to start of result
for(lresp++; lresp < endres; lresp++, startres++)
*startres=*lresp;
*startres = '\0';
return result;
}
int main() {
char *result = mul("123456789", "12345678");
printf("\n%s\n", result);
free(result);
}

C - Read in float value using getchar and print out float using printf

I'm extremely lost and confused.
I have to read in a float integer like 3.432 using getchar. Then, I have to print it out again as a float with a precision of 4 decimal places using printf. So 3.432 --> 3.4320 and .450 --> .4500, and 453 --> 453.0000.
I've been using getchar() and I understand that, but trying to reconvert the value as a float is where I'm just extremely lost.
float num = 0.0;
char ch;
while((ch = getchar()) != '\n'){
num = ch - '0';
printf("%.4f", num);
}
I know why that is wrong and what it outputs but that's what I have so far
EDIT: I can only use getchar to read the float values
Not tested (no time). Hope it helps.
#include <stdio.h>
int main(void)
{
float num = 0.0;
float i = 1.0;
char ch;
printf("Enter a float number: ");
while((ch = getchar()) != '\n')
{
if (ch == '.')
{
i = 0.1;
}
else if ((ch>= '0') && (ch <='9'))
{
if (i==1)
{
num *= 10;
num += ch - '0';
}
else
{
num += (ch - '0') * i;
i /= 10;
}
}
}
printf("%.4f\n", num);
return 0;
}
Ok, so you should first specify what you want - as usual keep away from the keybord until you exactly know what you want to build:
read until end of file or first new line
skip initial blank characters (optional but not expensive)
ignore trailing blank character (optional but not expensive)
reject any non blank after first trailing blank
reject any character other than blanks, digits and dot
process the integer part (until first dot) but multiplying current value by 10 and adding character code minus char '0'
ensure at most one dot
process the decimal part by adding char - '0' multiplied by 0.1 power decimal position
Once that has been stated coding is simple and could be:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void error(int pos, char c) {
fprintf(stderr, "Unwanted character %c at %d\n", c, pos);
exit(1);
}
int main() {
double f = 0.;
int c;
bool initial = 1, final=0;
int pos = 0;
double decimal = 0;
while (((c = getchar()) != EOF) && (c != '\n')) {
pos += 1;
if (isspace(c)) { // accept spaces before and after the number
if (initial || final) continue;
else {
final = 1;
continue;
}
}
else if (final) { // do not accept anything after a space after the number
error(pos, c);
}
initial = 0; // at least one non blank char
if (c == '.') {
if (decimal) { // accept only one decimal dot
error(pos, c);
}
else decimal = 1;
}
else if (! isdigit(c)) { // only digits
error(pos, c);
}
else if (decimal == 0) {
f = f * 10 + c - '0'; // integer part
}
else {
decimal *= .1; // fractional part
f += (c - '0') * decimal;
}
}
printf("%.4f\n", f);
return 0;
}
As a bonus I showed you how to process error conditions
It would be simpler if you first write a function reading integer.
Then you can think about writing a function reading the decimal part and combine the result.
Also, you need to accumulate the read information. At the moment you are overwriting previously read digit with a new one.
Another possibility using only stdio in solving the task could be a simple two-step process:
declaring and reading the input into a character array, using some more or less sophisticated fool-proofing
"parsing" the array members on the left and right hand side of the decimal point and multiplying the ('0' offset subtracted value) by the corresponding power of 10.
_
#include <stdio.h>
int main(void)
{
float power_of_ten, num = 0.;
char c, ch[32];
int j, i = 0;
int point_pos = -1; //initialize decimal point position 'offscale'
while(((c = getchar()) != EOF) && (c != '\n')) //simple fool-proof check
if(((c >= '0')&&(c <= '9')) || (( c == '.')&&(point_pos == -1))){
ch[i] = c;
if(ch[i] == '.')
point_pos = i;
i++;
}
ch[++i] = '\0'; //length of the array
//parsing the array
if(point_pos >= 0){ //to the right of decimal point
power_of_ten = .1;
for(j = point_pos + 1; j < i-1; j++){
num += (float)(ch[j] - '0')*power_of_ten;
power_of_ten *= .1;
}
}
power_of_ten = 1.; //to the left of decimal point
if(point_pos == -1)point_pos = i-1;
for(j = point_pos - 1; j >= 0 ; j --){
num += (float)(ch[j] - '0')*power_of_ten;
power_of_ten *= 10;
}
printf("%.4f\n", num);
return 0;
}
Hope this helps!!
#include<stdio.h>
#include<string.h>
#include<math.h>
int findNumOfDigits(int num);
int main(void)
{
char c;
float f, mod, fractional;
char *buff = malloc(10), *fptr;
char *str = buff;
int digits;
printf("Enter any number\n");
c = getchar();
while(c!='\n')
{
*buff = c;
buff = buff+1;
c = getchar();
}
*buff = '\0';
mod = atoi(str);
fptr = strstr(str, ".");
if(fptr!=NULL)
fptr++;
fractional = atoi(fptr);
digits = findNumOfDigits(fractional);
f = (mod + (fractional/pow(10,digits)));
printf("Number converted to float = %f", f);
return 0;
}
int findNumOfDigits(int num)
{
int i;
for(i = 1; num >= 10; i++)
{
num = num/10;
}
return i;
}

Segmentation fault in base number program?

I keep trying to test this code but I keep getting a segmentation fault in my power() function. The code is supposed to take a word made up of lowercase letters and change the word to a number of base 10. The word is supposed to take on the form of a number of base 20, where 'a' = 0, 'b' = 1,...., 't' = 19;
int power(int i){
if(i==1){
return 20;
}else{
return 20*power(i--);
}
}
int main(){
int len;
char mayan[6];
int n;
int val;
while(scanf("%s", mayan)){
val = 0;
n = 0;
for(len = 0; mayan[len] != '\0'; len++){
mayan[len] = tolower(mayan[len]);
mayan[len] = mayan[len] - 'a';
}
for(i = 0; len >= 0; len--, i++){
if(mayan[len] <= 19){
n = n + mayan[len] * power(i);
}else{
fprintf(stderr, "Error, not a base 20 input \n");
val = 1;
break;
}
}
if(val==0){
printf("%d \n", n);
}
}
return val;
}
There were three mistakes in your code.
Case for i==0 not added in the power function, which basically translates to any number to the power of zero is one i.e. x^0 = 1;.
Instead of using return 20*power(i--); for your recursive call, use return 20*power(i-1);. i-- is post decrement operator, which means that, it will return the value of i as it is and will the decrement it for further use, which is not what you want. Also, you altogether don't even want to change the value of i for this iteration too; what you want to do is use a value one less than i for the next iteration, which is what, passing i-1, will do.
Add a len-- in the initialization of the for(i = 0; len >= 0; len--, i++) loop, because len is now over the last index of the input because of the previous loop.
Correcting these mistakes the final code is:
#include<stdio.h>
int power(int i)
{
if(i==0)
{
return 1;
}
if(i==1)
{
return 20;
}
else
{
return 20*power(i-1);
}
}
int main()
{
int len,i;
char mayan[6];
int n;
int val;
while(scanf("%s", mayan))
{
val = 0;
n = 0;
for(len = 0; mayan[len] != '\0'; len++)
{
mayan[len] = tolower(mayan[len]);
mayan[len] = mayan[len] - 'a';
}
for(i = 0, len--; len >= 0; len--, i++)
{
if(mayan[len] <= 19)
{
n = n + mayan[len] * power(i);
}
else
{
fprintf(stderr, "Error, not a base 20 input \n");
val = 1;
break;
}
}
if(val==0)
{
printf("%d \n", n);
}
}
return val;
}
Note that, your code would essentially only work for at most a five digit base 20 number, because, the array mayan that you are using to store it has size 6, of which, one character will be spent for storing the terminating character \0. I recommend that you increase the size of the array mayan unless you want to support only five digit base 20 numbers.

Resources