I am trying to take input from a user and I don't the exact length of input so therefore I am using malloc and I am splitting char by space between them and just need to print an array but I am getting warning i.e assignment makes integer from pointer without a cast on the following line:
array[i++] = p;
and my whole program is as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
char buf[] ="abc qwe ccd";
int i;
char *p;
char *array=malloc(sizeof(char));
i = 0;
p = strtok (buf," ");
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, " ");
}
for (i=0;i<3; ++i)
printf("%s\n", array[i]);
return 0;
}
Can anyone please tell me what is wrong with my code.
Thank you.
The following assignment is not right.
array[i++] = p;
array[i++] evaluates to type char. p is of type char*.
That's what the compiler is complaining about.
Judging by the way you are using array, it needs to be of type char**.
char **array = malloc(sizeof(*array)*20); // Make it large enough for your needs.
I guess you wanted to create array of pointers to char instead of array of char.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
char buf[] ="abc qwe ccd";
int i;
char *p;
/* change type of array from char* to char** */
char **array=malloc(sizeof(char*) * sizeof(buf)); /* allocate enough memory */
i = 0;
p = strtok (buf," ");
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, " ");
}
for (i=0;i<3; ++i)
printf("%s\n", array[i]);
free(array); /* it is good to free whatever you allocated */
return 0;
}
Related
Jus started learning about pointers and im stuck with this program outputting a segmentation fault.
Its supposed to copy the first 10 Characters of a string to the location pointed by the double pointer
using gdb ive found that **pt=*s; produces the seg fault
#include <stdio.h>
#include <stdlib.h>
void str1(char *s, char **pt);
void str1(char *s, char **pt){
for(int i=0;i<10;i++){
**pt=*s;
pt++;
s++;
}
}
int main (void) {
char str[30] = "223This is test";
char *ptr;
str1(str, &ptr);
printf("%s", ptr);
return 0;
}
First of all ptr is not initialized, you can't really use it until you reserve space for it or store a valid memory address in it, i.e. make it point to some valid variable.
char *ptr = malloc(11);
Then you need to increment it properly in the function:
(*pt)++;
Once the copy is completed you need to null terminate the char array so it can be treatead as a string, aka a null terminated char array.
**pt = '\0';
Now as ptr was passed as a pointer to pointer, the increment is known by the caller, main in this case, so when you try to print it, it prints nothing because it's pointing to the end of the char array, we need to bring it back to the beggining.
*pt -= 10;
Corrected code with comments taking yours as base:
Live demo
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
void str1(char *s, char **pt) {
for (int i = 0; i < SIZE; i++) {
**pt = *s;
(*pt)++; //properly increment pt
s++;
}
**pt = '\0'; //null terminate copied string
//since ptr was passed as **, the increment is known by the caller
//now ptr will be pointing to the end of the string
//we have to bring it back to the beginning
*pt -= SIZE;
}
int main(void) {
char str[] = "223This is test";
char *ptr = malloc(SIZE + 1); //space for 10 character + null-terminator
//check for allocation errors
if(ptr == NULL){
perror("malloc");
return EXIT_FAILURE;
}
str1(str, &ptr);
printf("%s", ptr);
free(ptr);
return EXIT_SUCCESS;
}
You probably want this:
#include <stdio.h>
#include <stdlib.h>
void str1(char* s, char** pt) {
char *p = malloc(100); // allocate memory for destination
*pt = p; // store it for the caller
for (int i = 0; i < 10; i++) {
*p = *s;
p++;
s++;
}
*p = 0; // put string terminator, otherwise printf won't work correctly
}
int main(void) {
char str[30] = "223This is test";
char *ptr; // for now p points nowhere
str1(str, &ptr); // now p points to the memory allocated in str1
printf("%s", ptr);
free(ptr); // free memory for completeness
return 0;
}
I need help figuring out why the following code won't work. I want to split the buf string into tokens, and save it into the struct char *array field. And print out its contents.
#include <stdio.h>
#include <string.h>
struct parser{
char *array[10];
};
void stages(char buf[]){
struct parser t;
int i = 0;
char *p = strtok (buf, "|");
while (p != NULL)
{
t.array[i++] = p;
p = strtok (NULL, "|");
}
}
int main() {
struct parser t;
char buf[] ="ls < one | more | sort";
int i = 0;
stages(buf);
for (i = 0; i < 3; i++)
printf("%s\n", t.array[i]);
return 0;
}
The variable t in the function stages is a local variable.
This is different than the variable t in main.
To print t in main you need to pass a pointer to struct parser to the function and remove the local variable t
#include <stdio.h>
#include <string.h>
struct parser{
char *array[10];
};
void stages(char buf[],struct parser *ptr){
int i = 0;
char *p = strtok (buf, "|");
while (p != NULL)
{
ptr->array[i++] = p;
p = strtok (NULL, "|");
}
}
int main() {
struct parser t;
char buf[] ="ls < one | more | sort";
int i = 0;
stages(buf,&t);
for (i = 0; i < 3; i++)
printf("%s\n", t.array[i]);
return 0;
}
memory allocated for struct parser t, in function named void stages(char buf[]);
will be in stack and as soon as the function returns that memory will be deleted
by compiler. So you can't print values of struct parser t in main.
If you want to print the value either you return that structure from the function
or you can pass the pointer from main to that function.
I want to create a function in C, so that I can pass the function a string, and a delimiter, and it will return to me an array with the parts of the string split up based on the delimiter. Commonly used to separate a sentence into words.
e.g.: "hello world foo" -> ["hello", "world", "foo"]
However, I'm new to C and a lot of the pointer things are confusing me. I got an answer mostly from this question, but it does it inline, so when I try to separate it into a function the logistics of the pointers are confusing me:
This is what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void split_string(char string[], char *delimiter, char ***result) {
char *p = strtok(string, delimiter);
int i, num_spaces = 0;
while (p != NULL) {
num_spaces++;
&result = realloc(&result, sizeof(char *) * num_spaces);
if (&result == NULL) {
printf("Memory reallocation failed.");
exit(-1);
}
&result[num_spaces - 1] = p;
p = strtok(NULL, " ");
}
// Add the null pointer to the end of our array
&result = realloc(split_array, sizeof(char *) * num_spaces + 1);
&result[num_spaces] = 0;
for (i = 0; i < num_spaces; i++) {
printf("%s\n", &result[i]);
}
free(&result);
}
int main(int argc, char *argv[]) {
char str[] = "hello world 1 foo";
char **split_array = NULL;
split_string(str, " ", &split_array);
return 0;
}
The gist of it being that I have a function that accepts a string, accepts a delimiter and accepts a pointer to where to save the result. Then it constructs the result. The variable for the result starts out as NULL and without memory, but I gradually reallocate memory for it as needed.
But I'm really confused as to the pointers, like I said. I know my result is of type char ** as a string it of type char * and there are many of them so you need pointers to each, but then I'm supposed to pass the location of that char ** to the new function, right, so it becomes a char ***? When I try to access it with & though it doesn't seem to like it.
I feel like I'm missing something fundamental here, I'd really appreciate insight into what is going wrong with the code.
You confusing dereferencing with addressing (which is the complete opposite). Btw, I couldn't find split_array anywhere in the function, as it was down in main. Even if you had the dereferencing and addressing correct, this would still have other issues.
I'm fairly sure you're trying to do this:
#include <stdio.h>
#include <stdlib.h>
void split_string(char string[], const char *delimiter, char ***result)
{
char *p = strtok(string, delimiter);
void *tmp = NULL;
int count=0;
*result = NULL;
while (p != NULL)
{
tmp = realloc(*result, (count+1)*sizeof **result);
if (tmp)
{
*result = tmp;
(*result)[count++] = p;
}
else
{ // failed to expand
perror("Failed to expand result array");
exit(EXIT_FAILURE);
}
p = strtok(NULL, delimiter);
}
// add null pointer
tmp = realloc(*result, (count+1)*sizeof(**result));
if (tmp)
{
*result = tmp;
(*result)[count] = NULL;
}
else
{
perror("Failed to expand result array");
exit(EXIT_FAILURE);
}
}
int main()
{
char str[] = "hello world 1 foo", **toks = NULL;
char **it;
split_string(str, " ", &toks);
for (it = toks; *it; ++it)
printf("%s\n", *it);
free(toks);
}
Output
hello
world
1
foo
Honestly this would be cleaner if the function result were utilized rather than an in/out parameter, but you choice the latter, so there you go.
Best of luck.
Execute main, it will ask for input.
Store input in the argbuf.
Then, use strwrd to split argbuf into tokens
Yet, it says "Error: incompatible types in assignment of char * to char[200]"
I cannot figure out why..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char argbuf[200];//used to store input
char *strwrd(char *s, char *buf, size_t len, char *delim){
s += strcspn(s, delim);
int n = strcspn(s, delim); /* count the span (spn) of bytes in */
if (len-1 < n) /* the complement (c) of *delim */
n = len-1;
memcpy(buf, s, n);
buf[n] = 0;
s += n;
return (*s == 0) ? NULL : s;
}
int main(){
fgets(argbuf, sizeof(argbuf), stdin);
char token[10][20];
int index;
for (index = 0; index < 10; index++) {
argbuf = strwrd(argbuf, token[index], sizeof(token[index]), " \t");
if (argbuf == NULL)
break;
}
return 1;
}
strwrd returns a char*, so you can't store this value in a char[200] variable. Use char* type instead.
char * and char[x] are different types, see here
Here's another good resource
In your code char argbuf[200]; is a statically allocated array, so you can not assign a pointer to it. Why pass the global back and forth anyway? If you're going to use argbuf as a global variable then just modify it inside strwrd directly if your each for '\t' comes back with something valid.
Can anyone explain why I am getting segmentation fault in the following example?
#include <stdio.h>
#include <string.h>
int main(void) {
char *hello = "Hello World, Let me live.";
char *tokens[50];
strtok_r(hello, " ,", tokens);
int i = 0;
while(i < 5) {
printf("%s\n", tokens[i++]);
}
}
Try this:
#include <stdio.h>
#include <string.h>
int main(void) {
char hello[] = "Hello World, Let me live."; // make this a char array not a pointer to literal.
char *rest; // to point to the rest of the string after token extraction.
char *token; // to point to the actual token returned.
char *ptr = hello; // make q point to start of hello.
// loop till strtok_r returns NULL.
while(token = strtok_r(ptr, " ,", &rest)) {
printf("%s\n", token); // print the token returned.
ptr = rest; // rest contains the left over part..assign it to ptr...and start tokenizing again.
}
}
/*
Output:
Hello
World
Let
me
live.
*/
You need to call strtok_r in a loop. The first time you give it the string to be tokenized, then you give it NULL as the first parameter.
strtok_r takes a char ** as the third parameter. tokens is an array of 50 char * values. When you pass tokens to strtok_r(), what gets passed is a char ** value that points to the first element of that array. This is okay, but you are wasting 49 of the values that are not used at all. You should have char *last; and use &last as the third parameter to strtok_r().
strtok_r() modifies its first argument, so you can't pass it something that can't be modified. String literals in C are read-only, so you need something that can be modified: char hello[] = "Hello World, Let me live."; for example.
A bunch of things wrong:
hello points to a string literal, which must be treated as immutable. (It could live in read-only memory.) Since strtok_r mutates its argument string, you can't use hello with it.
You call strtok_r only once and don't initialize your tokens array to point to anything.
Try this:
#include <stdio.h>
#include <string.h>
int main(void) {
char hello[] = "Hello World, Let me live.";
char *p = hello;
char *tokens[50];
int i = 0;
while (i < 50) {
tokens[i] = strtok_r(p, " ,", &p);
if (tokens[i] == NULL) {
break;
}
i++;
}
i = 0;
while (i < 5) {
printf("%s\n", tokens[i++]);
}
return 0;
}
strtok_r tries to write null characters into hello (which is illegal because it is a const string)
You have understood the usage of strtok_r incorrectly. Please check this example and documentation
And try & see this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char hello[] = "Hello World, let me live.";
char *tmp;
char *token = NULL;
for(token = strtok_r(hello, ", ", &tmp);
token != NULL;
token = strtok_r(NULL, ", ", &tmp))
{
printf("%s\n", token);
}
return 0;
}
I think it might be the char *tokens[50]; because you are declaring it a pointer when it is already a pointer. An array is already a pointer upon declaration. You mean to say char tokens[50];. That should do the trick.