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;
}
Related
I wrote the following program to delete an array element entered by the user.
#include <stdio.h>
#include <conio.h>
void main() {
int j, i, a[100], n, key, l;
clrscr();
printf("Enter the number of elements:");
scanf("%d", &n);
printf("\nEnter the elements:\n");
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
printf("\nEnter the element to delete:");
scanf("%d", &key);
l = n; //Length of the array
for (i = 0; i < l; i++) {
if (a[i] == key) {
for (j = i; j < l; j++)
a[j] = a[j + 1];
l--; //Decreasing the length of the array
}
}
printf("\nThe new array is \n");
for (i = 0; i < l; i++)
printf("%d ", a[i]);
getch();
}
It works fine for most inputs but when the input is something like: 1 2 2 3 5 (here 2 repeats consecutively) and the element to be deleted is 2, the output is 1 2 3 5.
How can I modify the program such that all instances of the entered element is removed?
After l-- put i-- too as shown below
if(a[i]==key)
{
for(j=i;j<l;j++)
a[j]=a[j+1];
l--; //Decreasing the length of the array
i--; //check again from same index i
}
Other posters have given you 2 solutions ... I think understanding why it happens is good too :)
Let's take your example 1, 2, 2, 3, 5 and follow the code line by line
i = 0; /* first time through the loop; i "points" to 1 */
if (a[i] == 2) ... /* nope; next loop */
i = 1;
if (a[1] == 2) ... /* yes! let's go inside the if */
/* move all elements back
** and "decrease" array length */
/* array is now 1, 2, 3, 5 */
/* next loop */
i = 2;
if (a[i] == 2) ... /* nope; OH! Wait ...
** a[1] is the new 2 and it wasn't checked */
If you don't care about the order of the elements in the array, you can move the last element of the array into the newly formed gap (cunningly reducing the length of the array by one). This can be vastly more efficient than shunting the elements down: in computer science term this makes deleting an element O(1) rather than O(N).
a[i] = a[--l];
If your i index is looping over the array, you'll want to loop over this element again:
a[i--] = a[--l];
For example, to remove all elements '3' from an array of length 'l':
for (i = 0; i < l; ++i) {
if (a[i] == 3) {
a[i--] = a[--l];
}
}
If you do care about the order of the elements in the array, it's most efficient to use memmove rather than move elements by hand. It's designed to be used where the source and destination memory overlap.
memmove(a + i, a + i + 1, sizeof(a[0]) * (l - i - 1));
Change "if" to "while":
for(i=0;i<l;i++)
{
while (i<l && a[i]==key)
{
for(j=i;j<l;j++)
a[j]=a[j+1];
l--; //Decreasing the length of the array
}
}
use a new array.
int array[l];
int k=0;
for(i=0;i<l;i++)
{
if(a[i]!=key)
{
array[k]=a[i];
k++;
}
}
#include<stdio.h>
int main(){
int size;
int array[20];
int delete_pos;
int i;
printf("Enter the Size of the Array :");
scanf("%d",&size);
for(i=0;i<=size-1;i++){ //no of elements taken are 1 less than size of the array asked.
printf("\nEnter the element[%d] :",i+1);
scanf("%d",&array[i]);
}
printf("\nEnter the Position of the array to be deleted :");
scanf("%d",&delete_pos);
for(i=delete_pos-1;i<=size;i++){ //every element of the array is replaced by array on next position.
array[i]=array[i+1];}
size=size-1; // Reducing the size of the array as one element is deleted.
printf("Your new array is \n");
for(i=0;i<=size-1;i++){ //printing the entire new array.
printf("%d ",array[i]);
}
printf("\n\n");
return 0;
}
Your method with 2 nested for loops is too complicated. You can simple scan the array with an index i and copy all elements different from key with a different index len. The resulting array length is the final value of len.
Here is a modified version:
#include <stdio.h>
#include <conio.h>
int main(void) {
int a[100];
int i, n, key, len;
clrscr();
printf("Enter the number of elements: ");
if (scanf("%d", &n) != 1) {
printf("invalid input\n");
return 1;
}
if (n < 0 || n > 100) {
printf("invalid number of elements\n");
return 1;
}
printf("\nEnter the elements:\n");
for (i = 0; i < n; i++) {
if (scanf("%d", &a[i]) != 1) {
printf("invalid input\n");
return 1;
}
}
printf("\nEnter the element to delete: ");
if (scanf("%d", &key) != 1) {
printf("invalid input\n");
return 1;
}
for (i = len = 0; i < n; i++) {
if (a[i] != key)
a[len++] = a[i];
}
printf("\nThe new array is:\n");
for (i = 0; i < len; i++)
printf("%d ", a[i]);
printf("\n");
getch();
return 0;
}
Notes:
The prototype for main without arguments is int main(void) and it is considered good style to return 0 for success.
always test the return value of scanf(). This prevents many bugs and undefined behavior for invalid input. It also saves a lot of time looking in the wrong places when input was just invalid.
avoid naming a variable l as it looks too close to 1 in many fixed pitch fonts.
always terminate the program output with a newline.
So here is the problem: Write a program that accept an integer n, print out the largest number but smaller or equal n that is the product of two consecutive even number. Example: Input: 12, Output: 8 ( 2x4 )
Here is my code :
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for (int i = n; i >= 0; i--)
{
for (int j = 0; j <= n; j = j + 2)
{
if ( i == j * (j+2) )
{
printf("%d ", i);
break;
}
}
}
return 0;
}
So if i input 20, it will print out 8 and 0 instead of 8, if i input 30, it will print out 24,8 and 0 instead of just 24. How do i make it stop after printing out the first number that appropriate ?
You need to stop an outer loop from processing, for example by using a boolean flag (meaning "solution found, we finish work") or a goto statement.
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int solutionFound = 0;
for (int i = n; i >= 0; i--) {
// this could also be put into for's condition i.e. "i >= 0 && !solutionFound"
if (solutionFound) {
break;
}
for (int j = 0; j <= n; j = j + 2) {
if ( i == j * (j+2) ) {
printf("%d ", i);
solutionFound = 1;
break;
}
}
}
return 0;
}
EDIT: immediate return as noted in the comments is also a nice idea, if you don't need to do anything later.
Your problem is that you are nested - in a for loop which is inside another for loop - when you want to stop processing.
Some languages would let you code break 2; to indicate that you want to break out of 2 loops. Alas, C i snot such a language.
I would recommend that you code a function. That would serve a few porpoises: 1) your main should be "lean & mean" 2) as your programs get larger, you will learn the benefits of putting individual coding tasks into functions 3) you can use return; instead of break; and it will exit the function immediately.
Something like this:
#include <stdio.h>
void FindNeighbouringDivisors(int n)
{
for (int i = n; i >= 0; i--)
{
for (int j = 0; j <= n; j = j + 2)
{
if ( i == j * (j+2) )
{
printf("%d times %d = %d", j, j + 2, i);
return;
}
}
}
printf("There are no two adjacent even numbers which can be multiplied to give %d", n);
}
int main()
{
int n;
scanf("%d", &n); /* could get from comamnd line */
FindNeighbouringDivisors(n);
return 0; /* should be EXIT_SUCCESS */
}
Btw, when you have a problem with your code, ask a question here. When you have it working, consider posting it at our code review site where more experienced programmers can give you advice on how to improve it. It's a great way to learn
Break only breaks you out of immediate loop, so either use flags or just use return to terminate the execution. Or you can even use following code:
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for (int j = 0; j <= n; j = j + 2)
{
if ( n < j * (j+2) )
{
printf("%d ", j*(j-2));
break;
}
}
return 0;
}
I am doing a problem about checking monotonic sequences. The problem is inputting a sequence and then print "YES" if it is monotonic, "NO" if it is not.
This is my code:
#include <stdio.h>
int main()
{
//Inputting the sequence
int n;
scanf("%d", &n);
int a[n];
for (int i = 1; i <= n; i++)
{
scanf("%d ", &a[i]);
}
//Checking monotonic sequence
for (int i = 1; i <= n; i++)
{
if ((a[i] > a[i-1]) && (a[i] > a[i+1]))
{
printf("NO");
return;
}
else if ((a[i] < a[i-1]) && (a[i] < a[i+1]))
{
printf("NO");
return;
}
}
printf("YES");
return 0;
}
I have failed 2 test case with sequences [1, 2, 3] and [10, 6, 4, 2, 1, -100]; and passed one test case with [1, 2, 3, 3, 2, 1]. Can anyone please point out the problem in my code? I would truly appreciate that. Thank you.
Remove trailing " ". It obliges additional input (or end-of-file) after the number is entered before scanf() returns.
// scanf("%d ", &a[i]);
scanf("%d", &a[i]);
In addition to index problems in 2 places, code needs to look for overall monotonic and not just local monotonic behavior.
bool up = true;
bool down = true;
// for (int i = 1; i <= n; i++)
for (int i = 1; i < n; i++) {
if (a[i] > a[i-1]) down = false;
if (a[i] < a[i-1]) up = false;
}
printf((up || down) ? "YES" : "NO");
Additional code to short-circuit loop.
// for (int i = 1; i < n; i++) {
for (int i = 1; i < n && (up || down); i++) {
Further there is lack of the coding goal clarity on tie cases. May need
if (a[i] >= a[i-1]) down = false;
if (a[i] <= a[i-1]) up = false;
a has indices from 0 to n-1; you code references a[0] (which never gets assigned to) and a[n] (which is outside the bounds of the array).
You are checking with invalid array index. here you are declaring an array size of n but you are checking with i+1 that means n+1 for the last case. This is out of bound for your array. First of all you are storing data in array from 1 to n . But when you declare a array size n then it has index from 0 to n-1.so you can store data from 0 to n and start the check from 1 and end in n-1.
this one will work for you:
#include <stdio.h>
int
main ()
{
//Inputting the sequence
int n;
scanf ("%d", &n);
int a[n];
for (int i = 0; i < n; i++)
{
scanf ("%d", &a[i]);
}
int inc = 0;
int dec = 0;
//Checking monotonic sequence
for (int i = 1; i < n ; i++)
{
if (a[i] > a[i - 1])
{
inc = 1;
}
else if (a[i] < a[i - 1])
{
dec = 1;
}
}
if (inc == 1 && dec == 1)
{
printf ("NO");
}
else
{
printf ("YES");
}
return 0;
}
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.
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;
}