Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

Swap two strings using call by value and call by reference in C

+1 vote
asked Jul 18, 2020 by Rakshit Arora (170 points)
Please do not predefine the strings. I want to ask the user to input the strings.

1 Answer

+1 vote
answered Jul 20, 2020 by Peter Minarik (84,720 points)

Swapping String

You can swap strings in 3 different way: swap the reference, swap the content (characters) of the string (char *) or swap the characters in a buffer (char[]). Let's have a look one-by-one.

Swapping Strings (char *)

void swapStrings(char ** s1, char ** s2)
{
    size_t s1Length = strlen(*s1);
    size_t s2Length = strlen(*s2);
    
    char * tmp1 = (char*)malloc(sizeof(char) * s2Length + 1);
    strcpy(tmp1, *s2);

    // We can just reallocate (change the size of the string) s2.
    // During realloc, the value may be lost, thus we needed to copy s2 first.
    // For the same reason we cannot reallocate s1 too.
    *s2 = (char*)realloc(*s2, sizeof(char) * s1Length + 1);
    strcpy(*s2, *s1);
    
    free(*s1);
    *s1 = tmp1;
}

The key here is that we do not know the length of these strings. They may be of different length. We need to destroy the old strings (free()) and create new ones (malloc()). We an also utilize reallocation of memory -- or resizing the string -- via the user of realloc().

Swapping Pointers (const char *)

The argument looks very similar to the string swapping function. In this case, we can use const strings as well. The main difference here, is that we do not copy values of the strings (char *) from one to the other, merely swap the pointers that tell us what location in the memory these strings can be found.

void swapPointers(const char ** s1, const char ** s2)
{
    const char * tmp = *s1;
    *s1 = *s2;
    *s2 = tmp;
}

Swap Buffers (char [])

In this method, we expect char[] as input. The trick here is that the buffer may (or may no) be longer than the string itself. Also, to copy the content of one buffer to the other, the size of the target buffer needs to support the size of the source string. (Please, notice that the size of the buffer is not the same as the size of the string. E.g. char buffer[10] = "OK" will have a size of 10, but length is only 2)

bool swapBuffers(char buf1[], size_t len1, char buf2[], size_t len2)
{
    if (strlen(buf1) + 1 > len2 || strlen(buf2) + 1 > len1)
        return false;   // Not enough space in the buffer for the strings + the terminating zero;

    char tmp[len1];
    strcpy(tmp, buf1);
    strcpy(buf1, buf2);
    strcpy(buf2, tmp);
    return true;
}

User Input

You can use scanf() to take user input. I leave this part to implement for you. Just check the documentation. It's really not hard.

The Whole Code

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swapStrings(char ** s1, char ** s2)
{
    size_t s1Length = strlen(*s1);
    size_t s2Length = strlen(*s2);
    
    char * tmp1 = (char*)malloc(sizeof(char) * s2Length + 1);
    strcpy(tmp1, *s2);

    // We can just reallocate (change the size of the string) s2.
    // During realloc, the value may be lost, thus we needed to copy s2 first.
    // For the same reason we cannot reallocate s1 too.
    *s2 = (char*)realloc(*s2, sizeof(char) * s1Length + 1);
    strcpy(*s2, *s1);
    
    free(*s1);
    *s1 = tmp1;
}

void swapPointers(const char ** s1, const char ** s2)
{
    const char * tmp = *s1;
    *s1 = *s2;
    *s2 = tmp;
}

bool swapBuffers(char buf1[], size_t len1, char buf2[], size_t len2)
{
    if (strlen(buf1) + 1 > len2 || strlen(buf2) + 1 > len1)
        return false;   // Not enough space in the buffer for the strings + the terminating zero;

    char tmp[len1];
    strcpy(tmp, buf1);
    strcpy(buf1, buf2);
    strcpy(buf2, tmp);
    return true;
}

void swapPointersTest()
{
    printf("Pointer swap:\n");
    printf("-------------\n");
    const char * s1 = "Hello";
    const char * s2 = "World!";
    printf("Before swap: %s (%p), %s (%p)\n", s1, s1, s2, s2);
    swapPointers(&s1, &s2);
    printf("After swap: %s (%p), %s (%p)\n", s1, s1, s2, s2);
}

void swapStringsTest()
{
    printf("String swap:\n");
    printf("------------\n");
    char * s1 = (char*)malloc(sizeof(char) * sizeof("Hello"));
    strcpy(s1, "Hello");
    char * s2 = (char*)malloc(sizeof(char) * sizeof("World!"));
    strcpy(s2, "World!");
    printf("Before swap: %s (%p), %s (%p)\n", s1, s1, s2, s2);
    swapStrings(&s1, &s2);
    printf("After swap: %s (%p), %s (%p)\n", s1, s1, s2, s2);
}

void swapBuffersTest()
{
    printf("Buffer value swap:\n");
    printf("------------------\n");
    char s1[] = "Hello\0\0\0\0"; // With terminating zero, we allocate more space in thebuffer, so there's enough room for the other string too
    char s2[] = "World!\0\0";
    printf("Before swap: %s (%p), %s (%p)\n", s1, s1, s2, s2);
    if (swapBuffers(s1, sizeof(s1), s2, sizeof(s2)))
        printf("After swap: %s (%p), %s (%p)\n", s1, s1, s2, s2);
    else
        printf("Unable to swap. Buffer sizes are too small.");
}

void main()
{
    swapPointersTest();
    printf("\n\n");
    swapStringsTest();
    printf("\n\n");
    swapBuffersTest();
    printf("\n\n");
}
Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...