So I wrote the following code in linux(Ubuntu) using the emacs text editor it basically supposed to split the string on the delimeter passed in . When I ran it it segfaulted I ran it though GDB and it gives me an error at strcpy(which I don't invoke) but is probably done implicitly in sprintf. I didn't think I was doing anything wrong so I booted into windows and ran it through visual studio and it works fine I am new to writing C in Linux and know the problem is in the While loop where i call sprintf() (which is odd because the call outside of the loop writes without causing an error) to write the token to the array. If anyone can tell me where I am going wrong I would greatly appreciate it. Here is the code
/* split()
Description:
- takes a string and splits it into substrings "on" the
<delimeter>*/
void split(char *string, char *delimiter)
{
int i;
int count = 0;
char *token;
//large temporary buffer to over compensate for the fact that we have
//no idea how many arguments will be passed with a command
char *bigBuffer[25];
for(i = 0; i < 25; i++)
{
bigBuffer[i] = (char*)malloc(sizeof(char) * 50);
}
//get the first token and add it to <tokens>
token = strtok(string, delimiter);
sprintf(bigBuffer[0], "%s", token);
//while we have not encountered the end of the string keep
//splitting on the delimeter and adding to <bigBuffer>
while(token != NULL)
{
token = strtok(NULL, delimiter);
sprintf(bigBuffer[++count], "%s", token);
}
//for(i = 0; i < count; i++)
//printf("i = %d : %s\n", i, bigBuffer[i]);
for(i = 0; i< 25; i++)
{
free(bigBuffer[i]);
}
} //end split()
You aren't checking for NULL from the return of strtok on the last iteration of the loop ... so strtok can return NULL, yet you still pass the NULL value in the token pointer to sprintf.
Change your while-loop to the following:
while(token = strtok(NULL, delimiter)) sprintf(bigBuffer[++count], "%s", token);
That way you can never pass a NULL pointer to strtok because the while-loop NULL-pointer check will enforce that token always has a valid value when sprintf is called with it as an argument.
You should ask gdb for a full traceback of where your program crashed. The fact that you don't know precisely where it crashed means you didn't ask it for a full traceback, which is important.
Related
So im getting a file with strings, i want to tokenize each string whenever i come to a whitespace/newline. i am able to get the tokens seperated into delimiter strings, but im not able to copy them into an array.
int lexer(FILE* file){
char line[50];
char* delim;
int i = 0;
int* intptr = &i;
while(fgets(line,sizeof(line),file)){
printf("%s\n", line);
if(is_empty(line) == 1)
continue;
delim = strtok(line," ");
if(delim == NULL)
printf("%s\n", "ERROR");
while(delim != NULL){
if(delim[0] == '\n'){
//rintf("%s\n", "olala");
break;
}
tokenArray[*intptr] = delim;
printf("Token IN array: %s\n", tokenArray[*intptr]);
*intptr = *intptr + 1;
delim = strtok(NULL, " ");
}
if i run this i get the output :
Token IN array: 012
Token IN array: 23ddd
Token IN array: vs32
Token IN array: ,344
Token IN array: 0sdf
which is correct according to my textfile, but when i try to reprint the array at a later time in the same function and out
*intptr = *intptr + 1;
delim = strtok(NULL, " ");
}
}
printf("%s\n", tokenArray[3]);
fclose(file);
return 0;
i dont get an output, i tried writing all the contents of the array to a txt file, i got gibberish. i dont know what to do plz help
First, your pointer on i is useless. Why not using i directly?
I'll assume that from now on.
Then, the real problem: you have to allocate and copy the strings that strtok returns each time because strtok does not allocate the tokens for you, it justs points to the last one. The references are all the same, so you get last empty token
Something like this would help:
tokenArray[*intptr] = strdup(delim);
(instead of tokenArray[*intptr] = delim;) note that I have replaced the index by i. Just to i++ afterwards.
BTW I wouldn't recommend using strtok for other purposes that quick hacks. This function has a memory, so if you call several functions using it in different parts of your program, it can conflict (I made that mistake a long time ago). Check manual for strtok_r in that case (r for reentrant)
tokenArray[*intptr] = delim;
In this line, delim is a pointer to a char array of which the content is ever changing in the for loop. So in your case, the content which delim point to should be copied as content of tokenArray[*intptr], that is:
tokenArray[*intptr] = strdup(delim);
I'm still learning about writing simple shell.
I want this shell to allow blank lines and comments.
I did some coding and I encountered a problem that if I directly just input enter (blank line), it directly seg.fault core dumped.
I don't know exactly where's the mistake, because I print everything and all seems fine. The only thing that I suspicious in these line
if (args[0] == NULL || !(strncmp(args[0],"#",1))) {
exitstat = 0;
}
I got the args from basic split command function. The weird thing is the comments works just fine.
Below is my functions for read what user input and split them (tokenize if I'm not mistaken). They are really basic because I'm learn those functions from internet tutorial.
char *commandInput() {
char *command = NULL;
ssize_t bufsize = 0;
getline(&command, &bufsize, stdin);
return command;
}
char **splitLine(char *command) {
int bufsize = 64,
int position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token;
token = strtok(command, DELIMITER);
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= bufsize) {
bufsize += 64;
tokens = realloc(tokens, bufsize * sizeof(char*));
}
token = strtok(NULL, DELIMITER);
}
tokens[position] = NULL;
return tokens;
}
Anybody could help me recognize what makes it seg.fault if I enter blank line? Thank you.
EDIT
I used debugger (finally succeed to use it after several trial) and it turns out that the error is located at the line that I didn't expect to cause any problem (see ---UPDATE----).
They way I handle my commandInput function is in main() function, I write
int main () {
......
char * command = NULL
char **args;
command = commandInput();
args= splitLine(command);
------------------ UPDATE!(CAUSING ERROR IF STATEMENT) ---------------
background = 0
numbarguments = 0
// Condition to check whether there is a start program running in backgrond
if (!(strncmp(args[numbarguments - 1], "&",1))) {
background = 1;
args[numbarguments - 1] = NULL;
}
----------------------------------------------
if (args[0] == NULL || !(strncmp(args[0],"#",1))) {
exitstat = 0;
}
....... //(comparing the arguments other than null)
}
So any advice regarding that if condition that causing me seg.fault. Thank you.
The parameter you pass to splitline is modified. strtok has the effect of modifying the string it gets by inserting \0's and returning a pointer to substrings. What strtok returns is not something you can directly store for later use, instead you need to make a copy of it.
token = strtok(command, DELIMITER);
while (token != NULL)
{
tokens[position] = malloc(strlen(token)+1);
strcpy(tokesn[position],token);
...
so in other words it is not enough to allocate the array of pointers to strings, you also need to allocate space to hold strings that you tokenize with strtok.
The code
if (!(strncmp(args[numbarguments - 1], "&",1))) {
background = 1;
args[numbarguments - 1] = NULL;
}
looks wrong, numberarguments is initially 0 so you are comparing args[-1] with "&" then later you assign args[-1] = NULL which probably causes the seg fault.
C Programming:
I'm attempting to get the length of each word inside a string, but having massive troubles and get a segmentation fault no matter what method I use.
I was originally trying to use just "strlen(pstr)" but that caused segmentation fault.
This is my latest attempt which still causes segmentation fault:
void format_text(char* text)
{
char* pstr;
char copied[1000];
int loop;
int strCnt = 0;
int temp;
int strSize[100];
int strNo[100];
pstr = strtok(text, " ");
while (pstr != NULL)
{
pstr = strtok(NULL, " ");
strcpy(copied, pstr);
strSize[strCnt] = strlen(copied);
strCnt++;
}
printf("the number of strings is: %d\n", strCnt);
for (loop = 0; loop < strCnt; loop++)
{
printf("The length of string %d is %d\n", loop + 1, strSize[loop]);
}
}
How can I get and print the length of each word(token)?
You don't need the copied string to get the lenght, you can simply use pstr. And, you need to put the strtok() after the strlen(), otherwise you'll miss the length of the first word.
Here's what should work:
pstr = strtok(text, " ");
while (pstr != NULL)
{
strSize[strCnt++] = strlen(pstr);
pstr = strtok(NULL, " ");
}
The strtok() function returns pstr == NULL when there are no further tokens to return, however your code does not take notice of this and instead immediately calls strcpy(copied, pstr);, which will result in your crash. Check for NULL and terminate the loop immediately before otherwise using pstr.
For bonus learning points, walk through this in your debugger to follow exactly what happens.
I am writing a program where I use strtok in order to find each word in a string that I type into the command line, in my example, my code is called command.c so when I type:
./command.out "Hi, there"
I should get as my result:
Arg = "Hi, there"
Next word "Hi,"
Next word "there"
so far my code will complete the arg part of the print statement, but will not use execute the latter part in order to separate the string in question, my code currently is as follows:
#include <stdio.h>
#include <string.h>
void main (int argc, char *argv[]) {
int i;
for(i =1;i< argc; i++)
printf("Arg = %s\n", argv[i]);
char delims[] = " ";
char *word = NULL;
word = strtok(argv[i], delims);
while(word != NULL) {
printf("Next word \"%s\"\n", word);
word = strtok(NULL, delims);
}
}
Where am I going wrong and how can I fix this code? Thanks for all the help
You are missing the curly braces around the for block:
for(i =1;i< argc; i++)
{
printf /* ... and so forth */
}
Your code indentation is wrong, this may cause your problem.
The 'for' statement affects only the next line, the printf one, so variable 'i' increases later to value '2', then when you ask for argv[i], you're asking for argv[2], you should call argv[1].
I have a problem using strtok in C. I get a user input from the command line using fgets and I want to tokenize it with pipe ("|") as the delimeter and put the result in a double pointer variable. Here's my code:
char** argv;
char *token;
token = strtok(userInput, "|");
while(token != NULL){
*(argv++) = token;
token = strtok(NULL, "|");
}
*argv = '\0';
I then use this code to verify if it's well tokenized
while(*argv!= NULL)
{
if((strcmp(*argv, "|") == 0){
count = count + 1;
}
argv++;
}
printf("%d pipes", count);
But it doesn't work. char** argv contains nothing. The execution of the code stops and it returns -1. When I try to print argv, argv contains no values.
Any ideas please? Thanks.
Edit:
What i want to do is this
userInput = "abc|cde";
After using strtok. I want to have an **argv
**argv = "abc";
One problem is that you don't seem to be initializing argv. You need to allocate enough memory for it to hold as many char *s as are needed. Otherwise you're writing to some random block of memory. (Is it just that you haven't shown us the relevant code?)
Another problem is that you're actually modifying argv, so at the end of that loop, it's pointing one past the last token (and then you set *argv to NULL); but your verification code assumes that it's pointing to the first token, and starts by confirming that *argv is not NULL. (Is it just that you haven't shown us some relevant code?) Edited to add: I see from your comment above that "argv contains no values". I'm pretty confident that this is the reason why.
Incidentally, you're confusing '\0' (a null byte) with NULL (a null pointer). Technically this works out correctly — '\0' gets promoted to 0, 0 gets converted to NULL — but I find it a bit worrisome that you're confusing them, since conceptually they are quite different. You should write *argv = NULL rather than *argv = '\0', for clarity if nothing else.
your tokenizing code works like this :
if
userInput = "a|b|c"
then
argv = { "a", "b", "c" }
you might be expecting that
argv = {"a","|","b","|","c"}
Your code to count pipes should be :
while(*argv != NULL)
{
count = count + 1;
argv++;
}
printf("%d pipes", count-1);
I think it will work
what I am using is this format for searching 300x400. looking for the "x" to get rid of the x and use both sides, the 300 and 400 . this works for me.
char *tok1, *tok2, *saveptr;
tok1 = strtok_r(argv, "x", &saveptr);
tok2 = strtok_r(NULL, "x", &saveptr);
printf("this tok1 %s this is tok2 %s\n", tok1, tok2);
using strtok_r function
the problem is your argv does not point to first element when you try to get result from it.
problem occurs here:
*(argv++) = token
argv (a pointer to char*) is increased when you add token pointer to argv array (I assume you have initialized it correctly). So when you use the second part of code to get the result, argv already points to the last element, in your case '\0', which will produce no output.
And, you are mixing '\0' with NULL, although they are both right grammatically, but it using NULL is better in your case, because it means a pointer, but '\0' means null-terminate in a C-string
You can change the your code to the following:
/* Init argv array */
char** argv;
size_t argc=0; // token count
char *token;
token = strtok(userInput, "|");
while(token != NULL){
argv[argc++] = token;
token = strtok(NULL, "|");
}
argv[argc] = NULL; // the last element of argv array is a NULL pointer
/* get result from argv */
while(*argv!= NULL)
{
if((strcmp(*argv, "|") == 0){
count = count + 1;
}
argv++;
}
printf("%d pipes", count);