Why does this ISBN checking code turn '0' into 45? - c

Can you help me find out why the second 0 in the array turns into 45 please.
Everything is okay but except this number makes the result goes wrong. I cannot find out what's the matter with this.
Here is my code:
#include <stdio.h>
int getuserchoice() {
int n;
printf("---ISBN Validate---");
printf("\n1-ISBN Checking");
printf("\n2-Quit");
printf("\nSelect: ");
scanf("%d", &n);
return n;
}
int main() {
long a[10];
long sum = 0;
int i = 0, n = 1;
long x;
if (getuserchoice() == 1) {
printf("\nEnter the values for ISBN number : ");
scanf("%ld", &x);
if (x > 0) {
while (x > 0) {
a[i] = x % 10;
x = x / 10;
i++;
}
}
for (i = 0; i < 10; i++)
printf("%ld\t", a[i]);
for (i = 0; i < 10; i++) {
sum += a[i] * n;
n++;
}
if (sum % 11 == 0)
printf("\nISBN Status: Valid!");
else
printf("\nISBN Status: Invalid!");
} else
printf("\nSee you later!");
getchar();
return 0;
}

By default uninitialized arrays contain garbage (literally anything). It so happens that that particular element contains 45 (amazing, isn't it?).
It stays 45 because leading 0s are discarded when reading a number (you should read it as a string (C++) or char[]), so you are never accessing that particular array element to give it a meaningful value.
Here's SO post on how to initialize an array with 0s in C.

Related

C Programming array with repetition

I wrote a program that examines whether a number in a sequence is repeated 2 times (so many times it should be repeated) if it is repeated 2 times "YES", if not "NO". I think this can be written in a simpler and better way, so I'm interested in the suggestions and corrections of someone more experienced than me.
The program should print YES if each member of array is repeated exactly once, and otherwise it should print NO:
Enter the number of array: 8
Enter the sequence: 1 2 2 1 3 3 4 4
YES
Enter the number of string members: 7
Enter the string: 1 2 1 2 1 3 4
NO
Here is my code:
#include <stdio.h>
#define arr 100
int main() {
int n, i, p = 1, j, a;
double array[arr];
int num[100];
do {
printf("Enter the number of array: ");
scanf("%d", &n);
} while (n < 1 || n > 100);
printf("Enter array: ");
for (i = 0; i < n; i++) {
scanf("%lf", &array[i]);
num[i] = -1;
}
for (i = 0; i < n; i++) {
a = 1;
for (j = i + 1; j < n; j++) {
if (array[i] == array[j]) {
a++;
num[j] = 0;
}
}
if (num[i] != 0)
num[i] = a;
}
for (i = 0; i < n; i++) {
if (num[i] == 0)
continue;
if (num[i] != 2) {
p = 0;
break;
}
}
if (p == 1)
printf("YES");
else
printf("NO");
return 0;
}
I am going to provide a code review here because the code doesn't work and that makes it off-topic on Code Review.
Good things about the code:
There are no global variables.
There is an attempt to define a symbolic constant for the array size.
Things that can be improved:
Declare the variables are you need them. In the original version of C back in the 1970s and 1980s variables had to be declared at the top of the function. That is no longer the case, and a recommended programming practice to declare the variable as needed. In C the language doesn't provide a default initialization of the variable so variables should be initialized as part of the declaration. For readability and maintainability each variable should be declared and initialized on its own line.
Capitalize the constants, arr should be ARR.
ARR should be used in the declaration of num as well as the declaration of array.
ARR should be used instead of 100 in this statement while (n < 1 || n > 100).
Since the program only allows a single digit to be read at a time, array should be an array of integers rather than array of doubles.
There is only one error check on user input.
A simplified version of the program that does work:
One of the first things you need to learn in programming is how to write functions and subroutines. This is important because it allows you to break problems into smaller and smaller pieces until it is very easy to solve the problem. There are a number of programming principles that this relates to, 2 of them are the Single Responsibility Principle states:
that every module, class, or function should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by that module, class or function.
and the KISS Principle (Keep It Simple).
#include <stdio.h>
#include <stdbool.h>
#define ARR 100
static int get_user_input(int array[ARR])
{
int count = 0;
do {
printf("Enter the number of array: ");
scanf("%d", &count);
} while (count < 1 || count > ARR);
printf("Enter array: ");
for (int i = 0; i < count; i++) {
scanf("%1d", &array[i]);
}
return count;
}
static bool find_first_repetition(int count, int array[ARR])
{
bool repetition = false;
for (int i = 1; i < count; i++)
{
if (array[i - 1] == array[i])
{
return true;
}
}
return repetition;
}
int main() {
int n;
int num[ARR];
n = get_user_input(num);
if (find_first_repetition(n, num))
{
printf("YES");
}
else
{
printf("NO");
}
return 0;
}
Your code works, but there are some issues:
you should test for conversion failures in scanf(): the return value must be 1 as there is a single conversion for each scanf() call.
the counting loops are too complicated: just counting the number of occurrences with 2 nested loops is much simpler and has comparable time complexity, and using a += (array[i] == array[j]); may produce fast branchless code on most architectures.
it is good style to finish the program output with a newline.
Here is a modified version:
#include <stdio.h>
int main() {
int n;
do {
printf("Enter the length of the array: ");
if (scanf("%d", &n) != 1)
return 1;
} while (n < 1 || n > 100);
double array[n];
printf("Enter array: ");
for (int i = 0; i < n; i++) {
if (scanf("%lf", &array[i]) != 1)
return 1;
}
int p = 1;
for (int i = 0; i < n; i++) {
int a = 0;
for (int j = 0; j < n; j++) {
a += (array[i] == array[j]);
}
if (a != 2) {
p = 0;
break;
}
}
if (p == 1)
printf("YES\n");
else
printf("NO\n");
return 0;
}

Program to print sum of primes in C

#include <stdio.h>
#include <math.h>
int main() {
int n, count, sum;
printf("Enter upper bound n \n");
scanf("%d", &n);
for (int a = 1; a <= n; a++) {
count = 0;
sum = 0;
for (int i = 2; i <= sqrt(a); ++i) {
if (a % i == 0) {
count++;
break;
}
}
if (count == 0 && a != 1) {
sum = a + sum;
}
}
printf("%d", sum);
}
The program is my attempt to print summation of primes < n. I am getting sum = 0 every time and I am unable to fix this issue.
The reason you do not get the sum of primes is you reset the value of sum to 0 at the beginning of each iteration. sum will be 0 or the value of the n if n happens to be prime.
Note also that you should not use floating point functions in integer computations: i <= sqrt(a) should be changed to i * i <= a.
The test on a != 1 can be removed if you start the loop at a = 2.
Here is a modified version:
#include <stdio.h>
int main() {
int n = 0, sum = 0;
printf("Enter upper bound n: \n");
scanf("%d", &n);
// special case 2
if (n >= 2) {
sum += 2;
}
// only test odd numbers and divisors
for (int a = 3; a <= n; a += 2) {
sum += a;
for (int i = 3; i * i <= a; i += 2) {
if (a % i == 0) {
sum -= a;
break;
}
}
}
printf("%d\n", sum);
return 0;
}
For large values of n, a much more efficient approach would use an array and perform a Sieve of Eratosthenes, a remarkable greek polymath, chief librarian of the Library of Alexandria who was the first to compute the circumference of the earth, 2300 years ago.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int n = 0;
long long sum = 0;
if (argc > 1) {
sscanf(argv[1], "%i", &n);
} else {
printf("Enter upper bound n: \n");
scanf("%i", &n);
}
// special case 2
if (n >= 2) {
sum += 2;
}
unsigned char *p = calloc(n, 1);
for (int a = 3; a * a <= n; a += 2) {
for (int b = a * a; b < n; b += a + a) {
p[b] = 1;
}
}
for (int b = 3; b < n; b += 2) {
sum += p[b] * b;
}
free(p);
printf("%lld\n", sum);
return 0;
}
Error about sum getting set to zero inside the loop has been already pointed out in previous answers
In current form also, your code will not return zero always. It will return zero if value of upper bound is given as non prime number. If prime number is given as upper bound, it will return that number itself as sum.
As mentioned in comment you should initialize sum before first loop something like
int n, count, sum=0;
or you can initialize sum in the loop like
for(a=1,sum=0;a <= n; a++)
and remove sum=0; inside the first loop because it changes sum to 0 every time first loop executes. You can check this by inserting this lines to your code
printf("Before sum %d",sum);
sum = 0;
printf("After Sum %d",sum);
make sure sure that if you are initializing sum in the loop, define "a" in outer of the loop if not the sum goes to local variable to for loop and it hides the outer sum.

Find the longest arithmetic progression from an array

I have an array of numbers ex.[5,1,2,4,6,8,12], and I want to find the length of longest arithmetic progression within the sequence and to print it. Longest arithmetic progression means an increasing sequence with common difference, in this case [2,4,6,8].
#include <stdio.h>
void main()
{
int array[100], i, num,diff;
printf("Enter the size of an array \n");
scanf("%d", &num);
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
scanf("%d", &array[i]);
}
printf("\n Numbers in a.p: ");
for (i = 0; i < num; i++) {
diff = array[i+1]-array[i];
if (array[i]-diff == array[i+1]-diff);
{
printf("%d, ", array[i]);
}
}
printf("\n Common difference:%d", diff);
}
like this
#include <stdio.h>
int main(void){
#if DEBUG
int array[] = {5,1,2,4,6,8,12};
int num = sizeof(array)/sizeof(*array);
int i, diff;
#else
int array[100], i, num,diff;
printf("Enter the size of an array \n");
scanf("%d", &num);
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
scanf("%d", &array[i]);
}
#endif
int j, len, longest_len = 2, longest_i = 0;
for (i = 0; i < num - longest_len; i += len-1) {
diff = array[i+1]-array[i];
for(j = i+2; j < num && array[j-1]+diff == array[j]; ++j);
len = j - i;
if(longest_len < len){
longest_len = len;
longest_i = i;
}
}
printf("\n Numbers in a.p: ");
diff = array[longest_i+1] - array[longest_i];
printf("[ ");
for(i = 0; i < longest_len; ++i){
printf("%d", array[longest_i + i]);
if(i == longest_len-1)
printf(" ]\n");
else
printf(", ");
}
printf("\n Common difference:%d", diff);
}
Since this seems to be a homework or challenge I will only help by solving your immediate problems, caused by very strange code.
Here is code which at leat detects the progressions correctly.
You can yourself count the length, store the longest length and its index, then print that sequence after parsing all the array.
There are two assumptions here, which you might want to avoid for challenge/homework:
no identical numbers entered
no overlapping progressions,
i.e. no number is the last of one and the first of next progression
The representation of more than one sequence in the output is a little jittery (missing ")"), but that is not relevant for finding and exclusively printing the longest one.
I did not bother about your ratio output, no idea what that is supposed to be.
Code:
#include <stdio.h>
// avoid a warning
int main() {
int array[100], i, num, diff=0, lastdiff=0, first=1;
printf("Enter the size of an array \n");
// for good code, this should check the result
scanf("%d", &num);
// in case of scaf-failure, cleanup here for good code
// asking for the number of elements
// and then relying on that number to be entered
// is less elegant than checking for and end condition
// like EOF or negative input
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
// for good code, this should check the result
scanf("%d", &array[i]);
// in case of scaf-failure, cleanup here for good code
}
printf("\n Numbers in a.p: ");
for (i = 1; i < num; i++) {
lastdiff=diff;
diff = array[i]-array[i-1];
if (diff==lastdiff)
{ if(first==1)
{ first=0;
printf("(%d, %d",array[i-2], array[i-1]);
}
printf(", %d", array[i]);
} else
{ first=1;
}
}
printf(")\n Ratio:%d", diff);
// avoid a warning
return 0;
}
There are a number of ways to approach this challenge. You can either check each diff against each value in the array or work the other way around. Given you are not sorting the values, you may benefit by nesting the check of values within your loop over all possible diffs. Something similar to the following works:
#include <stdio.h>
int main (void) {
int a[] = {5, 1, 2, 4, 6, 8, 12},
n = sizeof a / sizeof *a,
startidx = 0,
maxlen = 0;
for (int d = 1; d < n; d++) { /* loop over diffs */
int idx = -1,
len = 1;
for (int i = 1; i < n; i++) /* loop over values */
if (a[i - 1] + d == a[i]) {
if (idx < 0) /* if index not set */
idx = i - 1; /* set to 1st index */
len++; /* increment length */
}
if (idx >= 0 && len > maxlen) { /* if progression found */
maxlen = len; /* save length */
startidx = idx; /* save start index */
}
}
printf ("longest progression: '%d' elements.\n", maxlen);
for (int i = 0; i < maxlen; i++)
printf (i ? ", %d" : "%d", a[startidx + i]);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/maxprogression
longest progression: '4' elements.
2, 4, 6, 8
Investigate several ways to approach it, and finally settle on the one that makes the most sense to you. You can work on optimizing later.
As far as the code you posted goes, always validate all user input by, at minimum, checking that the number of expected conversions to type took place, e.g.
if (scanf("%d", &num) != 1) {
fprintf (stderr, "error: input conversion failed for 'num'.\n");
return 1;
}
You would do the same in your values loop. Let me know if you have any questions. Good luck with your coding.
Following is the complete working code. You can see it working here:
#include <stdio.h>
int main()
{
int array[100], i, num,diff, resDiff, startIndx, resStartIndx, countCur, countPre;
printf("Enter the size of an array \n");
scanf("%d", &num);
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
scanf("%d", &array[i]);
}
//Now code changes
startIndx =0, resStartIndx=0, countPre=0, resDiff=0;
for (i = 0; i < num; /*No increment required here*/) {
countCur =0;
startIndx=i;
countCur++;
if(++i < num)
{
diff = array[i] - array[startIndx];
countCur++;
i++;
while((i < num) && (diff == (array[i] - array[i-1])))
{
countCur++;
i++;
}
if(countCur > countPre)
{
resStartIndx = startIndx;
countPre = countCur;
resDiff = diff;
}
}
}
countPre += resStartIndx;
printf("\n Numbers in a.p: ");
for (i = resStartIndx; i < countPre; i++) {
printf("%d, ", array[i]);
}
printf("\n Common difference:%d", resDiff);
return 0;
}

Need to find Max, Min, Avg number in Array - no size declared

So I have this array, I need to find the Min, Max, and Average. I have figured out how to get the Max, my code looks right for the minimum but it does not work so I must be missing something. I also need to find the average of the numbers entered. Everything I can find on this only works when you have the size of the array set. I have a max size set for the array but it does not get filled by user input. I have been staring and testing on this for days and still cant figure it out.
I know for the average I need something like (with added declartions at the top), but I cannot figure out how to get it to work:
for (i = 0; i < numOfGrades; i++) {
sum += grades[i];
}
avg = (double) sum / numOfGrades;
Here is the rest of my code:
#include <stdio.h>
int main(){
int grades [100];
int i = 0;
int small, big, input;
printf("Enter a series of grades. When done, enter any number above 100.\n\n");
while (i <= 100) { //while loop to set maximum for array
printf("Enter grade:");
if (scanf("%d", &input) == 1) {
if (input >= 0 && input <=100) {
grades[i] = input; //if good, add to array
i++;
}
else {
printf("\n\nExiting entry.\n");
printf("\n\nGrades entered:\n\n");
i = i - 1;
break; //exiting loop
}
}
}
int x, y;
for (x = 0; x <= i; x++) {
printf("Grade: %d\n", grades[x]); //print array
}
big = small = grades[0];
for (y = 0; y < i; y++) {
if (grades[y] > big) {
big = grades[y];
}
else if (grades[y] < small) {
small = grades[y];
}
}
printf("Highest number : %d\n", big);
printf("Smallest number: %d\n", small);
return 0;
}
Here you do the right thing:
for (x = 0; x <= i; x++) {
Because x <= i will take you from 0 to the value of i. Then in your min/max loop you do this:
for (y = 0; y < i; y++) {
So you are going from 0 to to i-1. You have 2 options:
Make the above loop correct with y <= i.
Dont decrement i in the while loop (Dont do this i = i - 1;) That way, i represents the number of numbers entered, instead of number of numbers entered -1 (you will need to fix the x <= i to x < i).
Here is a live example. http://ideone.com/ZEaDue
To calculate the average, you are doing the right thing, you can re-use i though:
int sum = 0, avg = 0;
for (y = 0; y < i; y++) {
sum += grades[y];
}
avg = (double) sum / i;
printf("Avg: %d\n", avg);
Actually you do have the number of grades
if (scanf("%d", &input) == 1) {
if (input >= 0 && input <=100) {
grades[i] = input; //if good, add to array
i++;
}
else {
numOfGrades=i;
printf("\n\nExiting entry.\n");
printf("\n\nGrades entered:\n\n");
i = i - 1;
break; //exiting loop
}
As for the minimum, your logic should be like this:
for (y = 0; y < numOfEdges; y++) {
if (grades[y] > big) {
big = grades[y];
}
if (grades[y] < small) {
small = grades[y];
}
}
The else statement I removed should do the trick. Also I would always use
for(int var = 0; var < numOfEdges; var++) in any of the loop constructs. It's easyer to follow the logic this way: You have counted the number of edges (numOfEdges), but your loop goes only to numOfEdges-1 since you start with index 0.

Most frequent element in a sequence using arrays in C

I'm doing an online course on "Programming, Data Structure & Algorithm". I've been given an assignment to "find the most frequent element in a sequence using arrays in C (with some constraints)". They've also provided some test-cases to verify the correctness of the program. But I think I'm wrong somewhere.
Here's the complete question from my online course.
INPUT
Input contains two lines. First line in the input indicates N,
the number of integers in the sequence. Second line contains N
integers, separated by white space.
OUTPUT
Element with the maximum frequency. If two numbers have the
same highest frequency, print the number that appears first in the
sequence.
CONSTRAINTS
1 <= N <= 10000
The integers will be in the range
[-100,100].
And here's the test cases.
Test Case 1
Input:
5
1 2 1 3 1
Output:
1
Input:
6
7 7 -2 3 1 1
Output:
7
And here's the code that I've written.
#include<stdio.h>
int main()
{
int counter[201] = {0}, n, i, input, maximum = 0;
scanf("%d", &n);
for(i = 1; i <= n; i++) {
scanf("%d", &input);
if(input < -100 && input < 100)
++counter[input];
}
maximum = counter[0];
for (i = 1; i < 201; i++) {
if (counter[i] > maximum) {
maximum = counter[i];
}
}
printf("%d", maximum);
return 0;
}
Please tell me where I'm wrong. Thank you.
EDIT:
I've modified the code, as suggested by #zoska. Here's the working code.
#include<stdio.h>
int main()
{
int counter[201] = {0}, n, i, input, maximum = 0;
scanf("%d", &n);
for(i = 1; i <= n; i++) {
scanf("%d", &input);
if(input < 100 && input > 0)
++counter[input + 100];
else
++counter[input];
}
maximum = counter[0];
for (i = 0; i < 201; i++) {
if (counter[i] > maximum) {
maximum = i - 100;
}
}
printf("%d", maximum);
return 0;
}
Additionally to problem pointed out by Paul R is:
You are printing maximum occurrences of number, not the number itself.
You're going to need another variable, which will store the number with maximum occurences. Like :
maximum = count[0];
int number = -100;
for (i = 0; i < 201; i++) {
if (counter[i] > maximum) {
maximum = counter[i];
number = i - 100;
}
}
printf("number %d has maximum occurences: %d", number, maximum);
Also you should iterate through an array from 0 to size-1:
So in all cases of your loops it should be :
for(i = 0; i < 201; i++)
Otherwise you won't be using count[0] and you will only have a range of -99...100.
Try below code
#include<stdio.h>
int main()
{
int counter[201] = {0}, n, i, input, maximum = 0;
scanf("%d", &n);
for(i = 1; i <= n; i++) {
scanf("%d", &input);
if(input >= -100 && input <= 100)
++counter[input + 100];
}
maximum = counter[0];
int index = 0;
for (i = 0; i < 201; i++) {
if (counter[i] >= maximum) {
index = i;
maximum = counter[i];
}
}
printf("number %d occured %d times\n", index-100, maximum);
return 0;
}
I would prefer checking in one loop itself for the maximum value just so that the first number is returned if i have more than one element with maximum number of occurances.
FInd the code as:
#include<stdio.h>
int main()
{
int n,input;
scanf("%d",&n);
int count[201] ={0};
int max=0,found=-1;
for(int i=0;i<n;i++)
{
scanf("%d",&input);
count[input+100]++;
if(max<count[input+100])
{
max= count[input+100];
found=input;
}
}
printf("%d",found);
return 0;
}
But, there is also one condition that if the number of occurance are same for two numbers then the number which appers first in sequence should appear.

Resources