Mistake with storing strings in char pointer array - c

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.

Related

Length of string using double pointers in C

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++;
}
}

get updated value from string pointer C

tearing my hair out over C strings over here. I have a function in a project which returns a char * pointer.
I need to change an element of that string before using it. Everything I read says just use a char array with the char[] format, but this is not compatible with my project in its current state, if at all.
I have desperately been looking for someway to copy the first n characters to a second char pointer, add the updated value and then concat the remainder of the initial pointer (minus the original value that was updated) that doesnt take 40 lines of code.
Every attempt to use fgetc for this has failed to write the unsigned int to the 'updated pointer'. Do I need to sprintf the unsigned int into a char buffer or something? why does this feel so ridiculously complicated?
An example of a failed attempt at the first steps of the desired behavior:
int main() {
char *s;
s = "babado = lubidee = popop =pew";
char * s1;
s1 = malloc(10);
memset(s1,'0',9);
strcpy(s1,fgetc(s));
for (int i = 0; i<4; i++){
strcat(s1,fgetc(s));
}
printf("%s",s1);
return 0;
}
If you need to just copy a string to another pointer,
.
.
char *newptr;
//Allocate memory for new pointer
int i=0;
while(i<n) //first n characters
*(newptr+i)=*(returnedptr+i);. //returnedptr is your initial ptr
//Add new value
i++;
while( *(returnedptr+i)!='\0')
*(newptr+i)=*(returnedptr+i);
.
.

comparing string to words in an array

I got an assignment from my teacher to write a code that compares a given word to a bunch of words located in an array of strings.
If the word in the array is lexicography smaller than the word given, I need to put it inside a new array.
else, I'm moving to the next word.
for example;
given word: hello
arr=bus, alpha, world, java.
new array=bus,alpha.
I wrote a code that does that using STRCMP, but the computer throws me out when it gets to the strcpy part.
this is my code
char** LowerSTR(char* arr[], int size_arr, char* str, int* size_res)
size_res = 0;
char** newArr= (char**)calloc(size_arr, sizeof(char));
for (int i = 0; i < size_arr; i++)
{
if (strcmp(str, arr[i])==1)
{
for (int k = 0; k <size_arr;k++)
{
strcpy(newArr[k], arr[i]);
}
size_res++;
}
}
if (size_res == 0)
return NULL;
else return newArr;}
maybe I should use STRCAT instead?
please help :\
In calling strcpy with newArr[k] as an argument you're dereferencing a NULL pointer.
Recall that we allocate newArr as follows:
char** newArr= (char**)calloc(size_arr, sizeof(char));
There's actually multiple errors here. The first is that we calloc with sizeof(char) when we in fact want a region of char*s. So corrected1
we have
char** newArr= calloc(size_arr, sizeof(char*));
As we've calloc'd this piece of memory, all of it is zeroed. Thus when strcpy internally accesses newArr[k] (itself of type char*) it points to memory address 0, which is likely reversed by the OS, and in any case, not a valid address in the context of our program.
In order to resolve this, we need to allocate for each string. For instance, one might do
newArr[k] = malloc(strlen(arr[i]) + 1); // The +1 is for the \0 termination character
the line before we strcpy.
You also have a bug with size_res as you just treat it as an int instead of an int* as you need to dereference it when you want to change or read the value to which it points.
1 See here for why I've removed the cast.
You should scan newArr and print all strings inside, something like:
for (int i = 0; i < *size_res; i++) // !
{
printf("%s\n",newArr[i]);
}
(!) 'size_res' is passed to the function as a pointer to int,

Delete chars from string C

So i start learning C from a book, and one of the exercises was to create a function that will take 2 string and delete from the first string the characters in the second string.
We stile didn't learn about pointer, so i guess this is possible without them,
but when i try to run my code its crush.
The code:
#include <stdio.h>
#include <string.h>
char squis(char string[], char sub[])
{
int i, c;
char ret_string[strlen(string)];
int map[strlen(string)];
for(i=0; i<= strlen(string);i++)
map[i] = -1;
for(i=0; i<= strlen(sub);i++)
{
while(string[c]!='\0')
{
if (string[c]==sub[i])
map[c] = c;
c++;
}
c=0;
}
for(i=0; i<= strlen(string);i++)
{
if (map[i]==-1)
ret_string[c++] = string[i];
}
ret_string[c] ='\0';
return ret_string[0];
}
int main()
{
char string[] = "string";
char remove[] = "sasas";
printf("%s",squis(string,remove));
return 0;
}
I stile newbie in C, so I think the problem lay on my lack of understanding in the way that C work.
Thanks a lot for help :-)
Update: its seem the problem laying in the return in the end of the function.
The function seems to work well when when i print ret_string inside the function(except one bug that make the function ignore the first char in the sub string, but i will deal with it later), but when i try to return the array to print it in the main function its fail.
There is specific rules for returning array in C?
Here is an obvious problem:
int map[strlen(string)];
for(i=0; i<= strlen(string);i++)
map[i] = -1;
You create an array of strlen(string) characters, and then you initialize strlen(string) + 1 characters in the array. Writing out of bounds of an array leads to undefined behavior, where anything could happen.
Change the loop condition to less-than <. You should probably do it in all your loops.
You have a similar problem with ret_string, which will be the string you return. It's going to be at most strlen(string) characters, but then you need to add one character for the string terminator so the array needs to be strlen(string) + 1 long.
Then you have the problem that the squis function only return a single character but in your printf call you treat this single character as a string. This should make your compiler scream a warning at you. If you fix this by simply returning ret_string you will have another case of undefined behavior, as you then return a pointer to a local variable, which goes out of scope when the function exits, so the returned pointer is no longer valid. And if you decide to allocate ret_string on the heap, with the current call you have a memory leak as then the pointer is not saved so you can free the allocated memory.

Passing pointers to function

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.

Resources