I have this short code:
#include <stdio.h>
void fastSwap (char **i, char **d)
{
char *t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "hello";
char num2[] = "class";
fastSwap ((char**)&num1,(char**)&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
The output of this short program is:
claso
hells
and I just don't understand why the last letters of each char[] are swapped.
Any ideas?
fastSwap ((char**)&num1,(char**)&num2);
This is undefined behavior. You can't cast a pointer to array of char to a pointer to pointer to char. What you need is:
const char* num1 = "hello";
const char* num2 = "class";
fastSwap (&num1,&num2);
Also, you'll need to change the declaration of fastSwap and add inner-level const to arguments
void fastSwap (const char **i, const char **d)
I'm assuming you're trying to swap the contents of the num1 and num2 arrays by just manipulating pointers, so that after calling fastswap the contents of num1 will be "class" and num2 will be "hello".
If that's the case, then this won't work for a number of reasons. Arrays are not pointers, even though array expressions are often converted to pointer types. Secondly, you cannot modify the value of an array expression.
If you want to keep num1 and num2 as arrays (as opposed to pointers to string literals) and be able to swap their contents, you'll need to something more along these lines:
void fastswap(char *i, char *d)
{
while (*i && *d)
{
char t = *i;
*d++ = *i;
*i++ = t;
}
}
which will be called as
fastswap(num1, num2);
You are passing pointers to pointers to chars. You probably just want to pass pointers to chars like this:
#include <stdio.h>
void fastSwap (char *i, char *d)
{
char t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "hello";
char num2[] = "class";
fastSwap (num1,num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
This swaps the first character of the 2 char arrays.
Related
I have been trying to solve this issue for whole day, and could not do it on my own. Searching the internet didn't help me solve it either
So, this the function prototype:
void invert(char **arr, int n);
First argument is an array of strings, and the second one is number of strings in an array.
This is my code:
#include <stdio.h>
#include <string.h>
void invert(char** arr, int n)
{
int i, j, len;
for(j=0;j<n;j++)
{
len=strlen(arr[j]);
for(i=0;i<len/2;i++)
{
char tmp = arr[j][i];
arr[j][i] = arr[j][len - i - 1];
arr[j][len - i - 1] = tmp;
}
}
}
int main()
{
int n=3, i;
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
invert(arr, n);
for(i=0;i<3;i++)
{
printf("%s ",arr[i]);
}
}
The code breaks when it reaches the line:
arr[j][i] = arr[j][len - i - 1];
and I can't figure out why.
The function receives an array of strings perfectly (tested it with some printf statements for characters of specific strings), and the char tmp succesfully recieves a correct character, but the program crashed when it reaches the line mentioned earlier. Printf statements after that line don't work.
Did I miss anything? Can someone explain what am I doing wrong? Thank you!
For starters this code snippet
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
invokes undefined behavior because the pointer arr is uninitialized and has an indeterminate value.
Moreover this approach in any case is wrong because you may not change string literals.
What you need is to declare a two-dimensional array as for example
enum { N = 11 };
//...
char arr[3][N] =
{
"John", "Doe", "Programmer"
};
In this case the function declaration will look like
void invert( char arr[][N], int n );
The enumeration must be declared before the function declaration.
Instead of the two-dimensional array you could declare an array of pointers like
char s1[] = "John";
char s2[] = "Doe";
char s3[] = "Programmer";
char * arr[3] = { s1, s2, s3 };
In this case the function declaration may be as shown in your question
void invert(char** arr, int n)
So what you need to do with minimal changes is to substitute this code snippet
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
for this code snippet
char s1[] = "John";
char s2[] = "Doe";
char s3[] = "Programmer";
char * arr[3] = { s1, s2, s3 };
To begin with, what you have here:
char **arr;
is a pointer to pointer to char.
Secondly, even if you had an array of pointers to char, like so :
char *arr[3];
And then assigning each string literal :
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
would still invoke Undefined behavior, since you are attempting to modify a string literal which is read only.
What you need is, either a 2D array of chars :
char arr[][100] = {"John", "Doe", "Programmer"};
and also change the function signature to :
void invert(char arr[][100], int n)
or you have to dynamically allocate memory and use a function like strcpy(), strdup(), memcpy() etc :
char **arr;
arr = malloc(n * sizeof(char *)); // or sizeof(*arr)
if (arr == NULL) {
fprintf(stderr, "Malloc failed to allocate memory\n");
exit(1);
}
arr[0] = strdup("John"); // good idea to also check if strdup returned null
arr[1] = strdup("Doe");
arr[2] = strdup("Programmer");
invert(arr, n);
for(i=0;i<3;i++)
{
printf("%s ",arr[i]);
}
for (i = 0; i < 3; i++) {
free(arr[i]);
}
free(arr);
So I am quite new to using pointers and wanted to know how I could do the following but for a string value.
int number(int, int *);
int main()
{
int a = 15;
int b =0;
number(a,&b);
fprintf(stdout,"Number b is %d\n",b);
return 0;
}
int number(int a, int *b) {
*b = a;
}
It seems you mean something like the following
#include <stdio.h>
char * assign( char **s1, char *s2 )
{
return *s1 = s2;
}
int main(void)
{
char *s1 = "Hello World!";
char *s2;
puts( assign( &s2, s1 ) );
return 0;
}
The program output is
Hello World!
That is to assign a value to the pointer s2 (that has the type char *) within the function you need to pass it to the function by reference as you are doing in your program with an object of the type int. Otherwise the function will deal with a copy of its argument and changes the copy will not influence on the argument.
Passing an object by reference in C means passing an object indirectly through a pointer to it.
If you have character arrays that store strings then to copy a string to a character array you can use the standard string function strcpy declared in the header <string.h>.
There is some code piece right here below:
main ()
{
char in[8];
char out[255];
iconv_t cd;
cd = iconv_open("gb18030", "utf-8");
...
char *p_in = in;
char *p_out = out;
size_t inlen = strlen(in);
size_t outlen = sizeof(out);
if (iconv(cd, &p_in, &inlen, &p_out, &outlen) < 0)
{
...
return -1
}
...
return 0;
}
I can't totally understand the 2nd and 3rd parameters of the call to iconv. Why should that be ** pointer not the * pointer as the input? Can anyone explain the cases in C when the ** pointer should be used?
Pointer to pointer is used where the passed pointer is need to be modified in the called function and that modification need to be seen in the caller function. This is required because in C arguments are passed by value. So, when an argument is passed to a function then it simply copied to the function's parameter and created a local copy having block scope. Any change to that variable will not be seen in the argument that has been passed.
void foo(in x){
x = 10;
}
int main(void){
int x = 5;
foo(x)
printf("%d\n", x); // x will be 5
}
Same happens with pointers
void bar(char *p){
p = "foobar";
}
int main(void){
char *p = NULL;
bar(p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Using a pointer to pointer will do the desired job (pointing p to the string "foobar"
void bar(char **p){
*p = "foobar";
}
int main(void){
char *p = NULL;
bar(&p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Another use is when an array of string is need to passed to a function. Like
int main(int argc, char **argv)
or
void print_fruits(char **fruits, size_t len){
for(int i = 0; i < len; i++)
printf("%s\n", fruits[i]);
}
int main(void){
char *fruits[5] = {"Apple", "Banana", "Cherry", "Kiwi", "Orange"};
print_fruits(fruits, sizeof(fruits)/sizeof(fruits[0]));
}
Note that in function call print_fruits, fruits in the argument list will decay to pointer to its first element and the expression fruits will become of type char ** after the conversion.
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);
i have to char[] in C and i wanted to swap between them, by only swaping the pointer
to the array and not one char at a time so i wrote this code:
#include <stdio.h>
void fastSwap (char **i, char **d)
{
char *t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "012345678910";
char num2[] = "abcdefghujk";
fastSwap ((char**)&num1,(char**)&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
I get this output (note the last 4 characters)
abcdefgh8910
01234567ujk
When I expect:
abcdefghujk
012345678910
NOTE: I am working on a 64 bit Linux System.
You can't modify the addresses of num1 and num2, your code should work if your test was instead:
int main ()
{
char num1[] = "012345678910";
char num2[] = "abcdefghujk";
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
printf ("%s\n",test1);
printf ("%s\n",test2);
return 0;
}
Arrays are not pointers. While they decay to pointers when you call your fastSwap(), these pointers are not the actual arrays. The fact that you need a cast should give you a hint that something is wrong.
This would work:
void fastSwap (const char **i, const char **d)
{
const char *t = *d;
*d = *i;
*i = t;
}
const char* num1 = "012345678910";
const char* num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
This will work:
int main ()
{
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
num1 is an array, and &num1 is the address of the array itself - it is not an address of a pointer.
The address of an array itself is the same location in memory as the address of the first element of the array, but it has a different type. When you cast that address to char **, you are claiming that it points at a char * value - but it does not. It points at a block of 13 chars. Your swap function then accesses that array of 13 chars as if it were a char * - since the latter is the same size as 8 chars on your platform, you end up swapping the first 8 chars of each array.
Your fastSwap only seems to work. You're invoking undefined behavior by casting '&num1' and '&num2' (which are pointers to the characters of num1 and num2) to pointers to pointers of characters (char**).
char *t = *d
t will point to whatever d's contents are pointing to, however d is pointing to the actually characters of num2 ("abcdefghujk" or 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00). This means that '*d' is actually copying the contents of 'num2' and not the pointer to num2 as you probably expected.
't' then is a bad pointer however since it is never dereferenced you avoid a crash/segment fault.
Because you're on a 64 bit machine/OS pointers are 8 bytes the value of 't' is now the first 8 bytes of 'num2' and this is what gets put into num1 after
*i = t
If you intend to swap pointers you must first create pointer variables as Mark did
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
Or change num1 and num2 into pointers (char *) rather than arrays (char[]) as sb1/Karl did
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
I've had the same situation and solved it with the following trick:
p.s. windows platform, vs-2012
void FastSwap (void **var1, void **var2) {
void *pTmp = *var1;
*var1 = *var2;
*var2 = pTmp;
}
int main () {
char *s1 = "1234567890123456";
char *s2 = "abcdefghij";
printf ("s1 before swap: \"%s\"\n", s1);
printf ("s2 before swap: \"%s\"\n", s2);
// if you change arguments in the FastSwap definition as (char **)
// then you can erase the (void **) part on the line below.
FastSwap ((void **) &s1, (void **) &s2);
printf ("s1 after swap : \"%s\"\n", s1);
printf ("s2 after swap : \"%s\"\n", s2);
return (0);
}
Change fastSwap to:
void fastSwap (char *i, char *d)
{
while ((*i) && (*d))
{
char t = *d;
*d = *i;
*i = t;
i ++;
d ++;
}
}
then call fastSwap (num1, num2);
int swap(char *a, char *b){
char *temp = (char *)malloc((strlen(a) + 1)*sizeof(char));
strcpy(temp, a);
strcpy(a, b);
strcpy(b, temp);
}
int main(){
char a[10] = "stack";
char b[10] = "overflow";
swap(a, b);
printf("%s %s", a, b);
}
While given answers already showed how to do it right (and hinted to undefined behaviour), you still might be interested in the details...
At very first, you have to character arrays. Applying the addressof operator to won't give you a pointer to pointer, but a pointer to array:
int(*ptr1)[10] = &num1;
Syntax might look strange, but that's C. The important thing here now is: You have a pointer with one level of indirection. But you cast it to a pointer with two levels of indirection (char**).
What now happens in fastSwap is:
char* t = *d;
This will copy as many bytes of *d into t as pointers on your system have size. Solely: In reality, you do not have a pointer to pointer, but a pointer to array which only has been casted. So the first sizeof(void*) bytes of the array will be copied into t. Similarly for the other assignments, explaining the results you get.
If now your arrays were shorter than the size of pointers, then memory after the arrays would have been read:
int a[] = "123";
int b[] = "456";
int c[] = "789";
fastSwap ((char**)&a, char**(&b));
printf("%s %s %s", a, b, c);
would have printed on your system (as pointer size is 8 bytes):
456 789 456
Explanation:
char *t = *d;
// copied the four bytes of b into t - AND the next four bytes (those of c!!!)
*d = *i;
// copied the eight bytes of a AND b int b AND c
// b contains "123", c "456"
*i = t;
// copied the eight bytes that were copied from b and c into a and b
// the "123" in b now got overwritten, that's why you never see them...
Be aware that you don't have guarantee for such result, it is just the most likely one. You invoked undefined behaviour, anything might happen instead, you even might switch off the sun by accident (if your compiler happened to produce the appropriate code...).