In here I am trying to tokenize the user input e.g. load sml.txt.
The load command works fine because it has 2 tokens, but if I try to use a single word input like display, it crashes and gives me a segfault. I assume its because the second token is NULL, but I have no idea how to circumvent this issue. Can you help?
For your reference COMMAND_LOAD = "load" and COMMAND_DISPLAY = "display".
int main(int argc, char **argv)
{
AddressBookList *addressBookList;
char input[BUFSIZ];
char load[BUFSIZ];
char fileN[BUFSIZ];
char *fileName;
char *token;
showStudentInformation();
do
{
printf("Enter your command: \n");
fgets(input, sizeof(input), stdin);
input[strlen(input) - 1] = '\0';
token = strtok(input, " ");
strcpy(load, token);
token = strtok(NULL, " ");
strcpy(fileN, token);
fileName = fileN;
if (strcmp(load, COMMAND_LOAD) == 0)
{
addressBookList = commandLoad(fileName);
}
else if (strcmp(load, COMMAND_UNLOAD) == 0)
{
/*commandUnload(fileName);*/
}
else if (strcmp(load, COMMAND_DISPLAY) == 0)
{
if (fileN == NULL)
{
printf("> No file loaded");
}
else
{
commandDisplay(addressBookList);
}
}
else
{
printf("> Invalid input\n\n");
}
} while (strcmp(load, COMMAND_QUIT) != 0);
return EXIT_SUCCESS;
}
strtok() returns NULL when there's no more tokens, you can check for this. If there's no token, I empty the target string by assigning '\0' to the first character, instead of calling strcpy().
do
{
printf("Enter your command: \n");
fgets(input, sizeof(input), stdin);
token = strtok(input, " \n");
if (token) {
strcpy(load, token);
} else {
load[0] = '\0';
}
token = strtok(NULL, " \n");
if (token) {
strcpy(fileN, token);
} else {
fileN[0] = '\0';
}
...
} while (strcmp(load, COMMAND_QUIT) != 0);
There's also no need to replace the last character in the string with \0. Just include \n in the strtok() delimiters, so it won't include the newline at the end in the token.
Related
I have been trying to write a code to remove a word from an inputted string as part of my homework. But the thing is the outputted "modified" string never really gets modified and it actually always outputs the inputted string. I'm new to strings so I don't have a perfect understanding of how the string.h library functions work.
#include<stdio.h>
#include<string.h>
int main(void)
{
char str[60], strtemp[60], word[10], * token;
printf("Enter the sentence: ");
gets_s(str);
printf("Enter the word to be deleted: ");
gets_s(word);
int i = 0;
token = strtok(str, " ");
while (token != NULL) {
if (!i && token != word)
strcpy(strtemp, token);
else if (token == word) {
token = strtok(NULL, " ");
continue;
}
else {
strcat(strtemp, " ");
strcat(strtemp, token);
}
token = strtok(NULL, " ");
i++;
}
strcpy(str, strtemp);
printf("Modified string: %s \n", str);
}
Add the following:
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
while ((p = strstr(p, sub)) != NULL) {
memmove(p, p + len, strlen(p + len) + 1);
}
}
return str;
}
You should use the memmove() (written on your post's comment too.)
Reference: this thread of SO.
I am trying to read in two lines using fgets, but only the first line is read and then returns a segmentation fault. I'm not sure what I would need to change for it to read in the second line. Any help would be appreciated!
int main(void)
{
char str[100];
char *word;
//First Line
fgets(str, 100, stdin);
printf("%s", str);
word = strtok(str," ");
printf("%s\n", word);
while(word != NULL)
{
word = strtok(NULL," ");
printf("%s\n", word);
}
//Second Line
fgets(str, 100, stdin);
printf("%s", str);
word = strtok(str," ");
printf("%s\n", word);
while(word != NULL)
{
word = strtok(NULL," ");
printf("%s\n", word);
}
return 0;
}
You got the order of function calls wrong in two parts of your code; Your are calling printf() after calling strtok() without checking for NULL. Fix it as follows:
int main(void)
{
char str[100];
char *word;
//First Line
fgets(str, 100, stdin);
printf("Printing entire string: %s\n", str);
word = strtok(str, " ");
printf("Printing tokens:\n");
while (word != NULL)
{
printf("%s\n", word);
word = strtok(NULL, " ");
}
//Second Line
fgets(str, 100, stdin);
printf("Printing entire string: %s\n", str);
word = strtok(str, " ");
printf("Printing tokens:\n");
while (word != NULL)
{
printf("%s\n", word);
word = strtok(NULL, " ");
}
return 0;
}
regarding:
word = strtok(str," ");
printf("%s\n", word);
while(word != NULL)
{
word = strtok(NULL," ");
printf("%s\n", word);
}
the function: strtok() can return NULL.
The result is the call to printf() will be trying to print a value from address 0.
That is what is causing the seg fault.
Suggest:
word = strtok(str," ");
while(word != NULL)
{
printf("%s\n", word);
word = strtok(NULL," ");
}
So consider this string:
1,2.2, 3.5 ,6, 7.7
And i want to separate each number, so until now i try this:
void readuserinput(char *ch)
{
char* buffer;
buffer = strtok(ch, ",");
while (buffer) {
printf("%s\n", buffer);
buffer = strtok(NULL, ",");
while (buffer && *buffer == '\040')
buffer++;
}
}
But this ignored theTab and print the number 7.7 with tab before.
As you can see in strtok documentation you can specify multiple delimiters to it. So you don't have to manually deal with whitespaces. strtok will do that for you:
void readuserinput(char *ch)
{
ch = strtok(ch, ", \t");
while (ch)
{
printf("%s\n", ch);
ch = strtok(NULL, ", \t");
}
}
I need to make a program that will emulate the terminal of Linux. Since some system calls requires 1,2 or more arguments, I want to make sure that the number of parameters given are correct. I'm using strtok() to separate the call name from the arguments, but I need to know how many tokens strtok() created to compare it.
Here's and example code:
char *comand = (char*) malloc(sizeof(char)*100);
char *token;
char *path1 = (char*) malloc(sizeof(char)*100);
char *path2= (char*) malloc(sizeof(char)*100);
fgets(comand, 100, stdin);
printf( "\nYou entered: %s \n", comand);
token = strtok(comand ," ");
//Check the number of tokens and add a condition in each IF to match
if (strcmp("ls",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
}
else if (strcmp("cat",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
}
else if (strcmp("cp",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
token = strtok(NULL," ");
strcpy(path2,token);
}
else if (strcmp("mv",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
token = strtok(NULL," ");
strcpy(path2,token);
}
else if (strcmp("find",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
}
else if (strcmp("rm",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
}
else if (strcmp("mkdir",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
}
else if (strcmp("rmdir",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token);
}
else if (strcmp("quit",token) == 0) {
exit(0);
}
else print("Number of parameters do not match);
the only thing strtok() does is look for the next occurance of the delimiter and overwrite that character with a \0 and return the pointer with the offset added. the pointer is kept in a static variable that's why a subsequent call to it with a NULL for the char * will perform it on the last string used from the offset that the last delimiter was found.
this page has a very nice example:
http://en.cppreference.com/w/c/string/byte/strtok
If you only want to count the arguments it would be easier to use strchr(), this function searches for a character and returns a pointer to its location. you could use it like this.
unsigned int i = 0;
char *temp = token;
while ( (temp = strchr(temp, '') != NULL) ) {
++i;
}
this has the added benefit of not modifying your original char array while strtok() does!
I would handle this within the functions you create for each command.
you pass all options to the function and there you parse it. either with strtok() or whatever else you want to use.
This keeps it nice and clean within the sub-routines and you will always know what to expect.
if (strcmp("ls",token) == 0) {
token = strtok(NULL," ");
strcpy(path1,token); // I would maybe change the path variable name to args
ret = lscmd(path1);
if (ret == -1) {
// invalid input detected
}
}
then you would have a ls function
int lsdcmd(char *args) {
// parse args for argumants you are looking for, return -1 if it fails
// do whatever you want to do.
}
You can count the arguments using strtok this way:
Example:
const char* delimiter = ",";
char* tokens[MAX_NUM_OF_ARGS];
unsigned int index = 0;
char* temp = strtok(buff,delimiter);
while (temp!=NULL){
if(index<MAX_NUM_OF_ARGS){
tokens[index]=temp;
}
index++;
temp = strtok(NULL,delimiter);
}
Then later you can iterate through the array of pointers (tokens) and compare them...
So I'm trying to add tokens to an array the if statement keeps verifying that the array, tokenHolder, is empty. My second while loop is where I try to input tokens into the array. However no tokens are inputted into the array and I don't understand why.
char* token;
int* bufflength = 0;
char* buffer = NULL;
char input[25000];
char *tokenHolder[2500];
int pos = 0;
while(1){
printf("repl> ");
getline(&buffer, &bufflength, stdin);
token = strtok(buffer, "");
//code to input tokens into array
while(token != NULL){
pos++;
token = strtok(NULL, "");
tokenHolder[pos] = token;
}
if(tokenHolder[0] == NULL){
printf("It's NULL");
}
}
You increment pos to 1 before you save any token, so nothing is ever assigned to tokenHolder[0].
Either use (note the use of blank rather than an empty string as the delimiter):
tokenHolder[0] = token = strtok(buffer, " ");
(or an equivalent) or do something like:
char *data = buffer;
while ((tokenHolder[pos++] = strtok(data, " ")) != NULL)
data = NULL;
char *tokenHolder[2500] = { NULL };
...
while(token != NULL){
tokenHolder[pos++] = token;
token = strtok(NULL, "");
}
if(tokenHolder[0] == NULL){//or if(pos == 0){
printf("It's NULL");
}