using array to store big numbers - c

i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}

Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.

Related

K&R C Programming Language Exercise 2-3 code returns rubbish

I tried to write a solution from exercise 2-3. After compilation, it returns random numbers on output. I don't really understand where this issue is coming from.
Any help appreciated.
StackOverflow keeps asking for more details. The purpose of the program is listed in the code bellow.
More delails.
Purpose of the code:
Write the function htoi(s), which converts a string of hexa-
decimal digits (including an optional 0x or 0X) into its
equivalent integer value. The allowable digits are 0 through 9,
a through f, and A through F.
/*
* Write the function htoi(s), which converts a string of hexa-
* decimal digits (including an optional 0x or 0X) into its
* equivalent integer value. The allowable digits are 0 through 9,
* a through f, and A through F.
*/
#include <stdio.h>
#include <math.h>
int hti(char s)
{
const char hexlist[] = "aAbBcCdDeEfF";
int answ = 0;
int i;
for (i=0; s != hexlist[i] && hexlist[i] != '\0'; i++)
;
if (hexlist[i] == '\0')
answ = 0;
else
answ = 10 + (i/2);
return answ;
}
unsigned int htoi(const char s[])
{
int answ;
int power = 0;
signed int i = 0;
int viable = 0;
int hexit;
if (s[i] == '0')
{
i++;
if (s[i] == 'x' || s[i] == 'X')
i++;
}
const int stop = i;
for (i; s[i] != '\0'; i++)
;
i--;
while (viable == 0 && i >= stop)
{
if (s[i] >= '0' && s[i] <= '9')
{
answ = answ + ((s[i] - '0') * pow(16, power));
}
else
{
hexit = hti(s[i]);
if (hexit == 0)
viable = 1;
else
{
hexit = hexit * (pow(16, power));
answ += hexit;
}
}
i--;
power++;
}
if (viable == 1)
return 0;
else
return answ;
}
int main()
{
char test[] = "AC";
int i = htoi(test);
printf("%d\n", i);
return 0;
}
answ is not initialized in htoi. Initialize it to zero.

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;
}

Need help creating a FindMaxOverlap function

I'm trying to create a function that, given two C strings, it spits back the number of consecutive character overlap between the two strings.
For example,
String 1: "Today is monday."
String 2: " is monday."
The overlap here would be " is monday.", which is 11 characters (it includes the space and '.').
If you need something more efficient, consider that a partial mismatch between Strings 1 and 2 means you can jump the length of the remainder of String 2 along String 1. This means you don't need to search the entirety of String 1.
Take a look at the Boyer-Moore algorithm. Though it is used for string searching, you could implement this algorithm for finding the maximum-length substring using String 2 as your pattern and String 1 as your target text.
There is probably a more efficient way to do this, but here's a simple approach:
#include <string.h>
int main() {
char s1[17] = "Today is monday.";
char s2[12] = " is monday.";
int max = 0;
int i_max = -1;
int j_max = -1;
int i = 0, j = 0, k=0;
int endl = 0, sl1, sl2;
char *ss1, *ss2;
for(i = 0; i < strlen(s1)-1; i++) {
ss1 = s1+i;
sl1 = strlen(ss1);
if(max >= sl1) {
break; // You found it.
}
for(j = 0; j < strlen(s2)-1; j++) {
ss2 = s2+j;
sl2 = strlen(ss2);
if(max >= sl2) {
break; // Can't find a bigger overlap.
}
endl = (sl1 > sl2)?sl2:sl1;
int n_char = 0;
for(k = 0; k < endl+1; k++) {
// printf("%s\t%s\n", ss1+k, ss2+k); // Uncomment if you want to see what it compares.
if(ss1[k] != ss2[k] || ss1[k] == '\0') {
n_char = k;
break;
}
}
if(n_char > max) {
max = n_char;
i_max = i;
j_max = j;
}
}
}
char nstr[max+1];
nstr[max] = '\0';
strncpy(nstr, s1+i_max, max);
printf("Maximum overlap is %d characters, substring: %s\n", max, nstr);
return 0;
}
Update: I have fixed the bugs. This definitely compiles. Here is the result: http://codepad.org/SINhmm7f
The problems were that endl was defined wrong and I wasn't checking for end-of-line conditions.
Hopefully the code speaks for itself.
Here is my solution, it will return the position of the overlap starting point, it's a bit complex, but that's how it's done in C:
#include <string.h>
int FindOverlap (const char * a, const char * b)
{
// iterators
char * u = a;
char * v = b;
char * c = 0; // overlap iterator
char overlapee = 'b';
if (strlen(a) < strlen(b)) overlapee = 'a';
if (overlapee == 'b')
{
while (*u != '\0')
{
v = b; // reset b iterator
c = u;
while (*v != '\0')
{
if (*c != *v) break;
c++;
v++;
}
if (*v == '\0') return (u-a); // return overlap starting point
}
}
else if (overlapee == 'a')
{
while (*v != '\0')
{
u = a; // reset b iterator
c = v;
while (*u != '\0')
{
if (*c != *u) break;
c++;
u++;
}
if (*v == '\0') return (v-b); // return overlap starting point
}
}
return (-1); // not found
}

Summing triplets in C

Okay so I have a file with a bunch of digits
002003005\n
001001\n
and I want to sum all the digits by three so the first lines sum would be 10 and the second line would be 2. Right now I'm not sure whats wrong with my control flow
#define MAXLINE 1000
int counter = 0;
int inputLine[MAXLINE] = {0};
int main(void)
{
int sum = 0;
int i = 0;
int ii = 0;
char c;
while ((c = getchar()) != EOF)
{
if (c == '\n')
{
for (ii = 0; ii < counter; ii = ii + 3)
{
sum = sum + ((inputLine[ii] - '0') * 100) + ((inputLine[ii+1] - '0') * 10) + ((inputLine[ii+2] - '0') * 1);
}
printf("%d\n", sum);
sum = 0;
counter = 0;
}
inputLine[i] = c;
i++;
counter++;
}
return 0;
}
You're not resetting i when you reach the end of a line.
Insert:
i = 0;
After the counter = 0 line.
You also need to include this block:
inputLine[i] = c;
i++;
counter++;
Within an else, since it shouldn't happen for the carriage return at the end of each line.
Once you've done that, you'll (hopefully) notice that i and counter will always contain the same value on each pass through the loop, so there's no need for them both to exist.
If your char type is unsigned by default then your end condition is not good
char c;
while ((c = getchar()) != EOF)
You should declare c as int, as EOF cannot be represented in the value range of 0..255. EOF is by definition a negative integer of type int used to indicate end-of-file conditions.

C code to convert hex to int

I am writing this code to convert a hex entry into its integer equivalent. So A would be 10 and B would be 11 etc. This code acts weirdly, in that it seg. faults at random locations and including an extra newline character at times will get it to work. I am trying to debug it, just so I can understand what I am doing wrong here. Can anyone take a look and help me here ? Thanks a lot for your time.
/* Fixed working code for anyone interested */
#include <stdio.h>
#include <stdlib.h>
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
int dec;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
if ( temp[i] == '\0')
{
return ;
}
if (temp[i] == '0' || temp[i] == 'x' || temp[i] == 'X' )
{
printf("0");
answer = temp[i];
}
// compare each temp[i] with all contents in hexchar[]
int j;
int a = temp[i];
for ( j=0; hexchar[j] != '\0'; j++)
{
if ( temp[i] == hexchar[j] )
{
answer *= 16;
answer = answer + 10 + (j/2);
// printf("%d\n",answer );
break;
}
}
}
return answer;
}
main()
{
char *test[] =
{ "bad",
"aabbdd"
"0100",
"0x1",
"0XA",
"0X0C0BE",
"abcdef",
"123456",
"0x123456",
"deadbeef",
"zog_c"
};
int answer=0;
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
printf("main():Number of chars = %d\n",numberOfChars);
int i;
// Go through each character and convert Hex to Integers.
for ( i = 0; i<numberOfChars;i++)
{
// Need to take the first char and then go through it and convert
it.
answer = hextoint(test[i]);
printf("%d\n",answer );
}
}
Let's take a look.
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
printf("In here");
printf("%c\t",temp[i] );
}
return answer;
}
This doesn't seem to even try to do any conversion. It should always return 0, since answer is never assigned any other value. Normally, you'd do something like:
for (i=0; input[i] != '\0'; i++) {
answer *= 16;
answer += digit_value(input[i]);
}
return answer;
Where digit_value (obviously enough) returns the value of an individual digit. One way to do this is:
int digit_value(char input) {
input = tolower(input);
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return -1; // signal error.
}
Then, looking at main:
main()
{
Depending on the "implicit int" rule is generally poor practice, at least IMO. It's much better to specify the return type.
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
This actually calculates the number of strings, not the number of chars.
for ( i = 0; i<=numberOfChars;i++)
Valid subscripts run from 0 through the number of items - 1, so this attempts to read past the end of the array (giving undefined behavior).
This'll work for any number within the unsigned int range, the nice thing is it does not use any other library functions so it is great for micro-controllers where space is tight.
unsigned int hexToInt(const char *hex)
{
unsigned int result = 0;
while (*hex)
{
if (*hex > 47 && *hex < 58)
result += (*hex - 48);
else if (*hex > 64 && *hex < 71)
result += (*hex - 55);
else if (*hex > 96 && *hex < 103)
result += (*hex - 87);
if (*++hex)
result <<= 4;
}
return result;
}
The problem is with calculating numberOfChars part. sizeof test is actually the size of the pointer, not the total length of all characters in your array, so the number returned in your code would be 1, which makes the for loop go to the second index of test (test[1]) which does not have a \0 at the end. Try using strlen for calculating numberOfChars.
This may not me the most optimal method, but it should work without problem.
unsigned int hex_to_int(const char* hex) {
unsigned int result = 0;
size_t len = strlen(hex);
for (size_t i = 0; i < len; ++i) {
char cur_char = tolower(hex[len - i - 1]);
// direct return if encounter any non-hex character.
if (!(isdigit(cur_char) && (cur_char >= 'a' && cur_char <= 'f'));)
return result;
unsigned int char_val = (isdigit(cur_char) ? cur_char - '0' : 10 + cur_char - 'a');
result += round(pow(16, i)) * char_val;
}
return result;
}

Resources