Using fgets in combination with strtok to transform input to tokens - c

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");
}
}

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.

Reading from an input file and storing words into an array [duplicate]

This question already has an answer here:
Unexpected strtok() behaviour
(1 answer)
Closed 4 years ago.
The end goal is to output a text file where repeating words are encoded as single digits instead. The current problem I'm having is reading words and storing them into an array.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_CODE 120
void main() {
FILE *inputfile = fopen("input.txt","rw");
char buffer[128];
char *token;
char *words[MAX_CODE];
int i = 0;
while(fgets(buffer, 128, inputfile)){
token = strtok(buffer," ");
printf("Token %d was %s",i,token);
while(token != NULL) {
words[i] = malloc(strlen(token)+1);
strcpy(words[i], token);
i++;
token = strtok(buffer," ");
}
}
for(int i = 0; i<3; i++) printf("%d\n%s\n",i,words[i]);
printf("End");
}
What I get is segmentation fault errors, or nothing. What I want is for words to be an array of strings. I'm allocating memory for each string, so where am I going wrong?
Your second call to strtok should pass NULL for the first argument. Otherwise, strtok will parse the first token over and over again.
token = strtok(buffer," ");
printf("Token %d was %s\n",i,token);
while(i < MAX_CODE && token != NULL) {
words[i] = malloc(strlen(token)+1);
strcpy(words[i], token);
i++;
token = strtok(NULL," ");
}
The check against MAX_CODE is for the safety's sake, in case you ever increase the size of your buffer or reduce the value of MAX_CODE. In your current code, the maximum number of space delimited tokens you can hold in a 128 byte buffer is 64.
From cppreference:
If str != NULL, the call is treated as the first call to strtok for this particular string. ...
If str == NULL, the call is treated as a subsequent calls to strtok: the function continues from where it left in previous invocation. ...

C tokenizing the input from stdin

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?

how to divide words with strtok in an array of chars in c

I have a struct named excuses that has chars, I need to store at least 20 excuses. Then, I need to divide each word of each excuse in an array.
¿How i can do that?
#define excuseLength 256
typedef struct{
char sentence[excuseLength];
}excuse;
excuse listExcuses[20];
for (int listExcuses_i = 0; listExcuses_i < 20; listExcuses_i++)
{
char *input;
scanf("%s", input);
strcpy(listExcuses[listExcuses_i].sentence, input);
char* token = strtok(input, " ");
while(token != NULL){
printf("token: %s\n", token);
token = strtok(NULL, " ");
}
}
Here are some things you can add to your solution:
Check fgets() for return value, as it returns NULL on error.
If you decide to still use scanf(), make sure to use scanf("%255s", input) instead for char input[256]. Using the format specifier %255s instead of the simpe %s checks for excessive input. Overall, it just better to read input using fgets().
Remove '\n' character appended by fgets(). This is also good for checking that you don't enter more characters than the limit of 256 in input, and that your sentences don't have a trailing newline after each of them. If you don't remove this newline, then your strtok() delimiter would have to be " \n" instead.
#define constants in your code, and use const char* for string literals, such as the delimiter for strtok().
You can also add some code to check for empty inputs from fgets(). You could simply use a separate counter, and only increment this counter for valid strings found.
It's also strange to have struct with one member, usually structs contain more than one member. You could simply bypass using a struct and use a 2D char array declared as char listexcuses[NUMEXCUSES][EXCUSELENGTH]. This array can hold up to 20 strings, each of which has a maximum length of 256.
Here is some modified code of your approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EXCUSELENGTH 256
#define NUMEXCUSES 20
typedef struct {
char sentence[EXCUSELENGTH];
} excuse;
int main(void) {
excuse listexcuses[NUMEXCUSES];
char input[EXCUSELENGTH] = {'\0'};
char *word = NULL;
const char *delim = " ";
size_t slen, count = 0;
for (size_t i = 0; i < NUMEXCUSES; i++) {
printf("\nEnter excuse number %zu:\n", count+1);
if (fgets(input, EXCUSELENGTH, stdin) == NULL) {
fprintf(stderr, "Error from fgets(), cannot read line\n");
exit(EXIT_FAILURE);
}
slen = strlen(input);
if (slen > 0 && input[slen-1] == '\n') {
input[slen-1] = '\0';
} else {
fprintf(stderr, "Too many characters entered in excuse %zu\n", count+1);
exit(EXIT_FAILURE);
}
if (*input) {
strcpy(listexcuses[count].sentence, input);
count++;
printf("\nTokens found:\n");
word = strtok(input, delim);
while (word != NULL) {
printf("%s\n", word);
word = strtok(NULL, delim);
}
}
}
return 0;
}
As you need to eventually store these tokens somewhere, you will need another form of storing this data. Since you don't know how many tokens you can get, or how long each token is, you may need to use something like char **tokens. This is not an array, but it is a pointer to a pointer. Using this would allow any number of words and any lengths of each word to be stored. You will need dynamic memory allocation for this. The answer in this post will help.
I changed the scanf for fgets and initialize the char input[256] and with that now it works!
#define excuseLength 256
#define numberExcuses 20
typedef struct{
char sentence[excuseLength];
}excuse;
excuse listExcuses[20];
for (int listExcuses_i = 0; listExcuses_i < numberExcuses; listExcuses_i++)
{
char input[256];
scanf("%s", input);
fgets(input, 256, stdin);
strcpy(listExcuses[listExcuses_i].sentence, input);
char* token = strtok(input, " ");
while(token != NULL){
printf("token: %s\n", token);
token = strtok(NULL, " ");
}
}

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