Incrementing pointer's value doesn't work - c

This program is supposed to count number of similar entries, using pointers, but
whenever I type in number, counter is always equal to zero. What am I going wrong?
#include <stdio.h>
#include <stdlib.h>
//using function to count similar enteries in an array...
void count_similar_enteries(int array_func[10],int *number, int *ptr_to_counter);
int main()
{
int number = 0;
int array[10] = {0,1,1,2,3,1,2,67,65,1};
int counter = 0;
printf("enter a number\n");
scanf("%d", &number);
count_similar_enteries(array, &number,&counter);
printf("the number of similar enteries are %d\n", counter);
return 0;
}
void count_similar_enteries(int array_func[10],int *number, int *ptr_to_counter)
{
int i;
for (i = 0; i< 10 ; i++)
{
if(array_func[i] == *number)
{
*ptr_to_counter++;
continue;
}
else
{
continue;
}
}
}

*ptr_to_counter++; is incrementing the pointer itself, write (*ptr_to_counter)++; to increment the value of the ptr_to_counter.
Note that continue; is redundant. You don't have to have if-else there. The loop will be "looped" anyway. You can just do:
for(i = 0; i< 10 ; i++) {
if(array_func[i] == *number) {
(*ptr_to_counter)++;
}
}
I advise you to reduce the amount of pointers as much as you can, for example, you don't have to pass a counter by pointer. You can just have a local int counter; and return its value to the caller.

You are incorrectly incrementing counter value at address ptr_to_counter.
You have use *ptr_to_counter++ which means *(ptr_to_counter++) i.e. it is increamenting address not the value. You should use (*ptr_to_counter)++. It will work perfectly.

I think you require
*ptr_to_counter = *ptr_to_counter + 1;
EDIT
Perhaps this would be a better implementation
int count_similar_enteries(int arr, size_t len,int number)
{
i;
int count = 0;
for (size_t i = 0; i<len ; ++i)
{
if(arr[i] == number)
{
++count;
}
}
return count;
}

If you are not sure about operator precedence please use brackets, it will also increase readability of your code.
*ptr_to_counter++ will work like *(ptr_to_counter++) because ++ has higher precedence. You should have used (*ptr_to_counter)++

*ptr_to_counter++
means
*(ptr_to_counter++)
which means increment the address holed by ptr_to_counter, which is taking your pointer to the adjacent address where nothing is stored(or may be garbage).
You should use (*ptr_to_counter)++ meaning increment the value pointed at by ptr_to_counter.

Related

Why can't I return the last value of the recursive fuction in C?

I've been trying to build a recursive function which calculates the max value, but even I can see the total value when I print in the function, I can't return the value to the main function. Can you tell me where do I do wrong? Thanks for help!
note : more explanation about what I ve been trying to build is : user defines an object and as long as user doesn't give the price, I keep asking what the object is..
small example :
Define the object:
Car
What is Car?:
4*Wheel+1*Frame
What is Wheel?:
2*Rim
What is Rim?
5.0
What is Frame?:
10.0
Total is : 50.0
Current code:
#include <stdio.h>
#include <stdlib.h>
#define INPUT_SIZE 101
void delete_space(char arr[])
{
int a, i, j, len;
for(a = 0; a < INPUT_SIZE; a++)
{
for(i = 0; i < INPUT_SIZE; i++)
{
if(arr[i] == ' ')
{
for(j = i; j < INPUT_SIZE; j++)
{
arr[j] = arr[j + 1];
}
}
}
}
}
double result(char input[], double coeff, double total)
{
/* if the input is number, num_of_obj is 0, if the input is object, num_or_obj is more than 0.
*/
int i, k = 1, num_of_obj = 0;
char temp_input[INPUT_SIZE];
char temp_input_1[INPUT_SIZE];
char x;
int* p;
double value;
p = (int*)calloc(1, sizeof(int));
p[0] = 0;
printf("What is %s:?\n", input);
scanf("%[^\n]s", temp_input);
getchar();
delete_space(temp_input);
for(i = 0; i < INPUT_SIZE; i++)
{
if(temp_input[i] == '*')
{
num_of_obj++;
}
}
if(num_of_obj == 0) // if the input is number.
{
sscanf(temp_input, "%lf", &value);
total = total + coeff * value;
printf("total : %lf", total);
return total;
}
if(num_of_obj > 0)
{
for(i = 0; i < INPUT_SIZE; i++)
{
if(temp_input[i] == '+')
{
p = (int*)realloc(p, (k + 1) * sizeof(int));
p[k] = i + 1;
k++;
}
}
for(i = 0; i < k; i++)
{
sscanf(&temp_input[p[i]], "%lf%c%[^+]s", &coeff, &x, temp_input_1);
result(temp_input_1, coeff, total);
}
}
printf("test");
return total;
}
int main()
{
double total = 0;
char input[INPUT_SIZE];
printf("Define the object :\n");
scanf("%[^\n]s", input);
getchar();
delete_space(input);
printf("total : %.2lf", result(input, 0, 0));
return 0;
}
I believe that the main issue is the recursive call: result(temp_input_1, coeff, total);, which is ignoring the returned result.
Two possible solutions: (1) do the aggregation in result OR (2) tail recursion. I'm not sure that this case fit into tail recursion (or that there are any benefits here). Consider removing the 'total' from result prototype, and doing the aggregation (over the 'components') in the loop.
double result(char input[], double coeff) {
double total ;
...
for(i = 0; i < k; i++)
{
sscanf(&temp_input[p[i]], "%lf%c%[^+]s", &coeff, &x, temp_input_1);
total += result(temp_input_1, coeff, total);
}
Side comment: Consider also removing the 'delete_space' function. I believe it does not property fix the string. Much easier to skip over the spaces in the scanf call.
Welcome to stackoverflow! I too am new here, but if you word your questions right, you'll get better answers. If this is a homework assignment, I highly recommend including that, it can be hard to follow descriptions.
So as a general rule of thumb, when writing C functions its best to use as few return statements as possible. But I too have difficulty with this.
It looks like your are checking for
is first condition met?
if not check next condition
should you be using if, if else, and else?
Also you have if statements with no else, generally needed, especially in a recursive function (you might be skipping over the next step after the last recursive call)
Hope this helps! Swamped with the end of the semester myself or else I would have attempted a solution!
You need three things to write a recursive method successfully:
A terminating condition, so that the method doesn't call itself forever,
Some work to do, and
A recursive call.
Consider the following code:
typedef struct node{
void* item;
struct node* next;
} Node;
int CountNodes(Node* list)
{
if (list == null) return 0;
return 1 + CountNodes(list.next);
}
This code works because it counts the current node plus all remaining nodes. The recursive call counts the next node and all remaining nodes. And so on.

Issue with returning an array of type int from function

I have read through a lot of posts giving ways in which you can return an array of type int from a function. I have attempted to follow the approach of dynamically allocating the memory inside of the function using the malloc() function.
In the example code, I am using a function foo which calculates peaks in an array which are greater than a specified value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* function declaration */
int *foo(int arr[],int size);
int main()
{
int test[] = {1,2,1,4,5,2,7,8,9,1}; //array of test data.
int *p;
p = foo(test,10);
int w;
for(w=0;w<5;w++)
{
printf(" Peak %d\t",p[w]); // This line is giving a non sensible answer.
}
free(p); // free the memory
return 0;
}
int *foo(int arr[],int size) {
int j;
int Peak_min = 3; // Minimum peak height
int *ret = malloc(size * sizeof(*ret));
if(!ret) return 1;
for (j = 0; j < size -1; ++j)
{
if ( (arr[j] < arr[j+1]) && (arr[j+1] > arr[j+2]) && (arr[j+1] > Peak_min))// Peak criteria
{
ret[j] = arr[j+1];
printf(" Peak_No %d",ret[j]); // This line is giving the correct output.
}
}
return ret;
}
The output printed in the function gives 5 and 9, as expected. However, the output when I call the function in int main() gives non-sensible values. I am struggling to find the error with my code, any suggestions on how I can debug/fix this?
Update
I edited the for loop in the fucntion foo to
for (j = 0; j < size -2; ++j)
{
if ( (arr[j] < arr[j+1]) && (arr[j+1] > arr[j+2]) && (arr[j+1] > Peak_min))// Peak criteria
{
ret[j] = arr[j+1];
printf(" Peak_No %d",ret[j]); // This line is giving the correct output.
}
else
{
ret[j] = 0;
}
}
I am now getting the output I wanted.
malloc() returns unitialized memory.
Inside the function, the assignment of ret[j] is conditional. You never know for sure that which or any index element is actually initialized. After returning the pointer, you unconditionally index into the pointer any to read the values which may be very well unitialized.
In case, you are returning the pointer with the same assignment condition, you can at least use calloc() which returns 0-filled memory, so at least, you have a deterministic value. However, this will fail to differentiate between a left-over index element and an element actually having a value of 0. For better precision, you can memset() the malloc()-ed memory to some guard value which indicates that those node values are not assigned.
Also, another quickfix would be, add one else condition which basically helps to unconditionally assign a value to each element.
Seems the loop must be:
int k= 0;
for (j = 0; j < size -2; ++j)
{
if ( (arr[j] < arr[j+1]) && (arr[j+1] > arr[j+2]) && (arr[j+1] > Peak_min))// Peak criteria
{
ret[k++] = arr[j+1];
}
}
ret[k]= 0;
return ret;
}
and in main:
int w= 0;
while (p[w]) printf(" Peak %d\t",p[w++]);
This creates a list of peaks, terminated with a null entry.

error with array size

I am trying to make a program that calculates the amount of prime numbers that don't exceed an integer using the sieve of Eratosthenes. While my program works fine (and fast) for small numbers, after a certain number (46337) I get a "command terminated by signal 11" error, which I suppose has to do with array size. I tried to use malloc() but I didn't get it quite right. What shall I do for big numbers (up to 5billion)?
#include <stdio.h>
#include<stdlib.h>
int main(){
signed long int x,i, j, prime = 0;
scanf("%ld", &x);
int num[x];
for(i=2; i<=x;i++){
num[i]=1;
}
for(i=2; i<=x;i++){
if(num[i] == 1){
for(j=i*i; j<=x; j = j + i){
num[j] = 0;
}
//printf("num[%d]\n", i);
prime++;
}
}
printf("%ld", prime);
return 0;
}
Your array
int num[x];
is on the stack, where only small arrays can be accommodated. For large array size you'll have to allocate memory. You can save on memory bloat by using char type, because you only need a status.
char *num = malloc(x+1); // allow for indexing by [x]
if(num == NULL) {
// deal with allocation error
}
//... the sieve code
free(num);
I suggest also, you must check that i*i does not break the int limit by using
if(num[i] == 1){
if (x / i >= i){ // make sure i*i won't break
for(j=i*i; j<=x; j = j + i){
num[j] = 0;
}
}
}
Lastly, you want to go to 5 billion, which is outside the range of uint32_t (which unsigned long int is on my system) at 4.2 billion. If that will satisfy you, change the int definitions to unsigned, watching out that your loop controls don't wrap, that is, use unsigned x = UINT_MAX - 1;
If you don't have 5Gb memory available, use bit status as suggest by #BoPersson.
The following code checks for errors, tested with values up to 5000000000, properly outputs the final count of number of primes, uses malloc so as to avoid overrunning the available stack space.
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long int x,i, j;
unsigned prime = 0;
scanf("%lu", &x);
char *num = malloc( x);
if( NULL == num)
{
perror( "malloc failed");
exit(EXIT_FAILURE);
}
for(i=0; i<x;i++)
{
num[i]=1;
}
for(i=2; i<x;i++)
{
if(num[i] == 1)
{
for(j=i*i; j<x; j = j + i)
{
num[j] = 0;
}
//printf("num[%lu]\n", i);
prime++;
}
}
printf("%u\n", prime);
return 0;
}

printing randome choices from an array

I am working on a function that picks random numbers from a given array and prints them to stdout. These numbers should not repeat and how many numbers are picked is given to the function along with the array. I have a separate test file for the function and a header file as well. Everything compiles fine but when I run the program I get a hang up in the pickNumbers function, nothing is printed and I don't even know if anything is being chosen to begin with.
#include <stdio.h>
#include <stdlib.h>
#include "head.h"
//program that picks random numbers from the given array
int alreadyPicked(int choices[], int choice);
void pickNumbers(int myArray[],int max)
{
// delcare/initilize variables
int i;
int choices[max];
int length = sizeof(myArray)/sizeof(myArray[0]);
// seed rand
srand(time(NULL));
// pick a random choice until that given number of choices is reached
// to make sure non repeat run against alreadyPicked function
for (i=0; i <= max; i++) {
do{
choices[i] = (rand() % max);
}while (alreadyPicked(choices, choices[i]) == TRUE);
}
for (i=0; i <= max; i++) {
printf("%d", myArray[choices[i]]);
}
printf("\n");
}
int alreadyPicked(int choices[], int choice)
{
int i;
int answer = FALSE;
for (i=0; i <= (sizeof(choices)/sizeof(choices[0])); i++) {
if(choices[i] == choice)
answer = TRUE;
}
return answer;
}
Perhaps
for (i=0; i <= max; i++) {
must be:
for (i=0; i < max; i++) {
and
for (i=0; i <= (sizeof(choices)/sizeof(choices[0])); i++) {
must be:
for (i=0; i < (sizeof(choices)/sizeof(choices[0])); i++) {
In your first "for" loop you have a nested while/do. You increment "i" in your for loop, instead you should increment the variable inside of while/do, otherwise it will hang forever performing such loop because "i" is never incremented.
Replace:
for (i=0; i <= max; i++) {
by:
for (i=0; i < max;) {
And also replace:
choices[i] = (rand() % max);
By:
choices[i++] = (rand() % max);
This way you make sure "i" is being incremented. Also your construction "i<=max" is incorrect since you start from 0, use the way David RF did.
Apart from the aforementioned wrong loop tests, the reason for the endless loop is that in alreadyPicked() you compare the new choice index with every choice index in choices[], including uninitialized ones and the new one itself; thus, alreadyPicked() always returns TRUE. I suggest to change to call of alreadyPicked() to
alreadyPicked(choices, i)
and its implementation to
int alreadyPicked(int choices[], int choice)
{
for (int i = 0; i < choice; i++)
if (choices[i] == choices[choice])
return TRUE;
return FALSE;
}

Find missing number between 1 to 100

This question has been asked here on SO before with below code
find3missing(int* array)
{
int newarray[100] = {0};
For i = 0 to 99
++newarray[array[i]] ;
For i = 0 to 99
If newarray[i] != 1
Cout << “the missing number is ” << i+1 << endl ;
}
But when I checked this code, it doesn't seem to work. Suppose I have an array of {1,2,6}. The output should be 3,4,5 but with the code above I get 1,4,5,6 instead. Below is my implementation of pseudo code with array size 6.
main()
{
int a[6]={1,2,6};
int tmp[6]={0},i;
for(i=0;i<6;i++)
{
++tmp[a[i]];
}
for(i=0;i<6;i++)
{
if(tmp[i]!=1)
{
printf("%d",i+1);
}
}
}
Is this the right code?
This ++newarray[array[i]] should be ++newarray[array[i] - 1]. This because you are interested in a sequence of 1-100 numbers, so no 0, but C arrays are 0 based. If you then look at the cout: the missing number is ” << i+1 here you "unshift" the number by adding 1.
There is another problem: you should pass the number of elements of the array, something like:
find3missing(int* array, int length) {
int newarray[100] = {0};
for (int i = 0; i < length; i++) {
++newarray[array[i] - 1] ;
}
C/C++ arrays are zero based, as A[i] is equivalent to *(A+i). So change ++newarray[array[i]] to ++newarray[array[i]-1]. Also use malloc, free and memset to use an array of dynamic size.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void find3missing(int* pArray, size_t size, int min, int max){
int* newarray;
int i;
unsigned int j;
int range = max - min;
if(range < 0)
return;
newarray = (int*) malloc(range*sizeof(int)); // allocate enough memory
memset(newarray,0,range*sizeof(int)); // set that block to zero
for(j = 0; j < size; ++j){
++newarray[pArray[j]-min];
}
for(i = 0; i < range; ++i){
if(!newarray[i])
printf("%d is missing!\n",min+i);
}
free(newarray);
}
int main(){
int test[] = {1,3,6};
find3missing(test,sizeof(test)/sizeof(int),1,6);
return 0;
}
Please note that this solution is very inefficient if your array is sorted. In this case have a look at Jimmy Gustafsson's answer.
This algoritm will be quite simple, since you're using a sorted array. Simply check if the current value +1 equals the nextvalue like below:
find3missing(){
int array[arraySize]; // the array with integers
for(i=0;i<arraySize;i++)
if(array[i]+1 != array[i+1]) // if value array[i]+1 is not equal the next index
// value, then it's a missing number
printf("A missing number: %i", i+1);
}

Resources