I'm trying to get the length of a string using double pointers but for some reason its not displaying correctly. Some explanation would be greatly appreciated. I feel like i'm missing something simple here.
(I am aware this can be done with a single pointer.)
#include <stdio.h>
void find_length(char**);
int main() {
char* p = "this a message";
char** k = &p;
find_length(k);
return 0;
}
void find_length(char **k) {
while (*k != '\0') {
printf("%c", *k);
k++;
}
}
Ask yourself: When you have a pointer to T and you indirect through that pointer what do you get?
You get T
Now, ask yourself: When T is char, the pointer in question is char* i.e. pointer to char; what do you get when you indirect through that?
You get char
Now, ask yourself: When T is char*, the pointer in question is char** i.e. pointer to pointer to char; what do you get when you indirect through that?
You get char*
Now, ask yourself: What is the type of '\0'
It is char.
Does it make sense to compare char* with char? No, it does not. Now, you have a char*, so how could you get a char out of it? By indirecting through it of course.
Another problem is that you are incrementing k. Incrementing a pointer is allowed when it points to element of an array. Does k point to an array of pointers? It does not. There is only one char* being pointed at. If you want to iterate through the array pointed by *k, then you need to increment *k (or a copy of it).
k is pointer to pointer to char
*k is a pointer to char
**k is a char
So when you check for *k != '\0' you check that the pointer to cahr is different from zero, not if the char is different from the null terminator in the string.
When you do the k++ you increase the pointer to pointer to point at the next pointer to char.
Try this instead.
void find_length(char **k) {
char *kk = *k; // temp.
while (*kk != '\0') {
printf("%c", *kk);
kk++;
}
}
Related
I'm working with a method that must take a pointer to a pointer. I was wondering how I would go about getting the individual char values in this variable? For example:
void spacer(char **ptr) {
int i;
for(i = 0; **ptr[i] != ' '; i++) {
printf("Is not space");
}
}
I'm unsure how to accomplish this without getting a compilation error or segmentation fault.
Assuming ptr points valid memory and *ptr does as well then(*ptr)[i] gets you a char.
If ptr is just a double layer pointer, you can move it to make a local variable to make it simpler.
char* str = *ptr;
Then access it like a normal string later on.
str[i] == ' '
Also be careful about not leaving the allocated buffer. You need to either know the length or watch out for a null terminator.
ptr is a pointer to pointer to char,so de-referencing it once will target a pointer.de-referencing it twice will target a char.
So **ptr will get you the first character.to loop over the characters you may use the following notation:
*(*ptr + i) which is equivalent to (*ptr)[i]
you may try this:
char *temp=NULL;
int i;
temp=(char *)malloc(strlen(*ptr));
memset(temp,'\0',strlen(*ptr)+1);
for(i=0;i<strlen(*ptr)+1;i++)
{
if(temp[i] != 32)
printf("not space!\n");
}
I have a string
char *str = "hello world";
I also have a int pointer
int *ptr;
How can I use these two in a function that loops over the string and prints all the chars in it?
The header function would be something like this:
void print(const int *ptr){
while(*ptr != 0){
printf("%c", (char)*ptr);
++ptr;
}
}
Now I know that I want to use the ptr to somehow reference the char ptr. But how would I do this?
I've tried doing just
ptr = str;
And tried a whole bunch of different combinations of
ptr=*str;
ptr=&str;
And so on.
I know I can iterate over the string just doing
while(*str != 0){
printf("%c",*str)
str++;
}
And that I can also do it using index elements like str[0].
But how can I use a pointer to act as the index element for the char string?
Why do you need to use int * to access char *? It is not correct and shouldn't be done so.
The main problem with it is that each time you increase you pointer ptr by 1 it is incremented by sizeof(int) bytes (which is platform dependent and varies between 2 and 4). While each character in the string is of size 1 byte.
Also when you write *ptr you actually access sizeof(int) bytes which may result in segmentation fault if ptr points to the end part of the string.
If you have no option to change the function signature do it like this:
void print(const int *ptr){
const char* char_ptr = (const char*)ptr;
while(*char_ptr != 0){
printf("%c", *char_ptr);
++char_ptr;
}
}
If all you need is just to print the string to which (for some reason) const int* ptr is pointing then you can do something like that:
void print(const int *ptr)
{
printf("%s", ptr);
}
printf won't check the type of the pointer, it will assume that the pointer is pointing to a buffer of chars and will print the whole buffer until it reachs '\0'.
im trying to copy a const char array to some place in the memory and point to it .
lets say im defining this var under the main prog :
char *p = NULL;
and sending it to a function with a string :
myFunc(&p, "Hello");
now i want that at the end of this function the pointer will point to the letter H but if i puts() it, it will print Hello .
here is what i tried to do :
void myFunc(char** ptr , const char strng[] ) {
*ptr=(char *) malloc(sizeof(strng));
char * tmp=*ptr;
int i=0;
while (1) {
*ptr[i]=strng[i];
if (strng[i]=='\0') break;
i++;
}
*ptr=tmp;
}
i know its a rubbish now, but i would like to understand how to do it right, my idea was to allocate the needed memory, copy a char and move forward with the pointer, etc..
also i tried to make the ptr argument byreferenec (like &ptr) but with no success due to a problem with the lvalue and rvalue .
the only thing is changeable for me is the function, and i would like not to use strings, but chars as this is and exercise .
thanks for any help in advance.
Just replace all the char* with std::string. Do that until you have a very specific reason to not use existing utilities, which is something you don't have as a beginner. None of the code above requires malloc() or raw pointers.
Some more notes:
const char strng[] as parameter is the same as const char* strng. The array syntax doesn't make it an array, it remains a pointer. I don't use this syntax in order to avoid this confusion.
Use static_cast or one of the other C++ casts not the C-style like (char*)malloc(..). The reason is that they are safer.
Check the return value of malloc(), it can return null. Also, you must call free() eventually, otherwise your application leaks memory.
Finally, the pointer does point to the 'H', which is just the first element of the string. Output *p instead of p to see this.
You code work as desired except
*ptr[i]=strng[i];
should be
(*ptr)[i]=strng[i];
Without the parens, it acts like `*(ptr[i])=strng[i];
2) Also
malloc(sizeof(strng));
s/b
malloc(strlen(strng)+1);
You may want to look at strdup(strng).
[edit per OP's request]
difference between *(ptr[i]) and (*ptr)[i]
// OP desired function
(*ptr)[i] = 'x';
// Dereference ptr, getting the address of a char *array.
// Assign 'x' to the i'th element of that char * array.
// OP post with the undesired function
*(ptr[i]) = 'x';
// This is like
char *q = ptr[i];
*q = 'x';
// This make sense _if_ ptr were an array of char *.
// Get the i'th char * from ptr and assign to q.
// Assign 'x' to to the location pointer to by q.
This is all the code needed...
nothing more...
void myFunc(char **pp, char * str){
*pp = str;
}
The only issue here is that "Hello" resides in read only section because it is a constant string... so you can't change "Hello" to something else...
I know this question might sound quite silly, but I somehow found myself stuck and need help. I have a char* variable char* address="/a/asdasd/c/sdfsdf/adsd"; and I declared an array of char pointer char* store[5]; . I'm trying to divide the content in the variable address by tracing the slash(/) and trying to store each part in the char pointer variable store by doing the following
char* store[5];
char* address="/a/asdasd/c/sdfsdf/adsd";
int k=0;
int j=0;
char* b=NULL;
for(int i=0;i<5;i++)
{
if(b==0)
{
b=strchr(address,'/');
}
else
{
b=strchr(b,'/');
}
j=b-address;
strncpy(store[i],address+k,j-k);
k=j;
}
But I see that in the code strncpy(store[i],address+k,j-k) there's an error. The compiler doesn't seem to understand that store[i] is a char pointer, it rather thinks it is a char. Could you see how I can solve the problem?
Thanks for all the help. I've solved it. Solution code is as below:
char* address="/a/asdasd/c/sdfsdf/adsd/asfsd";
char store[5][100];
char* b=NULL;
int k=0;
int j=0;
for(int i=0;i<5;i++)
{
if(b==0)
{
b=strchr(address+1,'/');
}
else
{
b=strchr(b+1,'/');
}
j=strlen(address)-strlen(b);
strncpy(store[i],address+k+1,j-k-1);
store[i][j-k-1]='\0';
printf("%s\n",store[i],j-k);
k=j;
}
char *store[5]
This is just an array of char pointers. To store strings in each element of this array, you need malloc memory and assign it to the respective pointer.
For Ex, you can change your code to
store[i] = malloc ((j-k)+ 1); // +1 is for the null terminator. Pls check return value of malloc also.
strncpy(store[i],address+k,j-k);
If you want to copy a pointer, you shouldn't be calling strncpy(), since that copies characters.
You want:
store[i] = address + (j - k);
assuming address + (j - k) is the desired starting point for the part.
If you don't want to have a copy of the string tokens, if you like only to retain the pointers, then just store the address in store[i] as #unwind pointed out. Or else, you could explore strtok () also. only think is that you need to have separate array to keep each length of the string according to your code. Hope this helps.
I have a doubt in my program
#include<stdio.h>
int myFunc(char **);
main()
{
char *a[2]={"Do","While"};
myFunc(a);
}
int myFunc(char **P)
{
/* Here I want to print the strings passed but I'm unable to
print the strings I just tried the below statement which
printed just the first letter which is 'D'*/
printf("%c",**P);
}
when i tried
printf("%s",**P);
I am getting run time error. so can anyone please help me out?
Thanks
Madhu
Put size as parameter to allow the function to know how many strings you have in your array. Then, you should iterate the array and print each one.
int myFunc( char** p, int size)
{
for( int i = 0; i < size; ++i)
{
printf("%s", p[i]);
}
}
Later edit (as requested :-) )
int main( int, char**)
{
char *a[2]={"Do","While"};
myFunc( a, 2); // Could be myFunc( a, sizeof(a)/sizeof(char*));
// ...
return 0;
}
Too many stars - try
printf("%s",*P);
And you need %s format specifier - %c is just for single character.
If you want to print all strings, you need to pass number of strings in array and then print these strings from the loop.
Check the code suggested by Cătălin Pitiș. To pass the number of strings, you call function like this:
myFunc(a, sizeof(a)/sizeof(a[0]));
for( int i = 0; i < 2; i++ ) {
char* string = P[i];
printf( "%s", string );
}
And you shoud use some way of passing size of array into the function - either pass it as an int parameter,
int myFunc(char **P, int size)
{
for( int i = 0; i < size; i++ ) {
//whatever here
}
}
or always append a zero value to the array and only loop until you find that zero value.
char* array[] = { "String1", "String2", 0 };
Otherwise you will have hard to maintain code.
I like objective-c style nil (0) terminated arrays:
void myFunc(char **P)
{
while (*P) // loop to iterate over all strings until 0
printf("%s\n",*P++); // print and move to next element in array
}
int main()
{
char *a[]={"Do","While",0}; // added 0 to null terminate array,
myFunc(a); // kind of like string
}
Output:
Do
While
First, the good news: the type of a is equivalent to char **, so you are passing a valid parameter to myFunc().
The first problem is that %c is a format specifier that means print a single character. Since **P is an expression that evaluates to a single character, your first version does exactly what you told it to do. That isn't what you want.
The second version is close to syntactically correct. It should read printf("%s", *P), where *P is an expression that evaluates to a pointer to a nul-terminated ASCII string. In this case, it evaluates to "Do". This version won't print both strings.
Although it is true that the name of an array is the same as a pointer to its first element, that is a kind of "lie to students". Passing an array to a function does not and cannot convey the length of the array. To do that, you need either a second argument containing the length, or a convention like the nul-terminator on a string to indicate the end of the array. With that change, you can modify myFunc() to use a loop over the elements passed and print each one.
The problem in your code is that you want to print a string (char*) but you're giving it a char. Remember that P is an array of char*. When you de-reference it once, you get a char*; when you do it a second time, you just get the char at the beginning of the char*.
When you try to use the char value with the %s specifier, it treats the value as a pointer, and tries to dereference that value. Hence, it will try to print the "string" at the memory location X, where X is the value of the char (i.e. a value from 0 to 255). This gives you an access violation/segmentation fault (the error you see at runtime).
The best workarounds for this, as noted by Cătălin Pitiș and RBerteig, are to either:
pass another parameter to specify the length of the array
add an additional null at the end of the array.
if you don't want to keep and pass around array size::
int myFunc(char **);
main()
{
char *a[2]={"Do","While", NULL};
myFunc(a);
}
int myFunc(char **P)
{
if( !P )
return 0;
while(*P != NULL)
{
printf("%s",*P);
P++;
}
}
Wrong Answer: I think you may have to dereference P when you print it, although I could be wrong.
EDIT: I'm tired, it's 3 am here but I don't feel like sleeping so I'm here trying to answer questions. After reading the criticism, I reread the question and noticed that he does dereference P, but as is stated in another answer, it's dereferenced too much. When one wants to print a char string, one wants to pass a pointer as the char string is really an array.
Another EDIT: I would also like to point out that the person who asked the question made an edit after I answered and that when I first answered it didn't read "printf("%s",**P);" it read "printf("%s", P);" and the last part was bold.