Reputation: 113
I'm attempting to do basic file reading in C with fgets
. It should read one line, pass it to the tokeniser function which should split it at every ' '
and add it to a linked list. At the moment it is entering into a never ending while loop and I'm not sure why. Any help is appreciated. I am really struggling with this C language
#define INPUTSIZE 11
void tokeniseString(LinkedList *list, char *str)
{
char *token = strtok(str, " ");
while (token != NULL)
{
insertLast(list, *token);
}
}
void readInputFile(char *fileName, LinkedList *list)
{
FILE* inputFile = fopen(fileName, "r");
char str[INPUTSIZE];
printf("1");
if (inputFile == NULL)
{
perror("Could not open file");
}
else
{
while (fgets(str, INPUTSIZE, inputFile) != NULL)
{
tokeniseString(list, str);
}
if (ferror(inputFile))
{
perror("Error while reading from file");
}
}
}
Upvotes: 1
Views: 59
Reputation: 145287
You have an endless loop because you do not scan for the next token in the loop body. You should write:
void tokeniseString(LinkedList *list, char *str) {
char *token = strtok(str, " ");
while (token != NULL) {
insertLast(list, *token);
token = strtok(NULL, " ");
}
}
Not however that you insert the value of the first byte of the token into the list. You should probably convert the token as a number using strtol()
instead:
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
void tokeniseString(LinkedList *list, char *str) {
char *token = strtok(str, " \t\r\n");
while (token != NULL) {
char *p;
long value;
errno = 0;
value = strtol(token, &p, 10);
if (p == token || *p != '\0') {
fprintf(stderr, "token is not a number: %s\n", token);
} else
if (errno != 0 || value > INT_MAX || value < INT_MIN) {
fprintf(stderr, "number is out of range: %s\n", token);
} else {
insertLast(list, (int)value);
}
token = strtok(NULL, " \t\r\n");
}
}
Note that modifying the string argument is considered bad practice, especially using a function with side effects on a static state such as strtok()
. Here is another version that does not modify the argument:
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void tokeniseString(LinkedList *list, const char *str) {
for (;;) {
char *p;
long value;
int len;
/* skip whitespace */
str += strspn(str, " \t\r\n");
if (*str == '\0')
break;
/* get the length of the token */
len = strcspn(str, " \t\r\n");
errno = 0;
value = strtol(token, &p, 10);
if (p == str) {
fprintf(stderr, "token is not a number: %.*s\n", len, str);
} else
if (p != str + len) {
fprintf(stderr, "token has extra characters: %.*s\n", len, str);
} else
if (errno != 0 || value > INT_MAX || value < INT_MIN) {
fprintf(stderr, "number is out of range: %.*s\n", len, str);
} else {
insertLast(list, (int)value);
}
str += len;
}
}
Also note that you must close the file in readInputFile()
.
Upvotes: 1