String swap by swap function - c

I have written code to swap strings, but I am not able to swap. What is the problem and how can I solve it by using a function, swap?
#include <stdio.h>
void swap( char*,char*);
int main()
{
char *ptr[2] = {"hello", "morning"};
swap(ptr[0], ptr[1]);
printf("%s %s", ptr[0], ptr[1]);
return 0;
}
void swap(char *t1, char*t2)
{
char *t;
t = t1;
t1 = t2;
t2 = t;
}
I also tried to pass (&ptr[0], &ptr[1]), but here it shows a segmentation fault. Also I made a char, *p1 = ptr[0], char *p1 = ptr[1], and then passes &p1, and &p2 to swap, but still I get a segmentation fault.

C function arguments are pass-by-value. You're passing the value of addresses to your swap function, and expecting those values, the addresses, to change. But only the copies of the addresses in your swap function change.
To change the actual passed-in addressed, you'll need an aditional level of reference:
void swap(char **t1, char **t2)
{
char *t;
t = *t1;
*t1= *t2;
*t2 = t;
}
And call this swap like so: swap(&ptr[0], &ptr[1]);

You need to pass in pointers to the pointers of the char arrays in order to switch them. By doing that you can swap the values of those pointers instead. (Which are the actual arrays.)
#include<stdio.h>
void swap( char**,char**);
int main()
{
char *ptr[2] = {"hello","mornig"};
swap(&ptr[0], &ptr[1]);
printf("%s %s",ptr[0], ptr[1]);
return 0;
}
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}

You need to pass pointers to your strings to swap them (char**). Otherwise the changes you do will be local to the swap function.
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
int main()
{
char *ptr[2] = {"hello","mornig"};
swap(&ptr[0], &ptr[1]);
printf("%s %s",ptr[0],ptr[1]);
return 0;
}

char *ptr[2] = {"hello","mornig"}; - This statement means you are allocating an array of size 2 which is going to store a address of two strings(ie char *). Now the two strings you are giving will be in text segment which is a read only data. If we tries to modify it, which will leads to crash(sgmentation fault).
So if you call swap(&ptr[0], &ptr[1]) leads to a crash. because you are trying to write the charcter m in the first read only string h. Write is not possible to the string which is in text segment.
If you want to simply swap a string you can call the function as swap(&ptr[0], &ptr[1]), which is equivalent to swap((ptr + 0),(ptr + 1));.
And change the swap function as below
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
Here we are just swapping the address of the string stored in the array pointer ptr.

Related

Using realloc to expand vector of structures in c

I was trying to write a stack in C, but i had some problems regarding realloc. Finally i managed to write a working program but i don't get why does it work and why i have to give on the input of my functions put_on_fun_stack and get_from_fun_stack a pointer to my table of structures.
When i tried to give it like put_on_fun_stack(stack_t *s, ...) it didin't work. Why do i have to put pointer in realloc and why do i have to write a (*s)[*l], and i can't write *s[*l]. Can somebody please explain the pointers to structures?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int *n;
char *name;
}stack_t;
void init(stack_t **s){
*s=malloc(0);
}
void put_on_fun_stack(stack_t **s, char *name, int *l, int n){
*s = realloc(*s, (*l+1) * sizeof(stack_t));
(*s)[*l].name = name; //why do i need (*s) ?
(*s)[*l].n = n;
*l=*l+1;
}
char* get_from_fun_stack(stack_t **s, int *l){
char *temp = (*s)[*l-1].name;
*s = realloc(*s, (*l - 2) * sizeof(stack_t));
*l=*l-2;
return temp;
}
void rm(stack_t *s){
free(s);
}
int main(int argc, char **argv){
char *name;
stack_t* s;
init(&s);
int i;
int l=0;
srand(time(0));
if (argc>1)
for(i=1;i<argc;i++){
printf("%s\n", argv[i]);
put_on_fun_stack(&s, argv[i], &l, rand()%10);
printf("name=%s, n=%d, l=%d \n", s[l-1].name,s[l-1].n, l-1);
}
rm(s);
return 0;
}
C is pass by value so when you call put_on_fun_stack() and you just pass s you have a copy of main's value of s and not the address of s. You can't change the value of s that's in main. In other words, when you had it coded as s = realloc(s, (*l - 2) * sizeof(stack_t)); you're only changing the value of s in put_on_fun_stack() and it doesn't affect the s from main.
You fixed that by passing the address of s in main to put_on_fun_stack() and so as coded *s = realloc(*s, (*l - 2) * sizeof(stack_t)); the value of s in main gets set as you need it to.
As for (*s)[*l] vs *s[*l], it's a matter of operator precedence. [] binds tighter than * so *s[*l] is the same as *(s[*l]). Not what you want.
If your question is, why does (*s)[*l] work you have to look at what s is. s is a stack_t **, (*s) then is a stack_t * and (*s)[*l] then is the *lth element of the array pointed to by (*s).
Looking at why the other one doesn't work, (s[*l]) is the *lth element of an array of stack_t * and then *s(*l]) is the 0th element of the *lth stack_t *. It will only work when *l is 0.
It would be confusing but you can avoid the () by coding it as s[0][*l]. A cleaner way to clean it up is to dereference s and save it in a local variable, sort of like this:
void put_on_fun_stack(stack_t **ps, char *name, int *pl, int n){
stack_t *s;
int l=*pl;
s = realloc(*ps, (l+1) * sizeof(stack_t));
s[l].name = name;
s[l].n = n;
// return the updated values
*pl=l+1;
*ps=s;
}

What is the trick for swap_pointers to work?

I am doing an exercise where the task is to fix swap_pointer().
Two string should be swapped.
s1 = "I should print second.";
s2 = "I should print first.";
My work so far:
#include <stdio.h>
void swap_nums(int *, int *);
void swap_pointers(char *x, char *y);
int main(void) {
int a = 3, b = 4;
char *s1, *s2;
swap_nums(&a, &b);
printf("a is %d\n", a);
printf("b is %d\n", b);
s1 = "I should be printed second.";
s2 = "I should be printed first.";
/* swap_pointers(s1, s2); */
printf("s1 is %s\n", s1);
printf("s2 is %s\n", s2);
return 0;
}
void swap_nums(int *x, int *y) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
void swap_pointers(char *x, char *y) {
char tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
I think that not appending & to s1 and s2 before I pass them to the function for swap_pointers is the error?
If anyone can fix my issue here, please don't give the whole solution! I want to use what you give me as a tool to fix it by my own. If I really can't fix it by my own I will adress this later.
Ty in advance!
Let's at first consider this code snippet
int a = 3, b = 4;
swap_nums(&a, &b);
To swap the objects a and b you need to pass then to the function swap_nums by reference through pointers to them. Thus within the function dereferencing the pointers we can get a direct access to original objects and change their values.
void swap_nums(int *x, int *y) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
The same we need to do with the variables s1 and s2. That is we need to pass them to the function swap_pointers by reference through pointers to them.
So you need to write
swap_ponters( &s1, &s2 );
and the function will be declared and defined like
void swap_ponters(char **x, char **y)
{
char *tmp = *x;
*x = *y;
*y = tmp;
}
In general if you have two objects like
T a;
T b;
where T is some type specifier then to change the objects in a function you need to pass them to the function by reference through pointers to them. So the declaration of the function swap will look like
void swap( T *a, T *b );
and the function will be called like
swap( &a, &b );
In your program a and b has the type int, that is T is an alias for the type int.
typedef int T;
T a = 3, b = 4;
so the function declaration will look like
void swap_nums( T *x, T *y );
For the variables s1 and s2 you can write
typedef char *T;
T s1, s2;
and again the function declaration will look like
void swap_pointers( T *x, T *y );
and the function will be called like
swap_pointers( &s1, &s2 );
As in this case T is an alias for the type char * then the function declaration can be rewritten like
void swap_pointers( char * *x, char * *y );
Your pass the pointers to the first characters of two null-terminated strings to the swap_pointers function.
Inside the function, when you use e.g. *x it's the same as x[0].
So you're swapping the first character of x with the first character of y.
If you want to switch pointers, you need to emulate pass-by-reference like you do with swap_nums, and pass pointers to the pointers, i.e. char **. And use the pointer-to operator & in the call.
So it should be
void swap_ponters(char **x, char **y);
and
swap_pointers(&s1, &s2);

Why doesn't this swapping function work? (swapping strings in C)

I am trying to swap 2 entries in an array of strings, but my swap function doesn't swap when called.
swap(char*, char*);
int main() {
char *ptsr[2] = { "x", "y" };
swap(ptsr[0], ptsr[1]);
}
swap(char *t1, char *t2) {
char *t;
t = t1;
t1 = t2;
t2 = t;
}
Can someone identify and explain my mistake?
C is strictly pass by value. You pass the values of ptsr[0] and pstr[1] to swap. It swaps where it keeps those two values, but that has no effect on the calling function. Consider:
swap (int v1, int v2)
{
int t;
t = v1;
v1 = v2;
v2 = t;
}
This is the same as your swap function, just using int instead. It should be pretty clear that if you call swap(1,2);, the swap function just puts the 2 where it was storing the 1 and vice versa, but that has no effect on anything in the caller.
Same if you do this:
int i = 2;
int j = 3;
swap(i,j);
Since all you passed to swap is the values 2 and 3, it cannot affect the values of i and j by any means.
And same with your swap function if you do this:
char* j = "hello";
char* k = "world";
swap(j,k);
The function receives "hello" and "world" and swaps where it stores those two pointers. This has no effect on j or k in the caller.
C is strictly pass by value. Whatever parameters you pass to a function, the function only receives the values of.
The function in the question only swaps the values of its argument. The arguments are copies of the array elements, so the swap function has no effect.
To swap the pointers in the array, you must pass their addresses and change the prototype of the swap function:
#include <stdio.h>
void swap(char **t1, char **t2) {
char *t;
t = *t1;
*t1 = *t2;
*t2 = t;
}
int main() {
char *ptsr[2] = { "x", "y" };
swap(&ptsr[0], &ptsr[1]);
printf("pstr: { \"%s\", \"%s\" }\n", pstr[0], pstr[1]);
return 0;
}
Functions accept their arguments by value.
That is the function swap (for which you forgot to specify the return type void)
void swap(char *t1, char *t2) {
char *t;
t = t1;
t1 = t2;
t2 = t;
}
deals with copies of values of the expressions ptsr[0] and ptsr[1]. Chamging the copies does not influence on the original pointers.
You may imagine the function definition and its call the following way
swap(ptsr[0], ptsr[1]);
//...
void swap( /*char *t1, char *t2*/) {
char *t1 = ptsr[0], *t2 = ptsr[1];
char *t;
t = t1;
t1 = t2;
t2 = t;
}
As you can see the variables and ptsr[0] and ptsr[1] were not be changed.
To change an object (that in particularly can have a pointer type) in a function you need to pass it to the function by reference.
In C passing by reference means passing an object indirectly through a pointer to it.
So the function swap will look like
void swap(char **t1, char **t2) {
char *t;
t = *t1;
*t1 = *t2;
*t2 = t;
}
and the function must be called .like
swap( &ptsr[0], &ptsr[1] );
Or as the same
swap(ptsr, ptsr + 1);
Dereferencing the pointers to pointers t1 and t2 the function gets a direct access to the original pointer ptsr[0] and ptsr[1] swapping their values.

How to sort strings with this code? I am failing at basics

I am trying to sort city names inputted. The code below seems correct to me, but while it does compile successfully, it does not work as I expected.
Am I failing in understanding pointers? Let me correct if below are true:
names type is a char **
names[0] type is char *
If I want to swap strings after checking if they are bigger with strcmp(), I have to change the values inside names[i] and names[j] because the values inside these values are pointers to actual city names. When these are interchanged, they point to each others' char array and I am done.
If my 3rd idea is true, I have to pass parameters to swap function as char * because swap function will take names[i] and names[j] as parameters and the type of these are char *.
The thinking was like above while writing the code below. But it seems I am failing at my logic because code does not work as intended.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j;
char *temp;
void swap(char *, char *);
int main(void){
char *names[4];
//gets city names
puts("Enter 4 city names:");
for (i = 0; i < 4; i++)
{
names[i]=malloc(100);
fgets(names[i],99,stdin);
}
//bubble sort names array and swap if necessary
for (i = 0; i < 3; i++)
{
for (j = i+1; j<4 ; j++)
{
if (strcmp (names[i],names[j]) >0 )
{
swap(names[i], names[j]);
}
}
}
puts("Printing sorted array");
for (i = 0; i < 4; i++)
{
printf("%s", names[i]);
}
getch();
}
void swap(char *first, char *second){
temp=first;
first=second;
second=temp;
}
You need to pass a pointer to the pointer:
void swap(char **first, char **second)
{
char *temp = *first;
*first = *second;
*second = temp;
}
As it was you are only modifying the copy of the pointer, not the original. We use pointers to look at the original...hence you need a pointer to a pointer; you are modifying a pointer!!
To get your head round it, I'd recommend swapping your pointers to strings for ints and sort those instead. If it was ints you were sorting your swap function would look like this:
void swap(int first, int second) // These ints/parameters have been copied
{
first = second; // This only modifies the local copy
// etc..
}
To modify the original values you would need to use a pointer:
void swap(int *first, int *second)
{
*first = *second;
// etc...
}
Your swap function has no effect at all at the passed pointers, you need to change it like this, so that the passed pointers are modified:
swap(&names[i], &names[j]);
void swap(char **first, char **second)
{
temp=*first;
*first=*second;
*second=temp;
}
Your swap function has no effect. Because I feel it is not obvious for you, let's try with a simpler example.
If you wanted to swap two integers, your function would take int instead of char*. Your function would be (I have just replaced the char* by int):
void swap(int first, int second){
int temp=first;
first=second;
second=temp;
}
When you call swap(a, b) with a and b 2 int variables, their values are copied into first in second. Then you swap the contain of the variables first and second. The important point is that you don't change the original variables a and b.
The correct function would be:
void swap(int *first, int *second){
int temp=*first;
*first=*second;
*second=temp;
}
Because that way, you pass the address of the variables and you modify the original variables this way. If it is not clear, you should document yourself about what is a pointer and how it works.
Now, you can change back the int by a char*:
void swap(char **first, char **second){
char* temp=*first;
*first=*second;
*second=temp;
}
Your swap function is incorrect, you can't assign strings like that. You need something like this (non-optimal)
void swap(char *a, char *b) {
char tmp[256];
strcpy(tmp, a);
strcpy(a, b);
strcpy(b, tmp);
}
Your problem is not with pointers, but with function calls. When you pass a value to a function, and modify that value, the "source" of the value is not necessarily changed.
void swap(char **first, char **second) {
char *temp;
temp=*first;
*first=*second;
*second=temp;
}
swap(&names[i], &names[j]);
Or you could do it like this:
void swap(char **arr, int x, int y) {
char *temp;
temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
swap(names, i, j);
In the first case you pass to the function the two addresses, the contents of which are to be changed. In the second you pass the master array address, and the two locations.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j;
char *temp;
void swap(char **, char **);
int main(void){
char *names[4];
//gets city names
puts("Enter 4 city names:");
for (i = 0; i < 4; i++)
{
names[i]=malloc(100);
fgets(names[i],99,stdin);
}
//bubble sort names array and swap if necessary
for (i = 0; i < 3; i++)
{
for (j = i+1; j<4 ; j++)
{
if (strcmp (names[i],names[j]) >0 )
{
swap(&names[i], &names[j]);
}
}
}
puts("Printing sorted array");
for (i = 0; i < 4; i++)
{
printf("%s", names[i]);
}
}
void swap(char **first, char **second){
temp=*first;
*first=*second;
*second=temp;
}

Swap char with table pointers in C

I'm trying to swap two char with two table pointers.
Can someone explain to me what's wrong in my code?
The terminal says char** is expected but I don't know what to do, so I think I don't really understand how pointers work for tables.
void echangeM2(char **ptab1, char **ptab2){
char *tmp = *ptab1;
*ptab1 = *ptab2;
*ptab2 = *tmp;
printf("%s\t %s",*ptab1,*ptab2);
return;
}
int main(void) {
char tab1[25];
char tab2[25];
char *adtab1;
char *adtab2;
*adtab1 = &tab1;
*adtab2=&tab2;
printf("type two words");
scanf("%s %s",tab1,tab2);
echangeM2(adtab1,adtab2);
return 0;
}
The following code should work for you:
#include <stdio.h>
void exchangeM2(char* *ptab1, char* *ptab2) { // accepts pointer to char*
char* tmp = *ptab1; // ptab1's "pointed to" is assigned to tmp
*ptab1 = *ptab2; // move ptab2's "pointed to" to ptab1
*ptab2 = tmp; // now move tmp to ptab2
printf("%s\t %s",*ptab1,*ptab2);
}
int main(void) {
char tab1[25];
char tab2[25];
char* adtab1;
char* adtab2;
adtab1 = tab1; // array name itself can be used as pointer
adtab2 = tab2;
printf("type two words");
scanf("%s %s",tab1,tab2);
exchangeM2(&adtab1, &adtab2); // pass the address of the pointers to the function
}
echangeM2(&adtab1,&adtab2);
This should fix the compile errors. You are passing char* pointers to a function that expects a char ** pointer
Edit: Actually looks like you want something like
char **adtab1;
char **adtab2;
adtab1 = &tab1;
adtab2=&tab2;
...
echangeM2(adtab1,adtab2);

Resources