Regarding null pointers and an assignment C - c

I'm stuck with my assignment and i can't seem to get it working, your help would be appreciated!:)
Task was to list prime numbers between a min max passed from program arguments (swap min&max if in wrong order). I was told to protect against null pointers and that there is some problem with not checking argv(?).(I won't include the prime part since that works )
Main.c
void proc(int argc, char *argv[])
{
int min,max;
min=atoi(argv[1]);
max=atoi(argv[2]);
if(min>max)
{
swap(min, max);
printf("Min&max swapped!");
}
if(argc!=3)
{
printf("Please set 2 numbers as interval");
exit(EXIT_FAILURE);
}
prime(min,max);
return EXIT_SUCCESS;
}
int main(int min,int max)
{
proc(min, max);
}
Swap.c
void swap(int *a,int *b)
{
int c = *a;
*a = *b;
*b = c;
}

Check argcvalue before accessing argv that way you eliminate the chance of accessing out of bound memory.
Also swap should get address of min and max so that the change can be reflected.
swap(&min,&max);
void swap(int *x,int *y)
{
int t=*x;
*x=*y;
*y=t;
}
How you should go about?
if( argc != 3)
{
printf("[%s]:[progname num1 num2]\n");
return 0;
}
...
...
min = atoi(argv[1]);
..
max = ..
if(max<min)
swap(&max,&min);

int min,max;
...
swap(min, max);
Okay, so you pass the swap function two ints.
void swap(int *a,int *b)
But swap expects two int*s. That can't be good.
Also:
int* c = *a;
Hmm, a is of type int*, so *a is of type int. So why are you assigning it to a variable of type int*? That can't be good either.

Related

After a pointer Returns from a function i cant print it

I am relatively new to C. My program is supposed to fill in the array with random numbers and i have to find the max and min using 1 function. The program works fine up until the point i have to return the values my 2 pointers get from the function. When i go to print them the porgram stop working and exits with the return value of 3221225477. I have been trying to fix this for 3 hours and i am going INSANE. Please help in any way you can i would really apreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void MaxMin(int size, int *B, int *Max, int *Min);
int main(int argc, char *argv[])
{
int N, i,*A,*MAX,*MIN;
srand(time(NULL));
/*Making sure the user enters a proper value for the array*/
do
{
printf("Give the number of spaces in the Array\n");
scanf("%d",&N);
}
while(N<1);
A = (int *) malloc(N*(sizeof(N)));
/*Giving random numbers to the array and printing them so i can make sure my code is finding the max min*/
for(i=0;i<N;i++)
{
A[i]=rand()%100;
printf("\n%d\n",A[i]);
}
/*Calling my void function so that the pointers MAX and MIN have a value assigned to them */
MaxMin(N, A, MAX, MIN);
/*Printing them*/
printf("\nMax = %d\nMin = %d",*MAX,*MIN);
free(A);
return 0;
}
/*The function*/
void MaxMin(int size, int *B, int *Max, int *Min)
{
/*using 2 temporary ints to get max min cause pointers and arrays confuse me*/
int max=B[0],min=B[0],i;
for(i=1;i<size;i++)
{
if(max<B[i])
{
max = B[i];
}
if(min>B[i])
{
min = B[i];
}
}
/*These have the proper value last i chekced */
Max = &max;
Min = &min;
}
(edit) SOLUTION Ty so much for the help !
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void MaxMin(int size, int *B, int *Max, int *Min);
int main(int argc, char *argv[])
{
int N, i,*A,MAX ,MIN ;
srand(time(NULL));
/*Making sure the user enters a proper value for the array*/
do
{
printf("Give the number of spaces in the Array\n");
scanf("%d",&N);
}
while(N<1);
A = (int *) malloc(N*(sizeof(int)));
/*Giving random numbers to the array and printing them so i can make sure my code is finding the max min*/
for(i=0;i<N;i++)
{
A[i]=rand()%100;
printf("\n%d\n",A[i]);
}
/*Calling my void function so that the pointers MAX and MIN have a value assigned to them */
MaxMin(N, A, &MAX, &MIN);
/*Printing them*/
printf("\nMax = %d\nMin = %d",MAX,MIN);
free(A);
return 0;
}
/*The function*/
void MaxMin(int size, int *B, int *Max, int *Min)
{
*Max=B[0];
*Min=B[0];
int i;
for(i=1;i<size;i++)
{
if(*Max<B[i])
{
*Max = B[i];
}
if(*Min>B[i])
{
*Min = B[i];
}
}
}
You passed to the function MaxMin pointers MAX and MIN by value. That is the function deals with copies of (indeterminate) values of the passed pointers. Changing the copies does not influence on the original arguments.
Within main you should declare MIN and MAX as objects of the type int.
int N, i,*A, MAX, MIN;
and call the function ,like
MaxMin(N, A, &MAX, &MIN);
Within the function you should write
*Max = &max;
*Min = &min;
And at last in main you should call printf like
printf("\nMax = %d\nMin = %d", MAX, MIN);
Pay attention to that the expression sizeof( N ) used in this statement
A = (int *) malloc(N*(sizeof(N)));
is error prone. The type of the variable N can be changed for example from the type int to the type size_t. In this case the size of the allocated memory will be incorrect, You should write for example
A = (int *) malloc(N*(sizeof( *A )));
You have three bugs:
In main, you don't assign MAX or MIN any values. So you pass garbage to MaxMin.
In MaxMin, Max and Min are about to go out of scope. Changing their values before they go out of scope has no effect on anything.
In main, you don't create any place to hold the maximum and minimum values. So where are you expecting them to be stored?

Sorting an array in ascending order using pointers in C

I am writing a program that creates an array of random numbers from 1 to 100 and sorts them in ascending order. Below is working code that does this, but I need to modify it so that the "swap" function makes use of pointers. The call for the swap function should look like this: swap(???,???) where the two inputs are pointers. What is the best way to accomplish this?
#include<stdio.h>
#include<math.h>
int main()
{
void fillArray(int sizeArray, int array[sizeArray]);
void printArray(int sizeArray, int array[sizeArray]);
void sortArray(int sizeArray, int array[sizeArray]);
int sizeArray;
printf("\nSize of the array? ");
scanf("%d", &sizeArray);
int array[sizeArray];
fillArray(sizeArray,array);
sortArray(sizeArray, array);
printArray(sizeArray, array);
}
void fillArray(int sizeArray, int array[sizeArray])
{
int increment;
for(increment=0; increment<sizeArray; increment++)
{
array[increment]=rand()%101;
}
}
void sortArray(int sizeArray, int array[sizeArray])
{
void swap(int increment2, int increment, int array[]);
int increment, increment2, temp;
for (increment=0; increment < sizeArray ; increment++)
{
for (increment2=increment+1; increment2 < sizeArray; increment2++)
{
swap(increment2, increment, array);
}
}
}
void swap(int increment2, int increment, int array[])
{
int temp;
if (array[increment2] < array[increment])
{
temp=array[increment];
array[increment]=array[increment2];
array[increment2]=temp;
}
}
void printArray(int sizeArray, int array[sizeArray])
{
int increment=0;
printf("\nHere's the sorted array:\n");
while(increment<21)
{
printf("\n array[%d] is %d", increment, array[increment]);
increment++;
}
}
The output should look like this:
output
Define your swap function as below:
void swap(int *increment2, int* increment)
Modify your for loop where you call the swap function:
for (increment=0; increment < sizeArray ; increment++)
{
for (increment2=increment+1; increment2 < sizeArray; increment2++)
{
swap(array[increment2], array[increment]);
}
}
Then, modify your swap function:
void swap(int *increment2, int* increment)
{
int temp;
if (increment2 < increment)
{
temp= *increment2;
*increment2=*increment;
*increment2=temp;
}
}
You need to fix your function call for the parameters to be with pointers.
void swap(int *increment2, int* increment)
Then in your swap function you need
You will need to deference the integer*.
Example
int n1;
int* x = 100
n1 = *x;
You may need to
deference in the future example
Your function accepts pointers
void swap(int *increment2, int* increment)
If you have integers or another data type to reference them, refer to their address, you can perform & for referencing.
int i = 5;
int* x;
x = &i;
x is now an integer pointer to the address of i.
Your calling code needs to pass the address of the integers to compare and swap. Either of the following forms is acceptable, and they are equivalent.
swap(array+increment2, array+increment);
swap(&array[increment2], &array[increment]);
The first form takes the address of the first element (array) and adds the index (increment2) to get the address of the correct element.
The second version is more straightforward, perhaps. It uses the & address-of operator to take the address of array[increment2], which is the desired integer.
Your swap function need to be defined as follows:
void swap(int** p2, int** p1)
{
int temp;
if (*p2 < *p1)
{
temp=*p1;
*p1=*p2;
*p2=temp;
}
}
Note how the pointers are dereferenced with the * operator to get the integer values for comparison (and storage in temp).

output error in printing number in c

int funcc(int a[],int b[],int *cnt)
{
int *c;
int j,i,s=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if(b[i]==a[j])
{
*cnt++;
break;
}
c=(int*)malloc(*cnt*sizeof(int));
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if(b[i]==a[j])
{
c[s++]=b[i];
break;
}
return c;
}
void main (void)
{
int *c;
int *cnt=0;
int i,arr[n]={3,2,1},brr[n]={3,2,0};
c=funcc(arr,brr,&cnt);
for(i=0;i<*cnt;i++)
printf("%d ",c[i]);
}
I need to print the common numbers in 2 arrays..
but the problem is with "cnt" .. if i replace cnt with 3 it works ..
but when i put cnt it doesnt work
The problem is you declare cnt as an int pointer, so when you pass in &cnt, you're passing in a pointer to a pointer to an int. Try changing that second line of main to int cnt=0; and change the for loop to for(i=0;i<cnt;i++) (notice the removal of the * character).
EDIT: the line *cnt++; should be changed to either ++*cnt; or (*cnt)++, since the increment operator takes higher precedence than the dereference operator.
Your prototype is:
int funcc(int a[],int b[],int *cnt)
but you are passing it a pointer to a pointer:
int *cnt=0; /* <- pointer */
int i,arr[n]={3,2,1},brr[n]={3,2,0};
c=funcc(arr,brr,&cnt); /* &cnt <- pointer to a pointer */

removing duplicate values from an array in C

I am trying to create a program in C that removes duplicate values in an integer array. My strategy is to first sort the array via a selectionsort function, and then call a function removedup that removes any consecutive, duplicate values in the array.
My code:
#include <stdio.h>
#include "simpio.h"
#define n 10
void GetArray(int a[]);
void SelectionSort(int a[]);
int FindMax(int a[], int high);
void swap(int a[], int p1, int p2);
int removedup(int a[]);
void printArray(int a[]);
main()
{
int a[n];
GetArray(a);
SelectionSort(a);
printf("The original, sorted array is\n");
printArray(a);
printf("The array with removed duplicates \n");
printArray(removedup(a));
getchar();
}
void GetArray(int a[])
{
int i;
for(i=0;i<n;i++)
{
printf("Enter integer# %d", i+1);
a[i]=GetInteger();
}
}
void SelectionSort(int a[])
{
int i, max;
for(i=0;i<n;i++)
{
max=FindMax(a,n-i-1);
swap(a,max,n-i-1);
}
}
int FindMax(int a[], int high)
{
int i, index;
index=high;
for(i=0;i<high;i++)
{
if(a[i]>a[index])
index=i;
}
return index;
}
void swap(int a[], int p1, int p2)
{
int temp;
temp=a[p2];
a[p2]=a[p1];
a[p1]=temp;
}
int removedup(int a[])
{
int i, count, OutArray[count], j;
count=0;
for(i=0;i<n-1;i++)
{
if(a[i]==a[i+1])
{
a[i+1]=a[i+2];
count++;
}
}
count++;
for(j=0;j<count;j++)
{
OutArray[i]=a[i];
}
return OutArray;
}
I have two questions:
1) How do I fix the error the compiler in giving me in the main body when calling removedup inside the printarray function, saying "invalid conversion from int to int*"? (line 22)
2) How do I accurately define the size of OutArray[] in the removedup function? Currently I have it defined as the size variable, but the value of this variable isn't accurately defined until after the declaration of OutArray.
Notice your prototypes ...
int removedup(int a[]);
void printArray(int a[]);
And also notice you're calling printArray() with the result of removedup().
printArray(removedup(a));
The result of removedup() is an int; printarray() requires a int[].
int and int[] are not compatible.
I suggest you remove duplicates and print array in two distinct statements.
You should be able to fix the compiling problems after reading comp.lang-c FAQ on arrays and pointers.
After you get your array sorted, you can use the following function to remove the duplicates:
int dedup(int arr[], int size) {
int curr = 0, next = 0;
while (next < size) {
while (next < size && arr[next] == arr[curr])
next++;
if (next < size)
arr[++curr] = arr[next++];
}
return size ? curr+1 : 0;
}
It takes two arguments, the array and its size. The duplicates are removed in-place, which means that the array is modified, without allocating a new array to store the unique elements.
Remember that the dedup function expects the elements to be sorted! I've noticed you are using your own implementation of selection sort, which makes me think this is homework. In that case, I feel a little reluctant on giving you a complete solution, although understanding it should be a good exercise anyway.
EDIT: I should've explained the last line of code.
return size ? curr+1 : 0; is equivalent to:
if (size)
return curr+1;
else
return 0;
Just a shorter way of saying the same thing.

How to output a float product of int multipliers?

I am trying to calculate the exponent of a number. When I do everything as int I get the correct result, but the output must be float, when I try to convert with %f in printf() I get 0, when I use %d I get the correct result. I cannot change the main() portion of the program, I can only alter the *powerArgs() function. The program input is 3, 5.
Full disclosure, this is part of a school assignment. I am not asking for complete code. I would appreciate a more general answer showing me what I am forgetting, possibly what area I should study more to find the answer myself.
#include <stdio.h>
#include <stdlib.h>
int *powerArgs(int *pA, int *pB);
/* MAIN */
int main(int argc, char **argv)
{
if (argc != 3)
{
printf("?Invalid number of arguments\n");
system("pause");
exit(1);
}
int parmA = atoi(argv[1]);
int parmB = atoi(argv[2]);
int idx;
/* Part C: Raise parmA to the power of parmB. Return pointer to the result */
/* Reset the original values after we print the result */
printf("%d raised to the %d power is %0.1f\n", parmA, parmB, *powerArgs(&parmA, &parmB));
printf("\n");
system("pause");
exit(0);
}
int *powerArgs(int *pA, int *pB)
{
int idx, result = *pA;
for (idx = 1; idx < *pB; idx++)
{
result *= *pA;
}
return &result;
}
float and int convert automatically in C - you can assign either one to the other, and the only thing to watch out for is that if you assign too large a float to an int, then you get undefined behavior (or possibly an unspecified result, I forget. Either way it's not good).
So, your powerArgs function can just be:
float powerArgs(float a, int b) {
// do some stuff and return a value
}
Then you can call it as powerArgs(parmA, parmB), even though parmA is an int.
Edit: if you can't change the call parameters, you can do this instead
float powerArgs(int *a, int *b) {
float base = *a;
int exponent = *b;
...
}
If your professor has really set you code where the function is called as *powerArgs(int *a, int *b), then your professor is a menace. There is no earthly reason why an exponentiation function should return a pointer to a float. There's an ugly workaround you could use:
float *powerArgs(int *a, int *b) {
static float result;
...
result = /* the result of the calculation */;
return &result;
}
The problem with this is, all calls to powerArgs share the same object result. static stops it from ceasing to exist at the end of the call, but the sharing will introduce problems in the long run. It is not good practice to do this, but it might be the best solution to the problem you've been set.
C++ sneaky solution:
struct FloatWrapper {
float value;
float operator*() {
return value;
}
FloatWrapper(float f) : value(f) {}
};
FloatWrapper powerArgs(int *a, int *b) {
...
float result = /* whatever */;
...
return result;
}
This returns an object of class FloatWrapper, by value, and FloatWrapper overloads the * operator. This means that *powerArgs(...) evaluates to the float that the function should have returned by value in the first place, without needing a pointer to any special storage place.
By the way, you might want to check what your function does when parmB is 0.
First, your int *powerArgs(int *pA, int *pB) function returns the address of a local variable, which results in undefined behavior. Use the following instead:
int powerArgs(int *pA, int *pB)
{
int idx, result = *pA;
for (idx = 1; idx < *pB; idx++)
{
result *= *pA;
}
return result;
}
Next, if you want to convert to float, you shouldn't do that in the call to printf(), but rather convert the value to float before the call like so:
printf("%d raised to the %d power is %0.1f\n", parmA, parmB, (float)powerArgs(&parmA, &parmB));
When a function terminates, all its local variables cease to exist (and their addresses point to garbage). To please your teacher who came up with that very awkward interface, you have to find a way to keep an object alive after the function exists.
You have, at least, 3 options:
a) reuse one of the input parameters
b) use a global variable
c) use a static variable
option a)
int *powerArgs(int *pA, int *pB) {
/* calculate */
*pA = CALCULATED_VALUE;
return pA;
}
option b)
int global_power;
int *powerArgs(int *pA, int *pB) {
/* calculate */
global_power = CALCULATED_VALUE;
return &global_power;
}
option c)
int *powerArgs(int *pA, int *pB) {
static int static_power;
/* calculate */
static_power = CALCULATED_VALUE;
return &static_power;
}
Neither of these "solutions" is good; the least bad is option c)

Resources