Don't know how to define my swap function properly - c

I can understand pointers to a certain extent but the multiple layers of dereferencing in swap() is confusing me. Thus,I'm unable to implement it correctly.
Below is a code on alphabetizing based on insertion sort:
void insertionSort(char **array,int rows,int cols)
{
for(int i=1;i<=rows-1;i++)
{
for(int j=i-1;strcmp(array[i],array[j])<0 && j>=0;j--)
{
swap(&array[i],&array[j]);
i--; //when swapped, subscript of key also drops
}
}
}
void swap(char **s1,char**s2)
{
char **temp=s1;
strcpy(*s1,*s2);
strcpy(*s2,*temp);
}
I know the swap() is wrongly implemented. I hopefully would like to know how to step through the thinking process to correctly implement swap()(ie how to understand the muliple layers of dereferencing better)

You don't want to use strcpy at all. You simply want to swap two char *s, to which you have pointers (char **s). As such, the implementation should be the same as any other swap. The temporary should be a char *, and you should be swapping the char * values, not copying the strings that lie behind them.
void swap(char **s1,char **s2)
{
char *temp = *s1;
*s1 = *s2;
*s2 = temp;
}
This is exactly the same as e.g. a function for swapping ints, except with int replaced by char *.

Related

How I can make a string array interchange it's components with a swap function?

The problem is that this code won't interchange these 2 strings. I'm new to programming but I can tell that the problem is that swap function, but I do not know how to fix it.
I tried to add strcpy instead of "=" in swap but that didn't worked.
#include <stdio.h>
#include <stdlib.h>
void swap(char *t1, char *t2) {
char *t;
t=t1;
t1=t2;
t2=t;
}
int main() {
char *s[2] = {"Hello", "World"};
swap(s[0], s[1]);
printf("%s\n%s", s[0], s[1]);
return 0;
}
You want to use out parameters here, and since your strings are represented as pointers, you need pointers to pointers:
void swap(char **t1, char **t2) {
char *t;
t = *t1;
*t1 = *t2;
*t2 = t;
}
Call it like this:
swap(&s[0], &s[1]);
I tried to add strcpy instead of "=" in swap but that didn't worked.
The reason why that doesn't work is because the strings are actually stored in the program's binary and therefore can't be modified, and with strcpy you would write over them. If you copy them to the stack or the heap instead then you can do the swap with strcpy. Of course that's going to be less efficient than just swapping the pointers, but this is how it would look like:
void swap(char *t1, char *t2) {
char buf[16]; // needs to be big enough to fit the string
strcpy(buf, t1);
strcpy(t1, t2);
strcpy(t2, buf);
}
Also you would need to change the definition of s to something akin to
char s[2][16] = { "Hello", "World" }; // strings are copied to the stack now
Check the types carefully.
What you have got as array members are pointers (to the starting element of string literals). You need to swap the members in a way so that they point to the other string literal. So, you need to change those pointers themselves.
So, you need to pass pointer to those pointers and then make the change from the called function.
Do something like
swap(&(s[0]), &(s[1]));
and then, in the called function:
void ptrSwap(char **t1, char **t2) {
char *temp;
temp=*t1;
*t1=*t2;
*t2=temp;
}
Bonus points: Name your functions (and variables, too, wherever applicable) meaningfully.
You need to passing the pointer of pointer, i.e. address of the position in array where the strings are present, so that you can swap and place correct addresses there.
Try the below code:
#include <stdio.h>
#include <stdlib.h>
void swap(char **t1, char **t2) {
char *t;
t=*t1;
*t1=*t2;
*t2=t;
}
int main() {
char *s[2] = {"Hello", "World"};
swap(&s[0], &s[1]);
printf("%s\n%s", s[0], s[1]);
return 0;
}
Output:
World
Hello

Pointers, Strings and functions in C

I've missed a week of class in which they covered pointers but I haven't been able to get the notes from class but my HW is due and I still don't understand how to use pointers to pass strings from function to function... below is my code in which I realize the pointers are beyond messed up but I've tried to read other forums but just get lost. Any help is appreciated.
#include <stdio.h>
char* returnInPlace(char);
int palindrom(char, char );
main(void)
{
char newString[20];
printf("Enter a string: ");
scanf("%s",&newString);
char flippedString[20]=reverseInPlace(newString);
int palCheck= palindrome(newString, flippedString);
if (palCheck==0)
printf("\n\tThe reverse string is %s, so we don't have a palindrome.", flippedString);
else
printf("\n\tThe reverse string is %s, so we do have a palindrome.", flippedString);
}
char* reverseInPlace(char newString)
{
int iterator;
char flipped[20];
char *ptr1;
for(iterator=0;iterator<20;iterator++)
{
flipped[iterator]=firstString[19-iterator];
}
ptr1=flipped[];
return *ptr1;
}
int palindrome(char newString, char flippedString)
{
int iterator;
int palCheck=1;
for(iterator=0;iterator<20;iterator++)
{
if (firstString[iterator]==secondString[iterator])
continue;
else
{
palCheck=0;
break;
}
}
return palCheck;
}
Problem 1
In char* reverseInPlace(char newString), you're using
return *ptr1;
which is wrong. What you may want is
return ptr1;
Problem 2
ptr1=flipped[];
is wrong. Here, you're assigning the base address of a local variable flipped and returning that value. flipped will cease to exist after reverseInPlace() finishes execution. You need to use dynamic memory allocation.
Problem 3
char flippedString[20]=reverseInPlace(newString);
is wrong. You cannot assign an array with = unless as initialization at time of definition.
Problem 4
char* reverseInPlace(char newString)
this function definition looks wrong by seeing the way it is being called. Maybe what you want is
char* reverseInPlace(char* newString)
instead.
......and maybe many more. Strongly suggest to read some good book about Pointers and C basics before jumping into writing code.

Swap strings using strcpy

I am trying to swap two strings by using only pointer notation, (no arrays), with
a function that looks like this
void str_switch(char *a, char *b)
the swapping should work irrespective of the sizes of b and a, and it is not known.
my idea is this:
void str_switch(char *a, char *b) {
const char *temp = a;
strcpy(b, temp);
}
however, after this, I am not sure how to copy b to a, because b changes, I tried declaring other constant pointers, but once I change b, I can never get the old version.
This strays from your question, heading in particular as strcpy is not used, and follow your comment to Martin James:
void str_switch(char **a, char **b) {
char *tmp = *a;
*a = *b;
*b = tmp;
}
If you really want to use strcpy you'll have to know size of C-strings.
if your strings are stored in allocated memories using functions like malloc(); thus this code works perfectly for that case, especially as it treats strings with different size and length
#include <stdio.h> // list of libraries that need to be included
#include <stdlib.h>
#include <string.h>
void str_switch(char **a, char **b) {
if (strlen(*a)>strlen(*b)) // check the strings with lowest size to reallocate
{ // in order to fit the big one
char *temp=malloc((strlen(*a)+1)*sizeof(char)); // temp variable to preserve the lowest
// the variable with lowest length
strcpy(temp,*a); // store the longest string in its new location
strcpy(*a,*b);
free(*b); // free the allocated memory as we no longer need it
*b=temp; // assign the new address location for the lowest string
}
else if (strlen(*b)>strlen(*a)) // the same as above but invert a to b and b to a
{
char *temp=malloc((strlen(*b)+1)*sizeof(char));
strcpy(temp,*b);
strcpy(*b,*a);
free(*a);
*a=temp;
}
else // if the lengths are equal ==> #Morpfh solution
{
char *tmp = *a;
*a = *b;
*b = tmp;
}
}
This is a test for function above (main code)
int main(int argc, char *argv[])
{
char *a=malloc(sizeof(char)*6);
strcpy(a,"hello");
char *b=malloc(sizeof(char)*4);
strcpy(b,"bye");
printf("a=%s\nb=%s\n",a,b);
str_switch(&a,&b);
printf("----------------------\n");
printf("a=%s\nb=%s\n",a,b);
return 0;
}
and we get
a=hello
b=bye
----------------------
a=bye
b=hello
If you don't want to allocate extra storage, you would need to switch the strings by swapping one character at a time.
If you are OK allocating extra storage, strdup a, strcpy b into a, strcpy the copy of a into b, then free the copy.

please help making strstr()

I have made strstr() function but the program does not give any output,just a blank screen.Please have a look at the code.
#include<stdio.h>
#include<conio.h>
const char* mystrstr(const char *str1, const char *str2);
int main()
{
const char *str1="chal bhai nikal";
const char *str2="nikal",*result;
result=mystrstr(str1,str2);
printf("found at %d location",(int*)*result);
getch();
return 0;
}
const char * mystrstr(const char *s1, const char *s2)
{
int i,j,k,len2,count=0;
char *p;
for(len2=0;*s2!='\0';len2++);//len2 becomes the length of s2
for(i=0,count=0;*s1!='\0';i++)
{
if(*(s1+i)==*s2)
{
for(j=i,k=0;*s2!='\0';j++,k++)
{
if(*(s1+j)==*(s2+i))
count++;
if(count==len2)
{
p=(char*)malloc(sizeof(char*));
*p='i';
return p;
}
}
}
}
return NULL;
}
The line with this comment:
//len2 becomes the length of s2
is broken. You repeatedly check the first character of s2. Instead of *s2, try s2[len2].
Edit: as others have said, there are apparently a lot more things wrong with this implementation. If you want the naive, brute-force strstr algorithm, here's a concise and fast version of it:
char *naive_strstr(const char *h, const char *n)
{
size_t i;
for (i=0; n[i] && h[i]; i++)
for (; n[i] != h[i]; h++) i=0;
return n[i] ? 0 : (char *)h;
}
It looks like this is an exercise you're doing to learn more about algorithms and C strings and pointers, so I won't solve those issues for you, but here are some starting points:
You have an infinite loop when calculating len2 (your loop condition is *s2 but you're never changing s2)
You have a similar issue with the second for loop, although I you have an early return so it might not be infinite, but I doubt the condition is correct
Given you want to behave like strstr(), you should return a pointer to the first string, not a new pointer you allocate. There is no reason for you to allocate during a function like strstr.
In main() if you want to calculate the position of the found string, you want to print result-str1 unless result is NULL). (int*)*result makes no sense - result should be a pointer to the string (or NULL)
You also need to change this line:
if(*(s1+j)==*(s2+i))
to this:
if(*(s1+j)==*(s2+k))
As already mentioned, the return value is a bit odd. You are returning a char* but kind of trying to put an integer value in it. The result doesn't make sense logically. You should either return a pointer to the location where it is found (no malloc needed) or return the integer position (i). But returning the integer position is not the "typical" strstr implementation.

Pushing a 1-D array onto a 2-D array in C

I am working on a queue data structure. The structure is:
struct queue
{
char array[MAX_LENGTH][8];
int back;
};
It is designed to store a list of MAX_LENGTH strings that are 7 chars long.
I wish to push a 1D array of 8 chars (well, 7 chars and \0, just like the array in the struct).
I have this push code:
void push (struct queue *q, char s[]){
q->array[q->back] = s;
}
Which I figure might work, but apparently does not. In cl (.net's C/C++) compiler, I get the following error:
2.c(29) : error C2106: '=' : left operand must be l-value
gcc returns a similar error, on the same line (but I forget, and don't have access to gcc at the moment).
I'm fairly new to structs, and pointers so there's probably something very obvious I'm not doing. Appreciate any help :)
Change it to:
void push (struct queue *q, char s[])
{
strcpy(q->array[q->back], s);
}
You can assign structs in C using = but you can't assign arrays - you have to use strcpy/memcpy for things like this.
You have to treat q->array just as you would any other array. You can't just "push" it, you have to pass the location you want to put it in then copy each character (or use q->back as your location). Something like this perhaps:
void push (struct queue *q, char s[]){
int i;
for ( i = 0; s[i]; ++i )
q->array[q->back][i] = s[i];
q->array[q->back][i] = '\0';
}
Or use strcpy:
void push (struct queue *q, char s[]){
strcpy(q->array[q->back], s);
}
If you want a bounds-checked strcpy using only the standard C library functions, then strncat is actually your best bet:
void push (struct queue *q, char s[])
{
q->array[q->back][0] = 0;
strncat(q->array[q->back], s, sizeof q->array[q->back] - 1);
}
On the other hand, if you know for certain that s always points to an array of the same size as the array in the struct (as your question states), then memcpy is the simplest solution:
void push (struct queue *q, char s[])
{
memcpy(q->array[q->back], s, sizeof q->array[q->back]);
}
strncpy(q->array[q->back], s,MAX_LENGTH) could be better to avoid buffer overflow

Resources