C tokenizing the input from stdin - c

I am work in parsing the commands that we get from stdin. My code nearly works. It prints all tokens except the first token. below is my code
/* Read a command line */
if (!fgets(line, 1024, stdin))
return 0;
char *p = strtok (line, " \n");
while (p != NULL)
{
Array[tokenscounter++] = p;
p = strtok (NULL, " \n");
}
}
return 0;
}
when i print all tokens stored in an array, it does not print the first one. any reason why is it behaving like that?

Related

How to get first and last word from lines in C?

I have a problem with code. I want to take first and last words from each lines from txt file. I wrote this code for now:
void StartEnd(char * word)
{
FILE* fp;
fp = fopen("linie.txt", "r");
if (fp == NULL) {
printf("! ");
return;
}
char store[MAX_LINE];
while (fgets(store, MAX_LINE - 1, fp)){
char * FirstWord = strtok(store," ");
char * LastWord;
char * token = strtok (store," ");
while (token != NULL){
LastWord = token;
token = strtok (NULL," ");
}
printf("%s\n",LastWord);
}
fclose(fp);
}
It is working for last word but only if i dont use FirstWord with strtok and i dont know why :(.
I would be grateful for any answer. Thanks!
On a first call, the function expects a C string as argument for str,
whose first character is used as the starting location to scan for
tokens. In subsequent calls, the function expects a null pointer and
uses the position right after the end of the last token as the new
starting location for scanning.
On subsequent calls to strtok, you are supposed to pass a NULL pointer. Doing that makes the function work properly:
void StartEnd(char * word)
{
FILE* fp;
fp = fopen("linie.txt", "r");
if (fp == NULL) {
printf("! ");
return;
}
char store[MAX_LINE];
while (fgets(store, MAX_LINE - 1, fp)){
char * FirstWord = strtok(store," ");
char * LastWord;
char * token = strtok (NULL, " ");
while (token != NULL){
LastWord = token;
token = strtok (NULL," ");
}
printf("%s\n",LastWord);
printf("%s\n",FirstWord);
}
fclose(fp);
}
Keep in mind that fgets reads n-1 characters or until it encounters a newline or EOF character. however a newline character is also considered a valid character and stored in the string. That means LastWord may end with a newline character. To fix that, pass " \n" instead of " " to strtok. Then both a newline and a blankspace are considered delimiters.

execvp not printing anything after fgets

I have been trying to make some kind of "my own shell". So, what I have been trying to do is get input with fgets() and execute it with execvp().
If I use execvp with an array made by me, it works as expected. However, if I try to do it with the results of fgets then I get no output.
main() {
char str[64];
char *array[sizeof(str)];
char *p = NULL;
int i = 0;
printf("my_shell >");
fgets(str, sizeof(str), stdin); // Use fgets instead of gets.
p = strtok(str," ");
while (p != NULL) {
array[i++] = p;
p = strtok(NULL, " ");
}
execvp(str, array);
}
As commented by user3386109, the solution was:
First, the array must have a NULL pointer at the end. Second, the delimiter string passed to both strtok should be " \n" (that's a space followed by a newline). You need the newline because fgets will put a newline character into your buffer, and you don't want that newline added to the array as an argument. Finally, put a perror("execvp failed"); after the execvp so that you get some indication of the problem when the execvp fails.

Using fgets in combination with strtok to transform input to tokens

I am reading input from different text files. These text files are integers that are either separated by a space, a new line, or a combination of spaces and new lines. I want to convert these strings to integers, and use these integers for a sorting algorithm.
char *line = malloc(BUF_SIZE);
char *token;
struct list* l = list_init();
while (fgets(buf, BUF_SIZE, stdin)) {
token = strtok(buf," \n");
printf("%s", token);
}
list_cleanup(l);
return 0;
What is wrong with this, it that it just prints the first element of each line. It doesn't handle multiple elements per line.
Thanks in advance.
You need to have loop to process all the tokens. strtok will return NULL once all the tokens are over.
Example:
while (fgets(buf, BUF_SIZE, stdin)) {
token = strtok(buf," \n");
while (token != NULL) {
printf("%s", token);
token = strtok(NULL," \n");
}
}

Taking of the last word in the line with strtok

Given a file with the following line:
word1 word2 word3 word4
I tried to write the following code:
FILE* f = fopen("my_file.txt", "r");
char line[MAX_BUFFER + 1];
if (fgets(line, MAX_LENGTH_LINE, f) == NULL) {
return NULL;
}
char* word = strtok(line, " ");
for (int i = 0; i < 4; i++) {
printf("%s ", word);
word = strtok(NULL, " ");
}
For prints the "words".
It's working. But, I don't understand something.
How it's acheive the last word word4? (I don't understand it because that after "word4" not exists a space)..
I'm not quite sure what you're asking. Are you asking how the program was able to correctly read word4 from the file even though it wasn't followed by a space? Or are you asking why, when the program printed word4 back out, it didn't seem to print a space after it?
The answer to the first question is that strtok is designed to give you tokens separated by delimiters, not terminated by delimiters. There is no requirement that the last token be followed by a delimiter.
To see the answer to the second question, it may be more clear if we adjust the program and its printout slightly:
char* word = strtok(line, " ");
for (int i = 0; word != NULL; i++) {
printf("%d: \"%s\"\n", i, word);
word = strtok(NULL, " ");
}
I have made two changes here:
The loop runs until word is NULL, that is, as long as strtok finds another word on the line. (This is to make sure we see all the words, and to make sure we're not trying to treat the fourth word specially in any way. If you were trying to treat the fourth word specially in some way, please say so.)
The words are printed back out surrounded by quotes, so that we can see exactly what they contain.
When I run the modified program, I see:
0: "word1"
1: "word2"
2: "word3"
3: "word4
"
That last line looks very strange at first, but the explanation is straightforward. You originally read the line using fgets, which does copy the terminating \n character into the line buffer. So it ends up staying tacked onto word4; that is, the fourth "word" is "word4\n".
For this reason, it's often a good idea to include \n in the set of whitespace delimiter characters you hand to strtok -- that is, you can call strtok(line, " \n") instead. If I do that (in both of the strtok calls), the output changes to
0: "word1"
1: "word2"
2: "word3"
3: "word4"
which may be closer to what you expected.
Your code doesn't check the return value of strtok(), it may be unsafe in some cases.
/* Split string
#content origin string content
#delim delimiter for splitting
#psize pointer pointing at the variable to store token size
#return tokens after splitting
*/
const char **split(char *content, const char *delim, int *psize)
{
char *token;
const char **tokens;
int capacity;
int size = 0;
token = strtok(content, delim);
if (!token)
{
return NULL;
}
// Initialize tokens
tokens = malloc(sizeof(char *) * 64);
if (!tokens)
{
exit(-1);
}
capacity = 64;
tokens[size++] = token;
while ((token = strtok(NULL, delim)))
{
if (size >= capacity)
{
tokens = realloc(tokens, sizeof(char *) * capacity * 2);
if (!tokens)
{
exit(-1);
}
capacity *= 2;
}
tokens[size++] = token;
}
// if (size < capacity)
// {
// tokens = realloc(tokens, sizeof(char *) * size);
// if (!tokens)
// {
// exit(-1);
// }
// }
*psize = size;
return tokens;
}

Get each word from a line in a text file

I am trying to read a txt file, and I can get the line which I want, but I can not print every words in this line one by one;
for example: the line looks like:
hello world 1 2 3
and I need print them one by one which looks like:
hello
world
1
2
3
I got the segmentation fault core dumped error
char temp[256];
while(fgets(temp, 256, fp) != NULL) {
...
int tempLength = strlen(temp);
char *tempCopy = (char*) calloc(tempLength + 1, sizeof(char));
strncpy(temCopy, temp, tempLength); // segmentation fault core dumped here;
// works fine with temp as "name country"
name = strtok_r(tempCopy, delimiter, &context);
country = strtok_r(Null, delimiter, &context);
printf("%s\n", name);
printf("%s\n", country);
}
Can anyone help me fix the code?
Thanks!
Impleted with strtok()
char *p;
char temp[256];
while(fgets(temp,256,fp) != NULL){
p = strtok (temp," ");
while (p != NULL)
{
printf ("%s\n",p);
p = strtok (NULL, " ");
}
}
If you see man strtok You will found
BUGS
Be cautious when using these functions. If you do use them, note that:
* These functions modify their first argument.
* These functions cannot be used on constant strings.
* The identity of the delimiting character is lost.
* The strtok() function uses a static buffer while parsing, so it's not thread safe. Use strtok_r() if this matters to you.
Try to make changes with strtok_r()
While read a line from a file you can invoke the following function:
if( fgets (str, 60, fp)!=NULL ) {
puts(str);
token = strtok(str," ");
while(token != NULL)
{
printf("%s\n",token);
token = strtok(NULL," ");
}
}

Resources