Having trouble with forever loop - c

#include <stdio.h>
int main(){
int n,copy,counter=0,prevcounter,prev;
scanf("%d",&n);
while(n>0){
counter = 0;
n--;
copy = n;
while(copy>0){
--copy;
if(n%copy==0){
counter++;}
if(copy==0)break;
}
if(counter>prevcounter){
prevcounter = counter;
prev = n;
}
}
printf("%d",prev);
}
So here is my code:The problem is that this code goes to forever loop and the problem is right here
while(copy>0)
but if i change it to
while(copy>1)
It is working....I am trying to get why it is going to forever loop but i cant find the answer..I am decremending copy and when it gets 0 it should break from the loop..I even added another check
if(copy==0)break;
but still it didnt work..Any sugestions?Thanks

You are using % when copy=0 also. It is a bug leading to undefined behavior.(Divide by zero).
prevcounter is uninitialized.
Code will be something like this:-
#include <stdio.h>
int main(){
int n,copy,counter=0,prevcounter=0,prev;
scanf("%d",&n);
while(n>0)
{
counter = 0;
n--;
copy = n;
while(copy>0)
{
--copy;
if(copy && n%copy==0){
counter++;
}
}
if(counter>prevcounter){
prevcounter = counter;
prev = n;
}
}
printf("%d",prev);
}
You needed to consider all the values of the copy that may come up during execution. Here in the loop you will exclude the cases when copy becomes zero and if(copy && n%copy==0) ensures that.

Related

A function in C runs for a set of values but gives Segmentation Fault: 11 for another

I am trying to find unique non-zero intersection between two sets. I have written a program which works for some set of arrays but gives segmentation fault for some. I have been trying to figure out why but have failed, any help will be greatly valued. The thing is the functions defined (NoRep and ComEle) are working fine but are unable to return the value to the assigned pointer in the case when Seg Fault is shown. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check complete\n");
// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check complete\n");
}
//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
// Have to remove repeating elements.
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:\t%d\n", CE[i]);}
printf("ComEle: %p\n",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];
}
}
NR[0] = cnt; // First element: # of relevant elements.
printf("NoRep: %p\n",NR);
return(NR);
}
Thanks again for your help!
Take a look at this code:
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
Here you have nested loops, i.e. a for-loop with a while-loop inside. So - in worst case - how many times can cnt1 be incremented?
The answer is size_ar1 * size_ar2
But your code only reserve size_ar1 + size_ar2 element for CE1. So you may end up writing outside the array.
You can see this very easy by printing cnt1 inside the loop.
In other words - your CE1 is too small. It should be:
int temp1 = size_ar1*size_ar2; // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
But be careful here - if the input arrays are big, the VLA gets huge and you may run in to stack overflow. Consider dynamic memory allocation instead of an array.
Besides the accepted answer: I have been missing a break statement in the while loop in ComEle function. It was not giving me the expected value of cnt1. The following will be the correct way to do it:
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}
This will also do away with the requirement for a bigger array or dynamic allocation as suggested (and rightly so) by #4386427

Understanding returning values functions C

I'm trying to understand how the return value of a function works, through the following program that has been given to me,
It goes like this :
Write a function that given an array of character v and its dim, return the capital letter that more often is followed by its next letter in the alphabetical order.
And the example goes like : if I have the string "B T M N M P S T M N" the function will return M (because two times is followed by N).
I thought the following thing to create the function:
I'm gonna consider the character inserted into the array like integer thank to the ASCII code so I'm gonna create an int function that returns an integer but I'm going to print like a char; that what I was hoping to do,
And I think I did, because with the string BTMNMPSTMN the function prints M, but for example with the string 'ABDPE' the function returns P; that's not what I wanted, because should return 'A'.
I think I'm misunderstanding something in my code or into the returning value of the functions.
Any help would be appreciated,
The code goes like this:
#include <stdio.h>
int maxvolte(char a[],int DIM) {
int trovato;
for(int j=0;j<DIM-1;j++) {
if (a[j]- a[j+1]==-1) {
trovato=a[j];
}
}
return trovato;
}
int main()
{
int dim;
scanf("%d",&dim);
char v[dim];
scanf("%s",v);
printf("%c",maxvolte(v,dim));
return 0;
}
P.S
I was unable to insert the value of the array using in a for scanf("%c,&v[i]) or getchar() because the program stops almost immediately due to the intepretation of '\n' a character, so I tried with strings, the result was achieved but I'd like to understand or at least have an example on how to store an array of character properly.
Any help or tip would be appreciated.
There are a few things, I think you did not get it right.
First you need to consider that there are multiple pairs of characters satisfying a[j] - a[j+1] == -1
.
Second you assume any input will generate a valid answer. That could be no such pair at all, for example, ACE as input.
Here is my fix based on your code and it does not address the second issue but you can take it as a starting point.
#include <stdio.h>
#include <assert.h>
int maxvolte(char a[],int DIM) {
int count[26] = {0};
for(int j=0;j<DIM-1;j++) {
if (a[j] - a[j+1]==-1) {
int index = a[j] - 'A'; // assume all input are valid, namely only A..Z letters are allowed
++count[index];
}
}
int max = -1;
int index = -1;
for (int i = 0; i < 26; ++i) {
if (count[i] > max) {
max = count[i];
index = i;
}
}
assert (max != -1);
return index + 'A';
}
int main()
{
int dim;
scanf("%d",&dim);
char v[dim];
scanf("%s",v);
printf("answer is %c\n",maxvolte(v,dim));
return 0;
}
#include <stdio.h>
int maxvolte(char a[],int DIM) {
int hold;
int freq;
int max =0 ;
int result;
int i,j;
for(int j=0; j<DIM; j++) {
hold = a[j];
freq = 0;
if(a[j]-a[j+1] == -1) {
freq++;
}
for(i=j+1; i<DIM-1; i++) { //search another couple
if(hold==a[i]) {
if(a[i]-a[i+1] == -1) {
freq++;
}
}
}
if(freq>max) {
result = hold;
max=freq;
}
}
return result;
}
int main()
{
char v[] = "ABDPE";
int dim = sizeof(v) / sizeof(v[0]);
printf("\nresult : %c", maxvolte(v,dim));
return 0;
}

Count of similar characters without repetition, in two strings

I have written a C program to find out the number of similar characters between two strings. If a character is repeated again it shouldn't count it.
Like if you give an input of
everest
every
The output should be
3
Because the four letters "ever" are identical, but the repeated "e" does not increase the count.
For the input
apothecary
panther
the output should be 6, because of "apther", not counting the second "a".
My code seems like a bulk one for a short process. My code is
#include<stdio.h>
#include <stdlib.h>
int main()
{
char firstString[100], secondString[100], similarChar[100], uniqueChar[100] = {0};
fgets(firstString, 100, stdin);
fgets(secondString, 100, stdin);
int firstStringLength = strlen(firstString) - 1, secondStringLength = strlen(secondString) - 1, counter, counter1, count = 0, uniqueElem, uniqueCtr = 0;
for(counter = 0; counter < firstStringLength; counter++) {
for(counter1 = 0; counter1 < secondStringLength; counter1++) {
if(firstString[counter] == secondString[counter1]){
similarChar[count] = firstString[counter];
count++;
break;
}
}
}
for(counter = 0; counter < strlen(similarChar); counter++) {
uniqueElem = 0;
for(counter1 = 0; counter1 < counter; counter1++) {
if(similarChar[counter] == uniqueChar[counter1]) {
uniqueElem++;
}
}
if(uniqueElem == 0) {
uniqueChar[uniqueCtr++] = similarChar[counter];
}
}
if(strlen(uniqueChar) > 1) {
printf("%d\n", strlen(uniqueChar));
printf("%s", uniqueChar);
} else {
printf("%d",0);
}
}
Can someone please provide me some suggestions or code for shortening this function?
You should have 2 Arrays to keep a count of the number of occurrences of each aplhabet.
int arrayCount1[26],arrayCount2[26];
Loop through strings and store the occurrences.
Now for counting the similar number of characters use:
for( int i = 0 ; i < 26 ; i++ ){
similarCharacters = similarCharacters + min( arrayCount1[26], arrayCount2[26] )
}
There is a simple way to go. Take an array and map the ascii code as an index to that array. Say int arr[256]={0};
Now whatever character you see in string-1 mark 1 for that. arr[string[i]]=1; Marking what characters appeared in the first string.
Now again when looping through the characters of string-2 increase the value of arr[string2[i]]++ only if arr[i] is 1. Now we are tallying that yes this characters appeared here also.
Now check how many positions of the array contains 2. That is the answer.
int arr[256]={0};
for(counter = 0; counter < firstStringLength; counter++)
arr[firstString[counter]]=1;
for(counter = 0; counter < secondStringLength; counter++)
if(arr[secondString[counter]]==1)
arr[secondString[counter]]++;
int ans = 0;
for(int i = 0; i < 256; i++)
ans += (arr[i]==2);
Here is a simplified approach to achieve your goal. You should create an array to hold the characters that has been seen for the first time.
Then, you'll have to make two loops. The first is unconditional, while the second is conditional; That condition is dependent on a variable that you have to create, which checks weather the end of one of the strings has been reached.
Ofcourse, the checking for the end of the other string should be within the first unconditional loop. You can make use of the strchr() function to count the common characters without repetition:
#include <stdio.h>
#include <string.h>
int foo(const char *s1, const char *s2);
int main(void)
{
printf("count: %d\n", foo("everest", "every"));
printf("count: %d\n", foo("apothecary", "panther"));
printf("count: %d\n", foo("abacus", "abracadabra"));
return 0;
}
int foo(const char *s1, const char *s2)
{
int condition = 0;
int count = 0;
size_t n = 0;
char buf[256] = { 0 };
// part 1
while (s2[n])
{
if (strchr(s1, s2[n]) && !strchr(buf, s2[n]))
{
buf[count++] = s2[n];
}
if (!s1[n]) {
condition = 1;
}
n++;
}
// part 2
if (!condition ) {
while (s1[n]) {
if (strchr(s2, s1[n]) && !strchr(buf, s1[n]))
{
buf[count++] = s1[n];
}
n++;
}
}
return count;
}
NOTE: You should check for buffer overflow, and you should use a dynamic approach to reallocate memory accordingly, but this is a demo.

Checking array for identical numbers and their value

As part of a program that I have to make, one of the function that I need to program should check if the array has any identical numbers that are the same, and if one of them is bigger/equals to a given number.
The given number is also the amount of numbers in the array
This is what I have so far:
int checkarray(int *arr, int num)
{
int check = num;
int check2 = num;
int *lor;
int *poi;
int *another;
another = arr;
lor = arr;
poi = arr;
int check3 = num;
for ( ; num > 1; num--) {
for ( ; check3 >= 0; check3--) {
if (*arr == *poi)
return 0;
poi++;
}
arr++;
poi = another;
}
for ( ; check2 > 0; check2--) {
if (*lor >= check)
return 0;
lor++;
}
return 1;
}
I know that I made too many pointers/int for the function, but that's not the problem..
The part of checking for a given value works fine if I'm not mistaken so I think you can ignore that part (that's the last 'for' loop)
I know it should be easy but for some reason I just can't get it to work...
Edit:
I'll give an example: If the array is 0 1 2 3 1 the function will return 0, cause the second and the last number are identical. The function will also return 0 if the given number is 5, and one of the numbers is bigger or equals to 5, for example 0 1 2 5 4.
Otherwise, the function returns 1.
I create a new array where I'm going to save the numbers so I can check if you have a repeat number in the array. I also have one more argument in the function to know the size of the array.
#include <stdio.h>
#include <stdlib.h>
int checkArray(int *arr, int size, int number){
int i,j;
int *countArray = calloc(size,sizeof(int));
for(i=0;i<size;i++){
if(arr[i]>=number){ //Check >= number
free(countArray);
return 0;
}
for(j=0;j<i;j++){ //Check repeat number
if(countArray[j]==arr[i]){
free(countArray);
return 0;
}
}
countArray[j]=arr[i]; //no repeat number so we save it.
}
free(countArray);
return -1; //Error
}
int main(){
int arr[6] = {0,8,2,3,4,1};
printf("Result %d",checkArray(arr,6,5));
}
I hope this can help you.
Update without new array
int checkArray(int *arr, int size, int number){
int i,j;
for(i=0;i<size;i++){
if(arr[i]>=number){
return 0;
}
for(j=0;j<i;j++){
if(arr[i]==arr[j]){
return 0;
}
}
}
return -1; //Error
}
Change your upper for loop to:
for ( ; num > 0; num--) {
if(arr[i]>=number){
return 0;
}
int check3 = num;
poi=arr+1;
for ( ; check3 > 0; check3--) {
if (*arr == *poi)
return 0;
poi++;
}
arr++;
}
and remove the bottom one.
The mistakes here are as following:
1- You need to change the lines:
int check3 = num;
for ( ; num > 1; num--) {
to be:
for ( ; num > 1; num --) {
int check3 = check; // Move to inside loop to reset each time for a fresh inner loop and use check instead of num to reset the value
2- You need to change the line:
for ( ; check3 >= 0; check3--) {
To be
for ( ; check3 > 0; check3--) { // Because `>=0` means attempting to read past the array
3- poi should be initialised every time in the loop as arr+1 to skip comparing the same member of the array to itself, and to skip re-comparing members more than one time.
I suggest re-writing the method with better code style to enable easier detection of such errors and typos

palindrome of number in C

#include<stdio.h>
int main(void)
{
int rev=0,temp=0,frwd,n,ans=0;
int i,j;
for(i=100;i<=999;i++)
{
for(j=i;j<=999;j++)
{
n = i*j;
frwd = n;
while(n!=0)
{
temp = n%10;
n = n/10;
rev = temp+rev*10;
}
printf("%d",rev);
if((rev == frwd)&&(ans<frwd))
{
ans=frwd;
printf("%d",ans);
}
}
}
return(0);
}
I have tried working out everything but this code doesn't seem to give the correct output.
The desired output is largest palindrome number of 6 digits.
If I am running the individual parts i.e. the reversing of number , checking of number whether or not it is a palindrome or the for loops, they are working fine but in the program they are giving garbage as output.
Any help would be appreciated.
ya the problem is that you are not reinitializing rev to 0 as said by cowanother.anon.ard. Try putting rev=0 in inner for loop.
But you cant get 999999 as the highest palindrome number of 6 digit by your method as u r not checking all the 6 digit numbers.
#include<stdio.h>
int main(void)
{
int rev=0,temp=0,frwd,n,ans=0;
int i,j;
for(i=100000;i<=999999;i++)
{
frwd = n = i;
rev = 0;
while(n!=0)
{
temp = n%10;
n = n/10;
rev = temp+rev*10;
}
if((rev == frwd)&&(ans<frwd))
{
ans=frwd;
}
}
printf("%d\n",ans);
return(0);
}
4 problems with your Code:-
Like another.anon.coward said- you need to put rev=0 inside inner loop
You need to separate each number printed either by a space or a newline ('\n')
printf("\n %d");. Otherwise they will look like one big number (garbage).
Your algorithm is also wrong. According to your program, the largest 6-digit number is 906609 (The correct answer is 999999). For this you should change your inner loop to j=0;j<999;j++ and change n=i*j to n=i*1000+j.
Also move the printf("\n%d",ans); outside the loop.
The corrected program is:
#include <stdio.h>
int main(void)
{
int rev=0,temp=0,frwd,n,ans=0;
int i,j;
for(i=100;i<=999;i++)
{
for(j=0;j<=999;j++) /*CORRECTED THIS LINE,*/
{ rev=0;/*ADDED THIS LINE;*/
n = (i*1000) + j; /*CORRECTED THIS LINE*/
frwd = n;
while(n!=0)
{
temp = n%10;
n = n/10;
rev = temp+rev*10;
}
printf("\n%d",rev); /*THIS LINE,*/
if((rev == frwd)&&(ans<frwd))
{
ans=frwd;
}
}
}
printf("\n%d",ans); /* AND THIS LINE*/
return(0);
}
#include <stdio.h>
int main(void)
{
int rev=0,temp=0,frwd,n,ans=0;
int i,j;
for(i=100;i<=999;i++)
{
for(j=0;j<=999;j++) /*CORRECTED THIS LINE,*/
{ rev=0;/*ADDED THIS LINE;*/
n = (i*1000) + j; /*CORRECTED THIS LINE*/
frwd = n;
while(n!=0)
{
temp = n%10;
n = n/10;
rev = temp+rev*10;
}
printf("\n%d",rev); /*THIS LINE,*/
if((rev == frwd)&&(ans<frwd))
{
ans=frwd;
}
}
}
printf("\n%d",ans); /* AND THIS LINE*/
return(0);
}

Resources