C Programming: How to determine an exact match between 2 numbers - c

I am trying to find the exact match between two numbers and have my counter stop at the first instance when they are not a match. However the code I have written counts the entire string length of my numbers. Is there an alternative way to do this?
Since my counter is starting from the first decimal place and not 0. , it counts to 15 but should stop at 10.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
int main(){
char str[100];
char buf[100];
double l,m,a,b;
int c,d,t,u,r,q;
int count =0;
l=59874.141715197809000;
m=59874.141715197817000;
a= (l - (int)l);
b= (m -(int)m);
sprintf(str,"%.15f",a);
sprintf(buf,"%.15f",b);
c = strlen(str);
d = strlen(buf);
for(t=3;t<c;t++){
for(u=3;u<d;u++){
if(str[t]==buf[u]){
count++;
break;
}
}
}
printf("matching decimal places = %d \n",count);
return 0;
}

First, when comparing two strings, you only need to iterate to the length of the smallest string if the two strings differ in length.. That is, if you want to count the amount of sequential character matches in a string.
For example:
A = 0.99997552
B = 0.9999753
would need one for loop to compare.. You would only iterate up to the length of B to determine that 6 decimals match. Why? Because going any further is irrelevant since none of the extra digits would exist in B. Iterating past the end of an array is undefined behaviour anyway.
In your case both buffers are the same length so no worries there, but again, the shorter string won't have the extra digits found in the longer string.. Hence: Iterate up to the smallest length.
The solution can be done as follows:
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main() {
//Create large enough buffer to hold 100 digits/characters..
char str[100] = {0};
char buf[100] = {0};
//Two doubles to be compared..
double l = 59874.141715197809000;
double m = 59874.141715197817000;
//Counter keeps track of matching digits..
int count = 0;
//Get rid of the base and keep only the decimals..
double a = (l - (int)l);
double b = (m - (int)m);
//Copy a maximum of 15 decimal places to `str` and `buf`
sprintf(str, "%.15f", a);
sprintf(buf,"%.15f", b);
//Get the length of both strings..
int c = strlen(str);
int d = strlen(buf);
//If C is smaller, iterate to length(c) else iterate to length(d).
for (int i = 2; i < (c < d ? c : d); ++i)
{
//If the two characters match, increment the count..
if (str[i] == buf[i])
{
++count;
}
}
//Print the amount of matching decimals..
printf("matching decimal places = %d \n", count);
return 0;
}

This may not be the answer, but do
if (number1 == number2)
{
// do something to stop it
}

Related

How to find if an int value contains a specific number?

Odd question, but I'm currently working on an assignment where I am asked to do the following:
Write a program that prompts the user for an integer between 1 and 1000, then prints from 1 to the entered number EXCEPT when the following conditions are met:
If the current number is a multiple of 3 OR contains a 3, print "Hello"
if the current number is a multiple of 7 OR contains a 7, print "Goodbye"
I understand how to determine if a number is a multiple of 3 or 7, but how would I determine if it contained a 3 or 7? I have all of my code written except for this part, and I am just a little lost and unsure what to do.
Thanks!
You should use mod % to find if somethings is dividable with 3 or 7.
To find the last digit of a number you should use mod 10 and then divide it by 10 to get the next digit.
The digits could also be obtained by using three nested loops from 0 to 10 with a break at final number or with a function like this:
#include <stdio.h>
int contains(unsigned long num,int x){
while(num){
if(num % 10 == x){
return 1;
}
num/=10;
}
return 0;
}
int main(){
printf("%d\n",contains(1237002,7));
printf("%d\n",contains(10000002,7));
printf("%d\n",contains(1234002,7));
printf("%d\n",contains(123002,7));
printf("%d\n",contains(7237002,7));
printf("%d\n",contains(1237007,7));
printf("%d\n",contains(7,7));
}
As #chux-ReinstateMonica suggested, you could print the integer to a buffer and then search for the '3' and '7' characters.
#include <string.h>
#include <stdbool.h>
bool contains_3_or_7(int num) {
char buffer[15];
sprintf(buffer,"%i",num);
return (strchr(buffer,'3') || strchr(buffer,'7'))
}
I think you must split the 2 parts:
First with your % comparaison which determine if it's a multiple like if (x % 7 == 0) (0 means x is a multiple of 7)
and for the seconde part convert your int into an str with itoa function or by coding your own like this:
char* itoa(int i, char b[]){
char const digit[] = "0123456789";
char* p = b;
if(i<0){
*p++ = '-';
i *= -1;
}
int shifter = i;
do{ //Move to where representation ends
++p;
shifter = shifter/10;
}while(shifter);
*p = '\0';
do{ //Move back, inserting digits as u go
*--p = digit[i%10];
i = i/10;
}while(i);
return b;
}
then you can determine for each condition if they are true or false

How to make my code take an input of numbers on one line separated by spaces between, and output the avg of non-repeated numbers?

My code:
#include <stdio.h>
int main()
{
int count = 0;
int size = 0;
float num[size];
int i = 0;
float avg = 0;
float sum = 0;
while (scanf("%f",&num) != EOF)
{
if ((num[i] != num[i+1]) && (num[i] != num[i-1]))
{
sum = sum + num[i];
size++;
}
}
avg = sum/size;
printf("%0.2f", avg);
}
My input and output:
//input
2
2
1
^Z
//output
1.67
Correct input and output:
2 2 1
^Z
1.50
My question:
1) How can I make my code prompt input of numbers all on one line separated with spaces in between each input? Right now, my code always starts a new line after entering a number.
2) How can I fix my code so that it only calculates the average of non-repeated numbers? (NOTE: my code has to run no slower than O(nlogn). ) So I can't use nested loops as it will then have a run time of O(n^2).
You have some problems in your code:
the usage of num
test on scanf
the test of already used number.
the usage of num
When you write
int size = 0;
float num[size];
You do not allocate memory to store numbers.
and
while (scanf("%f",&num) != EOF)
Is not correct since you are not storing the value read into a float: gcc warns:
warning: format ‘%f’ expects argument of type ‘float *’, but argument 2 has type ‘float (*)[(sizetype)(size)]’ [-Wformat=]
A more correct way to do would be to write:
float num;
...
while (scanf("%f",&num) != EOF)
test on scanf
You test that scanf does not return EOF, but what if your conversion failed if you do not give a number?
The correct way to test what the user gives, is to check that you have the number of conversion wanted:
while (scanf("%f",&num) == 1)
the test of already used number.
Writting
if ((num[i] != num[i+1]) && (num[i] != num[i-1]))
You test last number (i) against past and future number (?!)
You have a simplier approch: have an array to store the already got number. This imply to have a function to test a number has already been got.
Warning The current implementation of is_number_in_array it very naive and make your program run in O(n). You can easyly replace it with some dichotomic search which is O(log n)
So a corrected version of your code could be:
#include <stdio.h>
int is_number_in_array(float num, float *array, int size)
{
for (int i =0; i < size; ++i)
{
if (num == array[i])
return 1;
}
return 0;
}
#define MAX_NUMBER 50
int main(void)
{
/* number of number read */
int size = 0;
/* number already read */
float array[MAX_NUMBER] = {};
/* currently read number */
float num = 0;
float avg = 0;
float sum = 0;
/* get next number, stop when a conversion failed */
while (scanf("%f",&num) == 1)
{
/* test if number is already in array */
if (! is_number_in_array(num, array, size )) {
/* not in array: add it */
array[size ++] = num;
sum += num;
}
/* Add some test here to check that size is not as big as MAX_NUMBER */
}
avg = sum/size;
printf("%0.2f", avg);
return 0;
}
First, read the numbers into an array nums. Let n be the number of numbers in the array. This can be done in O(N). I leave this to you.
Secondly, sort the array using a O(N log N) algorithm. I leave this to you.
Finally, we can identify duplicates by simply consulting neighbours. The tricky part is avoiding going out of bounds. Accessing nums[-1] or nums[n] would result in Undefined Behaviour, so we have to avoid that.
We don't need to look ahead and backwards. We want to use a number the first time we encounter it, so we only need to look backwards.
Don't forget to make sure we have at least one number, because we can't divide by zero.
if (!n) {
fprintf(stderr, "Can't find the average of zero numbers.\n");
exit(1);
}
float sum = 0;
size_t uniques = 0;
for (size_t i=0; i<n; ++i) {
if (i > 0 && nums[i] == nums[i-1])
continue;
sum += nums[i];
++uniques;
}
float avg = sum/uniques;
The complexity analysis is O(N + N log N + N) = O(N log N).
(Both of the other answers include O(N^2) solutions
As an aside, we can do better than O(N log N).
In practical terms, inserting into a well-written hash table has an amortized performance of O(1), and lookups are O(1). We can use this to devise an O(N) solution to the problem.
Using Perl, since it has such hash tables built-in:
#nums
or die("Can't find the average of zero numbers.\n");
my %seen; # Hash table.
my $sum = 0;
my $uniques = 0;
for my $num (#nums) {
next if $seen{$num}++;
$sum += $num;
++$uniques;
}
my $avg = $sum/$uniques;
This approach saves all integers in an array, as long they are not saved already, as to avoid duplicates.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int bytes_read;
int size = 1000;
int i = 0;
int amount = 0;
int number = 0;
// boolean flag to detect duplicate numbers.
int duplicate = 0;
int sum = 0;
float unique_avg = 0;
// Allocate char / int arrays on the heap.
// These can be resized with realloc() if needed.
char* string = (char *) malloc (size);
int* unique_num = (int *) calloc (2 * size, 0);
// Declare char pointers to be used will splitting the string.
char* token;
char* rest = string;
printf ("Please enter a string: ");
bytes_read = getline (&string, &size, stdin);
// In case getline fails to get the input.
if (bytes_read == -1) {
puts ("error!");
}
// getline() read input succesfully.
else {
// Iterate over all space separated string tokens.
while ((token = strtok_r(rest, " ", &rest))){
// Convert string token to number
number = atoi(token);
for(i = 0; i < 2 * size; ++i){
if(number == unique_num[i]){
// Duplicate found.
duplicate = 1;
break;
}
}
if(!duplicate){
unique_num[amount] = number;
++amount;
}
// Restore value of duplicate for next iteration
duplicate = 0;
}
}
// Sum all unique numbers.
for(i = 0; i < amount; ++i){
sum += unique_num[i];
}
// Calculate the avg of unique numbers.
// Float casting is required for the fractional part of the division.
unique_avg = (float) sum / (float) (amount);
// Print the average.
printf("%f", unique_avg);
return 0;
}
Running this code in console yields with example input of 2 2 1:
Please enter a string: 2 2 1
1.500000

Generating a random code in c

I'm trying to generate a random 10-digit code, but even though I use the absolute value of every number in the code, it still sometimes prints a negative value
#include <stdio.h>
int main()
{
int i;
int r;
int barcode[11];
srand(time(NULL));
for(i=0;i <= 10;i++){
r = rand() % 10;
barcode[i] = abs(r);
}
printf("%d",barcode);
return 0;
}
Because you are actually printing the address of an integer array, not a string.
This line:
printf("%d",barcode);
Basically prints the address of barcode as a signed integer instead of the contents of barcode.
You of course could do this:
printf("%d%d%d%d%d%d%d%d%d%d",barcode[0], barcode[1], barcode[2], barcode[3], barcode[4], barcode[5], barcode[6], barcode[7], barcode[8], barcode[9]);
But perhaps a better way is to generate a string of characters instead of an array of integers. Quick mod to your code is to add to '0' to each random value in each interation of the loop and append to a char array.
int main()
{
int i;
int r;
char barcode[11]; // array of chars instead of ints
srand(time(NULL));
for(i=0; i < 10; i++) // loop 10 times, not 11
{
r = rand() % 10;
barcode[i] = '0' + r; // convert the value of r to a printable char
}
barcode[10] = '\0'; // null terminate your string
printf("%s\n",barcode);
return 0;
}
The above will generate a 10 digit code, with a small possibility of the first number being a leading zero. If that's not what you want, that's a simple bug fix. (Which I'll leave up to you...)

Converting int to char

Task is to get int using scanf("%d") then print it again using printf("%с") without standard functions like atoi , itoa .As i understood i need to divide all numbers then add \0 char and print it, however how can i divide it. I thought about loop for dividing number%10 + /0 and number/10 to decrease number for 1 character .
Therefore code should look smoothing like this
#include <conio.h>
#include <stdio.h>
main(void)
{
int number,reserve ;
char Array[50];
scanf_s("%d",&number);
if (number > 0 || number == 0)
{
do
{
reserve = number % 10;
printf("%c", reserve + '/0');
number /= 10;
} while (number != 0);
}
else
{
number *= -1;
printf("-");
do
{
reserve = number % 10;
printf("%c", reserve + '/0');
number /= 10;
} while (number != 0);
}
_getch();
return 0;
}
As well there can be negative number so i need some if statement to check if it is negative and in case it is loop should avoid it it so we won't get smthing like -%10
So i don't know if loop is correct (hope someone will fix it and explain me how it is supposed to be). Waiting for your advices.
One side effect of the line
number = number % 10;
is that you lose the original value of number. So when you go to do
number = number/10;
it would always get the value zero. To fix this, store the original value somewhere else, or use another variable to do your character conversion (modulo 10, then plus \0).
Also, your loop needs to be re-examined. This process of modulo, add \0, divide, repeat, should stop when the result of the division is zero (i.e. there are no more digits to print). Another thing to think about is: in what order are these digits being printed?
I'll leave it to you to to figure out how to determine if the value of an int is greater than or less than zero, since you didn't attempt that in this snippet.
this will help you, adopt for your purposes
#include <stdio.h>
int main() {
int a;
int i = 0;
int str_size = 0;
char str[11] = {};
char tmp;
scanf("%d", &a);
while (a) {
str[str_size++] = a % 10 + '0';
a /= 10;
}
str_size--;
while (i < str_size) { // rewind
tmp = str[i];
str[i++] = str[str_size];
str[str_size--] = tmp;
}
printf("%s", str);
return 0;
}

C program which is finding "happy" nums recursively

Hello guys i am trying to implement a program which is finding the happy numbers were between two numbers A and B.
Summing the squares of all the digits of the number, we replace the number with the outcome, and repeat the process. If after some steps the result is equal to 1 (and stay there), then we say that the number N is **<happy>**. Conversely, if the process is repeated indefinitely without ever showing the number 1, then we say that the number N is **<sad>**.
For example, the number 7 is happy because the procedure described above leads to the following steps: 7, 49, 97, 130, 10, 1, 1, 1 ... Conversely, the number 42 is sad because the process leads to a infinite sequence 42, 20, 4, 16, 37, 58, 89, 145, 42, 20, 4, 16, 37 ...
I try this right down but i am getting either segm faults or no results.
Thanks in advance.
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
void happy( char * A, int n);
int numPlaces (long n);
int main(void)
{
long A,B;
int npA;
char *Ap;
printf("Give 2 Numbers\n");
scanf("%li %li",&A,&B);
npA = numPlaces(A);
Ap = malloc(npA);
printf("%ld %d\n",A,npA);
//Search for happy numbers from A to B
do{
sprintf(Ap, "%ld", A);
happy(Ap,npA);
A++;
if ( npA < numPlaces(A) )
{
npA++;
Ap = realloc(Ap, npA);
}
}while( A <= B);
}
//Finds happy numbers
void happy( char * A, int n)
{
//Basic Condition
if ( n == 1)
{
if (A[0] == 1 || A[0] == 7)
printf("%c\n",A[0]);
printf("%s\n",A);
return;
}
long sum = 0 ;
char * sumA;
int nsum;
int Ai;
//Sum the squares of the current number
for(int i = 0 ; i < n;i++)
{
Ai = atoi(&A[i]);
sum = sum + (Ai*Ai);
}
nsum = numPlaces (sum);
sumA = malloc(nsum);
sprintf(sumA, "%li", sum);
happy(sumA,nsum);
free(sumA);
}
//Count digits of a number
int numPlaces (long n)
{
if (n < 0) return 0;
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}
Thanks for your time.
by the definition of your program sad numbers will cause your program to run forever
Conversely, if the process is repeated indefinitely
You need to add a stopping condition, like if I have looped for 1000 times, or if you hit a well known non terminating number (like 4) (is there a definite list of these? I dont know)
I find this solution tested and working..
Thanks for your time and I am sorry for my vagueness.
Every advice about this solution would be welcome
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
void happy( char * A, int n);
int numPlaces (long n);
int happynum = 0;
int main(void)
{
long A,B;
int npA;
char *Ap;
printf("Give 2 Numbers\n");
scanf("%li %li",&A,&B);
npA = numPlaces(A);
Ap = malloc(npA);
//Search for happy numbers from A to B
do{
sprintf(Ap, "%ld", A);
happy(Ap,npA);
if (happynum ==1)
printf("%s\n",Ap);
A++;
if ( npA < numPlaces(A) )
{
npA++;
Ap = realloc(Ap, npA);
}
}while( A <= B);
}
//Finds happy numbers
void happy( char * A, int n)
{
//Basic Condition
if ( n == 1)
{
if (A[0] == '3' || A[0] == '6' || A[0] == '9')
{
happynum = 0;
}
else
{
happynum = 1;
}
return;
}
long sum = 0;
char * sumA;
int nsum;
int Ai;
//Sum the squares of the current number
for(int i = 0 ; i < n;i++)
{
Ai = (int)(A[i]-48);
sum = sum + (Ai*Ai);
}
nsum = numPlaces (sum);
sumA = malloc(nsum);
sprintf(sumA, "%li", sum);
happy(sumA,nsum);
free(sumA);
}
//Count digits of a number
int numPlaces (long n)
{
if (n < 0) return 0;
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}
Your code uses some questionable practices. Yoe may be misguided because you are concerned about performance and memory usage.
When you allocate memory for the string, you forget to allocate one character for the null terminator. But you shouldn't be allocating, re-allocating and freeing constantly anyway. Dynamic memory allocation is expensive compared to your other operations.
Your limits are long, which may be a 32-bit or 64-bit signed integer, depending on your platform. The maximum number that can be represented with e 64-bit signed integer is 9,223,372,036,854,775,807. This is a number with 19 digits. Add one for the null terminator and one for a possible minus sign, so that overflow won't hurt, you and use a buffer of 21 chars on the stack.
You probably shouldn't be using strings inthe first place. Use the basic code to extract the digits: Split off the digit by taking the remainder of a division by 10. Then divide by 10 until you get zero. (And if you use strings with a fixed buffer size, as described above, you don't have to calculate the difits separately: sprintf returns the number of characters written to the string.
Your functions shouldn't be recursive. A loop is enough. As pm100 has noted, you need a termination criterion: You must keep track of the numbers that you have already visited. Each recursive call creates a new state; it is easier to keep an array, that can be repeatedly looked at in a loop. When you see a number that you have already seen (other than 1, of course), your number is sad.
Happy and sad numbers have this property that when your sum of squares is a number with a known happiness, the original number has this happiness, too. If you visit a known das number, the original number is sad. If you visit a known happy number, the original number is happy.
The limits of your ranges may ba large, but the sum of square digits is not large; it can be at most the number of digits times 81. In particular:
type max. number number of max. square sum dss
int 2,147,483,647 1,999,999,999 730
uint 4,294,967,295 3,999,999,999 738
long 9,223,372,036,854,775,807 8,999,999,999,999,999,999 1522
ulong 18,446,744,073,709,55,1616 9,999,999,999,999,999,999 1539
That means that when you take the sum of digit squares of an unsigned long, you will get a number that is smaller than 1540. Create an array of 1540 entries and mark all known happy numbers with 1. Then you can reduce your problem to taking the sum of digit squares once and then looking up the happiness of the number in this array.
(You can do the precalculation of the array once when you start the program.)

Resources