I was hoping someone could help me figure out why I am getting a segmentation fault on my code below. My user has inputted a line of text, which is passed to the parse function. The parse function should initialize a 2D array (I would ideally like to dynamically allocate the array, but for now I am making it an array of size [25][25]).
Starting at the beginning of input strtok() is called. If strtok() sees a pipe symbol, it should increase the count of pipes and go to the next row of the matrix. For example, if the user inputted foo bar | foo1 | foo2 bar1 foo2, the 2D array would look like:
array[][] = { foo, barr;
foo1;
foo2, bar1, foo2; }
Eventually I would like to pass this array to another function. However, If I actually input the above into my program, this is the result:
/home/ad/Documents> foo bar | foo1 | foo2 bar1 foo2
test1
Segmentation fault
ad#ad-laptop:~/Documents$
Thus, given where I put these debug statements, the problem is with saving the tokens? This is the first time I have worked with a 2D array so I am sure it is something wrong with my pointer logic. What can I do to fix this segmentation fault? Thanks for your time.
Code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int MAX_PATH_LENGTH = 1024; //Maximum path length to display.
int BUF_LENGTH = 1024; // Length of buffer to store user input
char * delims = "|"; // Delimiters for tokenizing user input.
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
void execute(char *args, int numPipes, int numArgs){
int i;
int j;
for(i = 0; i <= numArgs; i++){
for(j = 0; j < 25; j++){
printf("args[%d][%d]", i, j);
}
}
}
void parse(char *input) {
char argArray[25][25];
int numPipes = 0;
int i = 0;
int j = 0;
char *tokenPtr = NULL;
tokenPtr = strtok(input, delims);
while(tokenPtr != NULL) {
if(strcmp(tokenPtr, "|") == 0){ //is token a pipe?
numPipes++;
i++;
j = 0;
}
else {
argArray[i][j++] = *tokenPtr;
printf("test1\n");
tokenPtr = strtok(input, NULL);
printf("test2\n");
}
}
execute(*argArray, numPipes, i);
}
int main () {
char path[MAX_PATH_LENGTH];
char buf[BUF_LENGTH];
char* strArray[BUF_LENGTH];
while(1) {
getcwd(path, MAX_PATH_LENGTH);
printf("%s> ", path);
fflush(stdout);
fgets(buf, BUF_LENGTH, stdin);
parse(buf);
bzero(strArray, sizeof(strArray)); // clears array
}
}
Only the first call to strtok should receive the input. Subsequent calls (while parsing the same string) should have NULL as their first argument.
You misread the manpage for strtok:
In each subsequent call that should parse the same string, str should be NULL.
And you did: tokenPtr = strtok(input, NULL);
Related
When I iterate through a string in a void function like this it doesn't give me any problem and iterates through the string I input.
#include <stdio.h>
#include <string.h>
void iter_string (void){
char source[30];
scanf(" %[^\n]s",source );;
int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
for (int i = 0; i < length; i++)
{
printf("%c\n", source[i]);
}
//return 0;
}
int main(void)
{
iter_string();
return 0;
}
However, problems arise when I modify the function to return the input value and store it in a value in the main function. It gives me an error called segmentation fault:11. Why is this?
const char* iter_string (void){
char source[30];
scanf(" %[^\n]s",source );;
int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
for (int i = 0; i < length; i++)
{
printf("%c\n", source[i]);
}
return *source;
}
int main(void)
{
char author[30];
strcpy(author,iter_string());
printf("%s\n",author );
return 0;
}
Because you are returning a reference to a memory that no longer exists once the function finishes executing.
You have to declare it dinamically if you want to return that pointer:
char *source = malloc(30);
// Do your processing here...
return source; // No asterisk here
Then in main, to do a proper cleaning on the memory allocated inside the function you should free the stuff you malloc'ed:
char * temp = iter_string();
strcpy(author, temp);
free(temp);
Other alternativa would be to pass author as parameter and alter it inside.
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 have a function which print lot of printf statements, number of lines as output is not fixed. I need to get all the lines which are getting printed in myFun to the main function and used them for some other purpose. Can someone please guide how to do that ?
#include<stdio.h>
int myFun(char* name){
printf("myFun: this is important line too\n");
printf("myFun: my name is %s\n",name);
printf("myFun: this is a important line needed in main, genrated from some function called inside myFun\n");
}
int main(){
printf("this is main and now calling myFun\n");
myFun("monk");
//how can I get all the output of all three printf statements done inside myFun to the main function ?
return 0;
}
You could try saving the strings into an array, and returning the whole array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **Func(char *name)
{
int numOfOutputs = 3;
numOfOutputs++; //Append an extra null byte to the end so we know when it ends
int maximumStringSize = 100;
char **final = (char **)malloc(numOfOutputs * sizeof(char *));
for (int i = 0; i < numOfOutputs; i++)
final[i] = (char *)malloc(maximumStringSize * sizeof(char));
strcpy(final[0], "myFun: this is important line too\n");
sprintf(final[1], "myFun: my name is %s\n", name);
strcpy(final[2], "myFun: this is a important line needed in main, genrated from some function called inside myFun\n");
//Final member assigned as NULL to indicate end
final[3] = NULL;
return final;
}
int main()
{
printf("this is main and now calling myFun\n");
char **result = Func("monk");
//Print result, check for ending member with the nullbyte we added
for(int i = 0 ; result[i] != NULL; i++)
printf("For i = %d, string is -> %s", i, result[i]);
//Don't forget to free with something like this:
for(int i = 0 ; result[i] != NULL; i++)
free(result[i]);
free(result);
return 0;
}
I am completely newbie in C.
I am trying to do simple C function that will split string (char array).
The following code doesn't work properly because I don't know how to terminate char array in the array. There are to char pointers passed in function. One containing original constant char array to be split and other pointer is multidimensional array that will store each split part in separate char array.
Doing the function I encountered obviously lots of hustle, mainly due to my lack of C experience.
I think what I cannot achieve in this function is terminating individual array with '\0'.
Here is the code:
void splitNameCode(char *code, char *output);
void splitNameCode(char *code, char *output){
int OS = 0; //output string number
int loop;
size_t s = 1;
for (loop = 0; code[loop]; loop++){
if (code[loop] == ':'){
output[OS] = '\0'; // I want to terminate each array in the array
OS ++;
}else {
if (!output[OS]) {
strncpy(&output[OS], &code[loop], s);
}else {
strncat(&output[OS], &code[loop], s);
}
}
}
}
int main (int argc, const char * argv[]) {
char output[3][15];
char str[] = "andy:james:john:amy";
splitNameCode(str, *output);
for (int loop = 0; loop<4; loop++) {
printf("%s\n", output[loop]);
}
return 0;
}
Here is a working program for you. Let me know if you need any explanation.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void splitNameCode(char *code, char **output) {
int i = 0;
char* token = strtok(code, ":");
while (token != NULL) {
output[i++] = token;
token = strtok(NULL, ":");
}
}
int main (int argc, const char *argv[]) {
char* output[4];
char input[] = "andy:james:john:amy";
splitNameCode(input, output);
for (int i = 0; i < 4; i++) {
printf("%s\n", output[i]);
}
return 0;
}
If I understand your intent correctly, you are trying to take a string like andy:james:john:amy and arrive at andy\0james\0john\0amy. If this is the case, then your code can be simplified significantly:
void splitNameCode(char *code, char *output){
int loop;
strncpy(code, output, strlen(code));
for (loop = 0; output[loop]; loop++){
if (output[loop] == ':'){
output[loop] = '\0'; // I want to terminate each array in the array
}
}
}
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.