Trying to swap multiple values in a user entered array - c

I am trying to take a user entered array and swap the 0th value with the 7th, 8th value with the 3rd and the 0th with the 14th value. I have to use a function to swap which is where i think i messed up. When i compile it says to few arguments for function swap. also, its my 1st time using pointers so i wouldn't be surprised if there errors with that,. this is what i have, thanks!
#include <stdio.h>
void swap (int a[15], int *p, int *q, int *r ,int *s , int*t) {
int temp;
p = &a[0];
q = &a[7];
r = &a[8];
s = &a[3];
t = &a[14];
temp = *p;
*p = *q;
*q = temp;
temp = *r;
*r = *s;
*s = temp;
temp = *t;
*t = *p;
*p = temp;
}
int main (int argc, char *argv[]) {
int a[15], i;
printf(" Enter 15 integers: ");
for (i=0; i <15; i++)
swap(a);
printf(" Swapped array:\n %d", a[15]);
return 0;
}

Its not an error related to pointers.
You called swap() with one argument, like this swap(a);
And while defining it you have more then one arguments. Like
void swap (int a[15], int *p, int *q, int *r ,int *s , int*t) {
...
You do not need those extra arguments in the function definition.
Just change it to,
void swap (int a[15]) {
int temp;
int* p = &a[0];
int* q = &a[7];
int* r = &a[8];
int* s = &a[3];
int* t = &a[14];
...

A much better approach would be define a general function swap() and call it with proper required arguments multiple times when required.
void swap(int *p, int *q)
{
int tmp = *p;
*p = *q;
*q = tmp;
}
Call the above API something like
swap (&a[0], &a[7])
swap (&a[8], &a[3])
...
..

Related

I have doubts about double pointer as parameters for a swap function

I hope you can help me! I added this function to my array.c to shuffle the array elements and it works with static Item *a; static int dim; in my array.c.
static Item *a;
static int dim = 3;
a=malloc( dim * sizeof(Item);
void random_array() {
int i , j;
Item t;
for (i = dim - 1;i > 0; i--)
{
j = rand() % (i + 1);
t = a[i];
a[i] = a[j];
a[j] = t;
//swap(a[i], a[j]);
}
}
item.h
typedef void *Item;
item-int.c
#include <stdio.h>
#include <stdlib.h>
#include "item.h"
Item inputItem(){
int *p;
p=malloc(sizeof(int));
scanf("%d",p);
return p;
}
void outputItem(Item item){
int *p;
p=item;
printf("%d ",*p);
}
int cmpItem(Item item1,Item item2){
int *p1,*p2;
p1 = item1;
p2 = item2;
return *p1 - *p2;
}
So I tried with a function swap (a[i], a[j]) from the file utils.c but it doesn't work.
void swap (Item pa, Item pb) {
Item t;
t = pa;
pa = pb;
pb = t;
}
It works with these instructions:
void swap (Item *pa, Item *pb)
{
Item t;
t = *pa;
*pa = *pb;
*pb = t;
}
I know that with "typedef void *Item' Item t is like void *t and Item *a is like void **a, right?
So with double pointers I have a dynamic array with many pointers thanks to a=malloc(numberelements*(sizeof(Item)); and with a[i]=malloc(sizeof(Item) every pointer points to a memory location with many bytes?
Here a image.
So for t I don't need malloc because with t = a[i] t points to memory location pointed from a[i], right?
If yes, why do I have to use in my swap function t = *pa etc. instead of t = pa ? I have several doubts about double pointers as function parameters. I hope you can resolve that. Thanks in advance!
Ok, let's start from here:
typedef int Item; // Always get this backwards, need to check...
void swap (Item *pa, Item *pb)
{
Item t;
t = *pa;
*pa = *pb;
*pb = t;
}
void foo()
{
Item i= (Item), j=(Item)2; // These casts are not needed, but help later explanations
// Must take address so swap can change original values of i and j.
swap(&i, &j);
Item *ip = &i;
Item *jp = &j;
// This also works because we do the dereference above.
swap(ip, jj);
}
Either are fine. What about?
typedef int******* Item;
void swap (Item *pa, Item *pb)
{
Item t;
t = *pa;
*pa = *pb;
*pb = t;
}
void foo()
{
Item i= (Item)1, j=(Item)2;
// Must take address so swap can change original values of i and j.
swap(&i, &j);
int *ip = &i;
int *jp = &j;
// This also works because we do the dereference above.
swap(ip, jp);
}
Again, the type doesn't matter. It's how it's used. If you were to forget the &, the compiler would warn you about type mismatch.

Testing function with pointer parameter C

I started learning C this week and here is the first difficulty I'm encountering with pointers.
I would like to test this function:
void ft_ultimate_div_mod(int *a, int *b)
{
int *tmp;
if (b != 0)
{
*tmp = *a % *b;
*a = *a / *b;
*b = *tmp;
}
}
But I can't figure out the main using pointers. My program is not printing anything with:
int main(void)
{
int *a;
int *b;
*a = 5;
*b = 3;
ft_ultimate_div_mod(a, b);
printf("%d", *a);
printf("%d", *b);
return (0);
}
What can I do? Thx!
For starters it does not make sense to declare the variable tmp as having the type int *. The variable is used to store an object of the type int so it has to have the type int. Otherwise you are using an uninitialized pointer with an indeterminate value that results in undefined behavior of the program.
Also as the variable is used in the compound statement of the if statement then it should be declared in the blco scope of the if statement.
These declarations in main
int *a;
int *b;
als do not make sense.
What you mean is the following.
#include <stdio.h>
void ft_ultimate_div_mod(int *a, int *b)
{
if ( *b != 0 )
{
int tmp = *a % *b;
*a = *a / *b;
*b = tmp;
}
}
int main(void)
{
int a = 10;
int b = 3;
ft_ultimate_div_mod( &a, &b );
printf( "%d %d\n", a, b );
return 0;
}
The function ft_ultimate_div_mod excepts its arguments by reference because it tries to change their original values.
You declare int *tmp in your function. That is a pointer to an int sized bit of memory that can store an int. You never point it anywhere however so *tmp = *a % *b; will do a mod of a an b and then crash when it stores it using an uninitialized pointer.
Change the *tmp to just tmp so then your code becomes:
void ft_ultimate_div_mod(int *a, int *b)
{
int tmp;
if (a && b)
{
tmp = *a % *b;
*a = *a / *b;
*b = tmp;
}
}

Generic swap function using pointer to char in C

I don't understand so well how this code works:
#include <stdio.h>
void gswap(void* ptra, void* ptrb, int size)
{
char temp;
char *pa = (char*)ptra;
char *pb = (char*)ptrb;
for (int i = 0 ; i < size ; i++) {
temp = pa[i];
pa[i] = pb[i];
pb[i] = temp;
}
}
int main()
{
int a=1, b=5;
gswap(&a, &b, sizeof(int));
printf("%d , %d", a, b)
}
What I understand is that char has 1 byte(size) in memory and we are using pointers to swap each byte of the int value(4 bytes).
But in the end, how it is possible to dereference a char pointer to int value?
Let's try and figure this out, step by step, with code comments
#include <stdio.h>
//gswap() takes two pointers, prta and ptrb, and the size of the data they point to
void gswap(void* ptra, void* ptrb, int size)
{
// temp will be our temporary variable for exchanging the values
char temp;
// We reinterpret the pointers as char* (byte) pointers
char *pa = (char*)ptra;
char *pb = (char*)ptrb;
// We loop over each byte of the type/structure ptra/b point too, i.e. we loop over size
for (int i = 0 ; i < size ; i++) {
temp = pa[i]; //store a in temp
pa[i] = pb[i]; // replace a with b
pb[i] = temp; // replace b with temp = old(a)
}
}
int main()
{
// Two integers
int a=1, b=5;
// Swap them
gswap(&a, &b, sizeof(int));
// See they've been swapped!
printf("%d , %d", a, b);
}
So, basically, it works by going over any given datatype, reinterpreting as bytes, and swapping the bytes.

Pointers and Address in C

I write a C program. I have 2 pointers *a and *b. Now, I impose *a = 20 and *b = 10. After that I impose a = b in subroutine but the value seem doesn't change. I expect that *a = 10 and *b = 10. Please help me find a solution for this. Thank you.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void Copy(int *a1, int *a2)
{
a1 = a2;
}
void Test()
{
// a = 20
int *a = (int *)malloc(sizeof(int));
*a = 20;
// b = 10
int *b = (int *)malloc(sizeof(int));
*b = 10;
Copy(a, b); // a = b
printf("\na = %d", *a);
printf("\nb = %d", *b);
}
int main(int argc, char *argv[]){
Test();
fflush(stdin);
printf("\nPress any key to continue");
getchar();
return 0;
}
Function arguments are passed by value. So inside the function Copy you are modifying a copy of the pointer not the original pointer you had in the Test function. So when you leave the Copy function the pointers outside are not modified.
Change the Copy to receive a int **, so you can change inside the value of pointers
void Copy(int **a1, int **a2)
{
*a1 = *a2;
}
And call the function in this way:
void Test() {
...
Copy (&a, &b);
...
}
If you want to assign the values, such that after the call of Copy *a == *b holds, then you'd have to change your function as follows:
void Copy(int *a1, int *a2)
{
*a1 = *a2;
}
If you want to assign the pointers, such that after the call of Copy a==b holds, then you have to pass a pointer to the pointers:
void Copy(int **a1, int **a2)
{
*a1 = *a2;
}
void Test() {
...
Copy (&a, &b);
...
}
Note that a==b also implies that *a == *b.

correct way to change values of c pointers

Sorry, another C pointer question.. I have a function func() that sorts an array, then get the largest and smallest integers. I'm trying to put them inside pointer variables in main() but the values are only correct inside the func() function. I don't understand why :(
#include <stdio.h>
void func(int arr[], int *s, int *l, int n){
int i = 1;
for(; i < n; i++){
int temp = arr[i];
int n = i;
while( n > 0 && arr[n-1] > temp){
arr[n] = arr[n-1];
n--;
}
arr[n] = temp;
}
l = &arr[n-1];
s = &arr[0];\
printf("%d %d\n",*l,*s);
}
int main(void){
int arr[] = {1,2,9,3,58,21,4};
int *s, *l;
int size = 7;
func(arr,s,l,size);
printf("%d %d\n",*l,*s);
}
When you pass a pointer as an argument to a function in C, a copy of the pointer is made. Thus, changing the value of the pointer has no effect outside of that function. However, changing the value at the memory referenced by the pointer will take effect everywhere, as you want. In your case, you would need to do this:
void func(int arr[], int *s, int *l, int n){
// sorting code..
// l = &arr[n-1]; WRONG - these change the value of the pointer,
//s = &arr[0];\ without changing the value of the memory they reference
*l = arr[n-1]; // CORRECT - changes the value at the referenced memory
*s = arr[0];
printf("%d %d\n",*l,*s);
}
Of course, the way you're using the pointers in main is also incorrect; they're uninitialized and likely to cause a segmentation fault. Since there appears to be no reason to use actual int* variables over ordinary int variables there, we can take another approach to passing them "by reference":
int main(void){
int arr[] = {1,2,9,3,58,21,4};
// int *s, *l; WRONG - we don't need pointers, we need to pass regular ints
int s, l;
int size = 7;
// Get the address of our variables with the address-of (&) operator
// This effectively creates int* variables out of our int variables
func(arr, &s, &l,size);
printf("%d %d\n",*l,*s);
}
Note that the term "by reference" here is not correct in the true sense of the phrase, since you are still receiving a copy of the address associated with the variable. Most languages provide a true by-reference faculty by removing this distinction and only allowing you access to the variable and its value, with the copying somewhat out of sight of the programmer. You can think of this as being "by reference with respect to l and s inside main", in the sense that their values can change due to the called function.
You need to pass the address of the pointer variables if you want to change what they are pointing at, otherwise a copy of the pointer variable is being changed inside the function (and is why it is correct within the function):
void func(int arr[], int** s, int** l, int n){
/* snip */
*l = &arr[n-1];
*s = &arr[0];
}
func(arr, &s, &l, size);
This would leave s and l pointing to elements of the array arr. If you just wanted the values of integers then the alternative would be to define int variables in main() and pass their addresses to func() and copy the relevent values from the array:
void func(int arr[], int* s, int* l, int n){
/* snip */
*l = arr[n-1];
*s = arr[0];
}
int s, l;
func(arr, &s, &l, size);
See this question from the C FAQ.
Your pointers are not initialized. You have two solutions:
use integers in main function (and eventually, although useless, make pointers point to them in the same function);
dynamically allocate memory for your pointer.
Easiest code:
#include <stdio.h>
int main(void)
{
int arr[] = {1, 2, 9, 3, 58, 21, 4};
int s, l;
int size = 7;
func(arr, &s, &l, size);
printf("%d %d\n", l, s);
}
In the current code, you don't need to make l and s point to the case of the array. So, as Dan F stated, you can just do integer's assignment.
void func(int arr[], int *s, int *l, int n)
{
int i = 1;
for(; i < n; i++){
int temp = arr[i];
int n = i;
while( n > 0 && arr[n-1] > temp){
arr[n] = arr[n-1];
n--;
}
arr[n] = temp;
}
*l = arr[n-1];
*s = arr[0];
printf("%d %d\n", *l, *s);
}

Resources