Struct in headerfile doesnt contain right data - c

i have created a headerfile containing a Struct:
functions.h
typedef struct ConfigData
{
char hostServerName[256];
unsigned short int portNmbr;
char gameKind[256];
} config;
extern config configInput;
in the file config.c I am adding data to the struct and I am able to print it correctly.
#include "functions.h"
config configInput;
char* splitString (char *lineInFile){
char *word = strtok (lineInFile, " ");
word = strtok (NULL, " ");
word = strtok (NULL, " ");
return word;
}
// Function removing spaces from a string
char * removeSpacesFromStr(char *string)
{
int non_space_count = 0;
for (int i = 0; string[i] != '\0'; i++)
{
if (string[i] != ' ')
{
string[non_space_count] = string[i];
non_space_count++;//non_space_count incremented
}
}
string[non_space_count] = '\0';
return string;
}
void readConfig (char* configFile){
FILE *fPointer= fopen (configFile, "r");
if (fPointer == NULL){
perror("ERROR: Couldnt open confg file!\n");
}
char bufferIn[256];
int count = 0;
while(fgets(bufferIn, 256, fPointer)) { // eventuell != NULL
if(strcmp(bufferIn, "") != 0){
bufferIn[strcspn(bufferIn, "\n")] = 0;
switch (count) {
case 0:
strcpy(configInput.hostServerName, splitString(bufferIn));
break;
case 1:
configInput.portNmbr = atoi(splitString(bufferIn));
break;
case 2:
strcpy(configInput.gameKind, splitString(bufferIn));
break;
}
count++;
}
}
printf("\n>>>Config File Data<<<\n");
printf("HostServerName: %s\n", configInput.hostServerName);
printf("PortNumber: %d\n", configInput.portNmbr);
printf("GameKind: %s\n\n ", configInput.gameKind);
}
but when I try to print the data from this struct in the main method, it doesn't work properly. It just prints some random chars
#include "functions.h"
int main (int argc, char *argv[]) {
char gamekindname[256]= "NMMorris";
char *hostname[256] = "sysprak.priv.lab.nm.ifi.lmu.de";
int portnumber = 1357;
char* gameID = argv[2];
char playerNumber[256];
char configFile[256] = "client.conf" ;
...
//read in Data from config File
readConfig(configFile);
config configInput;
strcpy(gamekindname, configInput.gameKind);
strcpy(hostname, configInput.hostServerName);
portnumber = configInput.portNmbr;
}
So when I try to access the data of the configInput struct it doesn't show the correct one.
Best Enno :)

I would suggest to pass a pointer to config in the readConfig()method.
Something like this:
config localConfig;
readConfig(configFile, &localConfig);
And the function:
void readConfig (char* configFile, config* ptr_config){
FILE *fPointer= fopen (configFile, "r");
if (fPointer == NULL){
perror("ERROR: Couldnt open confg file!\n");
}
char bufferIn[256];
int count = 0;
while(fgets(bufferIn, 256, fPointer)) { // eventuell != NULL
if(strcmp(bufferIn, "") != 0){
bufferIn[strcspn(bufferIn, "\n")] = 0;
switch (count) {
case 0:
strcpy(*ptr_config->hostServerName, splitString(bufferIn));
break;
case 1:
*ptr_config->portNmbr = atoi(splitString(bufferIn));
break;
case 2:
strcpy(*ptr_config->gameKind, splitString(bufferIn));
break;
}
count++;
}
}
printf("\n>>>Config File Data<<<\n");
printf("HostServerName: %s\n", *ptr_config->hostServerName);
printf("PortNumber: %d\n", *ptr_config->portNmbr);
printf("GameKind: %s\n\n ", *ptr_config->gameKind);
}

For starters the program should not compile at least due to this invalid declaration
char *hostname[256] = "sysprak.priv.lab.nm.ifi.lmu.de";
It seems that instead of the array of pointers you mean a character array
char hostname[256] = "sysprak.priv.lab.nm.ifi.lmu.de";
This statement
if(strcmp(bufferIn, "") != 0){
does not make sense. It seems you mean
if ( bufferIn[0] != '\n' ){
This switch statement within the while loop
switch (count) {
case 0:
strcpy(configInput.hostServerName, splitString(bufferIn));
break;
case 1:
configInput.portNmbr = atoi(splitString(bufferIn));
break;
case 2:
strcpy(configInput.gameKind, splitString(bufferIn));
break;
}
count++;
also does not make sense. After three iterations of the while loop the variable count will be equal to 3 and the compound statement of the switch statement will be skipped.
The function splitString looks suspecious.
char* splitString (char *lineInFile){
char *word = strtok (lineInFile, " ");
word = strtok (NULL, " ");
word = strtok (NULL, " ");
return word;
}
There is no check whether word is equal to NULL.
Within main you are using the local variable configInput that is not initialized
config configInput;
strcpy(gamekindname, configInput.gameKind);
strcpy(hostname, configInput.hostServerName);
portnumber = configInput.portNmbr;
Pay attention to that there is no sense to declare character arrays with 256 characters if they store string literals with much less characters as for example
char configFile[256] = "client.conf";
It is much better to declare a pointer like
const char *configFile = "client.conf";
Shortly speaking you need to rewrite the whole program anew.

Related

How to make a function to input a string with unknown length in c with type void

I am trying to make a function that input an unknown length of a string , but I don't want it to return anything I want it to make changes by using the pointer that I pass.
this was my attempt .
#include <stdlib.h>
#include <stdio.h>
void get(char * string){
int size=1;
string = malloc(size);
char c;
int i=0;
while(1){
c = getchar();
if(c=='\n'){break;}
string[i] = c;
i++;
string = realloc(string , ++size);
}
string[i] = '\0';
}
int main(){
char *buff;
printf("String :");
get(buff);
printf("%s" , buff);
return 0;
}
the output on my gcc windows os :
PE
1- what is the PE
2- what is wrong here
3- is the c=='\n' line good for the test if the user pressed an enter or should i use EOF or something else
I made a few changes to your code so that it would use the pointer passed to it and handle a possible EOF in the input:
#include <stdlib.h>
#include <stdio.h>
void get(char **string){
char *input = NULL;
int result, index = 0;
while (1) {
result = getchar();
if (EOF == result) { printf("\n"); break; }
if ('\n' == result) break;
char *temp = realloc(input , index + 2);
if (NULL == temp) {
perror("Could not increase memory for string");
if (input) free(input);
exit(1);
}
input = temp;
input[index++] = (char) result;
}
if (input) {
input[index] = '\0';
*string = input;
}
}
int main(void) {
char *buff = NULL;
printf("String : ");
get(&buff);
if (buff) {
printf("%s\n" , buff);
free(buff);
}
return 0;
}
Output
$ ./main
String : a short string
a short string
$ ./main
String : input with EOF
input with EOF
Note
I do my best to handle error conditions, but I am not certain I caught everything.

Unknown C String Truncation/Overwrite

I am having an interesting memory problem with a simple string manipulation. The problem itself isn't actually in the reading of the string but right before it when I am trying to call the string.
char *removeInvalid(char *token){
fprintf(stderr," Before: %s \n", token);
char *newToken = malloc(sizeof(100) + 1);
fprintf(stderr," After: %s \n", token);
}
Whenever I run this, the string if truncated right after the char *newToken is malloc'd. So the printout of this results in
Before: Willy Wanka's Chochlate Factory
After: Will Wanka's Chochlate F!
Anyone have any clue what this is? I looked at other examples of malloc, but can't figure out how it is going wrong here.
EDIT: FULL CODE BELOW. Take note I am a college student who just began C, so it isn't perfect by anymeans. But it works up until this error.
Function calls goes as follows. Main->initialReadAVL (This part works perfectly)
Then after commandReadAVL is called which goes commandReadAVL->ReadHelper (Again works fine here.
Then CleanUpString->removeSpaces(works fine)
Then CleanUpString->removeInvalid(THIS IS WHERE IT ERRORS)
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include "node.h"
#include "avl.h"
#include "scanner.h"
#include "bst.h"
/* Options */
int avlSwitch = 0;
int bstSwitch = 0;
int insertSwitch = 0;
int deleteSwitch = 0;
int frequencySwitch = 0;
int displaySwitch = 0;
int statisticSwitch = 0;
int ProcessOptions(int argc, char **argv);
char *cleanUpString(char *token);
char *turnToLowerCase(char *token);
char *removeSpaces(char *token);
char *removeInvalid(char *token);
char *readHelper(FILE *in);
void Fatal(char *fmt, ...);
void preOrder(struct node *root);
void initialReadAVL(avl *mainAVL, FILE *in);
void initialReadBST(bst *mainBST, FILE *in);
void commandReadBST(bst *mainBST, FILE *commandList);
void commandReadAVL(avl *mainAVL, FILE *commandList);
int main(int argc, char **argv) {
struct avl *mainAVL;
struct bst *mainBST;
FILE *text;
FILE *commandList;
if(argc != 4){
Fatal("There must be 4 arguments of form 'trees -b corpus commands' \n");
}
int argIndex = ProcessOptions(argc,argv);
text = fopen(argv[2], "r");
commandList = fopen(argv[3], "r");
//Protect against an empty file.
if (text == NULL){
fprintf(stderr,"file %s could not be opened for reading\n", argv[2]);
exit(1);
}
if (commandList == NULL){
fprintf(stderr,"file %s could not be opened for reading\n", argv[3]);
exit(1);
}
if (avlSwitch){
mainAVL = newAVL();
initialReadAVL(mainAVL, text);
preOrder(mainAVL->root);
fprintf(stderr,"\n");
commandReadAVL(mainAVL, commandList);
preOrder(mainAVL->root);
fprintf(stderr,"\n");
}
else if (bstSwitch){
mainBST = newBST();
initialReadBST(mainBST, text);
preOrder(mainBST->root);
commandReadBST(mainBST, commandList);
preOrder(mainBST->root);
}
return 0;
}
void commandReadAVL(avl *mainAVL, FILE *commandList){
char *command;
char *textSnip;
while(!feof(commandList)){
command = readHelper(commandList);
textSnip = readHelper(commandList);
textSnip = cleanUpString(textSnip);
if(command != NULL){
switch (command[0]) {
case 'i':
fprintf(stderr,"%s \n", textSnip);
insertAVL(mainAVL, textSnip);
break;
case 'd':
deleteAVL(mainAVL, textSnip);
break;
case 'f':
break;
case 's':
break;
case 'r':
break;
default:
Fatal("option %s not understood\n",command);
}
}
}
}
void commandReadBST(bst *mainBST, FILE *commandList){
char *command;
char *textSnip;
while(!feof(commandList)){
command = readHelper(commandList);
textSnip = readHelper(commandList);
textSnip = cleanUpString(textSnip);
if(command != NULL){
switch (command[0]) {
case 'i':
insertBST(mainBST, textSnip);
break;
case 'd':
deleteBST(mainBST, textSnip);
break;
case 'f':
break;
case 's':
break;
case 'r':
break;
default:
Fatal("option %s not understood\n",command);
}
}
}
}
char *readHelper(FILE *in){
char *token;
if (stringPending(in)){
token = readString(in);
}
else {
token = readToken(in);
}
return token;
}
void initialReadBST(bst *mainBST, FILE *in){
char *token;
while(!feof(in)){
token = readHelper(in);
token = cleanUpString(token);
if (token != NULL){
insertBST(mainBST, token);
}
}
}
void initialReadAVL(avl *mainAVL, FILE *in){
char *token;
while(!feof(in)){
token = readHelper(in);
token = cleanUpString(token);
if (token != NULL){
insertAVL(mainAVL, token);
}
}
}
//Helper Function to clean up a string using all the prerequisites.
char *cleanUpString(char *token){
char *output = malloc(sizeof(*token)+ 1);
if (token != NULL){
output = removeSpaces(token);
fprintf(stderr,"before : %s \n", output);
output = removeInvalid(output);
fprintf(stderr,"%s \n", output);
output = turnToLowerCase(output);
return output;
}
return NULL;
}
//Helper function to turn the given string into lower case letters
char *turnToLowerCase(char *token){
char *output = malloc(sizeof(*token) + 1);
for (int x = 0; x < strlen(token); x++){
output[x] = tolower(token[x]);
}
return output;
}
//Helper function to remove redundent spaces in a string.
char *removeSpaces(char *token){
char *output;
int x = 0;
int y = 0;
while (x < strlen(token)){
if (token[x]== ' ' && x < strlen(token)){
while(token[x] == ' '){
x++;
}
output[y] = ' ';
y++;
output[y] = token[x];
y++;
x++;
}
else {
output[y] = token[x];
y++;
x++;
}
}
return output;
}
char *removeInvalid(char *token){
fprintf(stderr," Before: %s \n", token);
char *newToken = malloc(sizeof(* token)+ 1);
fprintf(stderr," After: %s \n", token);
int x = 0;
int y = 0;
while (x < strlen(token)){
if (!isalpha(token[x]) && token[x] != ' '){
x++;
}
else {
newToken[y] = token[x];
y++;
x++;
}
}
return newToken;
}
//Processes a system ending error.
void Fatal(char *fmt, ...) {
va_list ap;
fprintf(stderr,"An error occured: ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(-1);
}
//Processes the options needed to be executed from the command line
int ProcessOptions(int argc, char **argv) {
int argIndex;
int argUsed;
int separateArg;
argIndex = 1;
while (argIndex < argc && *argv[argIndex] == '-')
{
/* check if stdin, represented by "-" is an argument */
/* if so, the end of options has been reached */
if (argv[argIndex][1] == '\0') return argIndex;
separateArg = 0;
argUsed = 0;
if (argv[argIndex][2] == '\0')
{
separateArg = 1;
}
switch (argv[argIndex][1])
{
case 'b':
bstSwitch = 1;
break;
case 'a':
avlSwitch = 1;
break;
default:
Fatal("option %s not understood\n",argv[argIndex]);
}
if (separateArg && argUsed)
++argIndex;
++argIndex;
}
return argIndex;
}
void preOrder(struct node *root) {
if(root != NULL)
{
fprintf(stderr,"%s ", root->key);
preOrder(root->lChild);
preOrder(root->rChild);
}
}
ReadString()
char *
readString(FILE *fp)
{
int ch,index;
char *buffer;
int size = 512;
/* advance to the double quote */
skipWhiteSpace(fp);
if (feof(fp)) return 0;
ch = fgetc(fp);
if (ch == EOF) return 0;
/* allocate the buffer */
buffer = allocateMsg(size,"readString");
if (ch != '\"')
{
fprintf(stderr,"SCAN ERROR: attempt to read a string failed\n");
fprintf(stderr,"first character was <%c>\n",ch);
exit(4);
}
/* toss the double quote, skip to the next character */
ch = fgetc(fp);
/* initialize the buffer index */
index = 0;
/* collect characters until the closing double quote */
while (ch != '\"')
{
if (ch == EOF)
{
fprintf(stderr,"SCAN ERROR: attempt to read a string failed\n");
fprintf(stderr,"no closing double quote\n");
exit(6);
}
if (index > size - 2)
{
++size;
buffer = reallocateMsg(buffer,size,"readString");
}
if (ch == '\\')
{
ch = fgetc(fp);
if (ch == EOF)
{
fprintf(stderr,"SCAN ERROR: attempt to read a string failed\n");
fprintf(stderr,"escaped character missing\n");
exit(6);
}
buffer[index] = convertEscapedChar(ch);
}
else
buffer[index] = ch;
++index;
ch = fgetc(fp);
}
buffer[index] = '\0';
return buffer;
}
INPUT: Commands.txt
i "Willy Wonka's Chochlate Factory"
INPUT testFile.txt
a b c d e f g h i j k l m n o p q r s t u v w x y z
Thanks!
char *turnToLowerCase(char *token){
char *output = malloc(sizeof(*token) + 1);
for (int x = 0; x < strlen(token); x++){
output[x] = tolower(token[x]);
}
return output;
}
This is probably your main issue. You allocate enough space for two characters and then proceed to store lots more than that. You probably wanted:
char *output = malloc(strlen(token) + 1);
Since token is a char*, *token is a char. So sizeof(*token) is sizeof(char) -- definitely not what you want.
You almost certainly have a buffer overrun in some part of the code that you're not showing us. If I were to guess, I'd say you allocate too little storage for token to contain the full string you're writing into it in the first place.
Did you by any chance allocate token using the same erroneous code you have in removeInvalid():
malloc(sizeof(100) + 1);
^^^^^^^^^^^ this doesn't allocate 101 characters, it allocates sizeof(int)+1
char *readHelper(FILE *in){
char * token = malloc(sizeof(char *) + 1);
if (stringPending(in)){
token = readString(in);
}
else {
token = readToken(in);
}
return token;
}
It's hard to make sense of this without being able to see readString or readToken, but this can't possibly be right.
First, you allocate one more byte than is needed for a pointer to one or more characters. What use would such a thing be? If you're not storing a pointer to one or more characters, why use sizeof(char *)? If you are storing a pointer to one or more characters, why add one? It's hard to imagine the reasoning that lead to that line of code.
Then, in the if, you immediately lose the value you got back from malloc because you overwrite token by using it to store something else. If you weren't going to use the value you assigned to token, why did you assign it at all?
Bluntly, a lot of this code simply doesn't make any sense. Without comments, it's hard to understand the reasoning so we could point out what's wrong with it.
Either there was reasoning behind that line of code, in which case it's just completely wrong reasoning. Or worse, the line of code was added with no reasoning in the hopes it would work somehow. Neither method will produce working code.
When you're trying to debug code, first remove anything you added experimentally or that you didn't understand. If you do understand malloc(sizeof(char *) + 1), then please explain what you think it does so that your understanding can be corrected.
Why did you think you needed a buffer that was one byte larger than the size of a pointer to one or more characters?
With the help of David Schwartz and the other posters I was able to find the bug in my problem. When I was allocating memory for my token/output, I wasn't allocating enough space.. Using the erroneous code of
malloc(sizeof(100) + 1);
and
malloc(sizeof(*token) + 1);
both of which produced only a couple of bytes to be allocated. This caused a buffer problem causing random letters and numbers/ truncation to happen. The first resulting in the space equivalent to int + 1 and the second in char + 1. (as I was taking the sizeof token which is just the size of what it originally started as, a char)
To fix this I changed the allocation of my token variable to that of
malloc(strlen(token) + 1);
This allocates a space equivalent to the "string" length of token + 1. Allowing the appropriate space for my problem which would end up with space of <= token.

Segmentation fault, parsing, C

I am writing a c file that takes in information from a .csv file, parse it, then delete whatever ive parsed. The problem that i am having is that, after it runs through one line of the .csv file i get a segmentation fault. I heard i can use GDB to help with this, but I don't know how to use that. This is my .c file
void parser(int argc, char ** argv)
{
FILE * songList;
char * theString;
char * theToken;
char songs[ROOM_STRING_LENGTH];
char artist[ROOM_STRING_LENGTH];
char title[ROOM_STRING_LENGTH];
int x;
int length;
double size;
char * type;
char songType[1];
char songTypeC;
MusicRec * next;
theToken = "";
songList = fopen(argv[1], "r");
if(songList == NULL)/*returns an error if file wasnt opened*/
{
printf("error opening file\n");
}
else
{
while(fgets(songs, ROOM_STRING_LENGTH, songList) != NULL)/*gets one string at a time until fgets equals NULL*/
{
theString = malloc((sizeof(char)*(strlen(songs)+1))); /* mallocs some memory*/
strcpy(theString, songs);
x = 0;
for(theToken = strtok(theString, ","); theToken; theToken = strtok(NULL, ","))
{
switch(x)
{
case 0:
strcpy(artist, theToken);
printf("%s\n", artist);
break;
case 1:
strcpy(title, theToken);
printf("%s\n", title);
break;
case 2:
sscanf(theToken, "%d",&length);
printf("%d\n", length);
break;
case 3:
size = atof(theToken);
printf("%.2f\n", size);
break;
case 4:
type = malloc(sizeof(char));
sscanf(theToken, "%s",type);
songType[0] = *type;
songTypeC = songType[0];
printf("%c\n", songTypeC);
free(type);
break;
}
x++;
}
next = malloc(sizeof(MusicRec));
next = createRecord(title, artist, size, length, songTypeC);
/*print = printRecord(toPrint);*/
destroyRecord(next);
/*free(print);*/
free(next);
}
free(theString);
free(theToken);
fclose(songList);
}
}
These are the 2 functions being called:
char * printRecord(MusicRec * toPrint)
{
char token[ROOM_STRING_LENGTH];
char * pointer;
sprintf(token, "%s (%s):%d[%.2f]", toPrint->title, toPrint->artist, toPrint->lengthInSeconds, toPrint->sizeInKB);
pointer = malloc(sizeof(char)*strlen(token));
strcpy(pointer, token);
return(pointer);
}
void destroyRecord(MusicRec * theRecord)
{
free(theRecord->title);
free(theRecord->artist);
}
Take a look at this piece of code:
case 4:
type = malloc(sizeof(char));
sscanf(theToken, "%s",type);
You're allocating a 1 byte string and reading an arbitrary length string into it.
That is prone to a segfault if the input token is larger than 1.

Loop through char array line by line

I know how to loop through a file line by line by reading into a FILE* using fopen, fgets etc
but how can i look through a char array line by line using plain C?
i have googled a lot an can only find stuff that reads from a file.
#include <stdio.h>
char *sgets(char *s, int n, const char **strp){
if(**strp == '\0')return NULL;
int i;
for(i=0;i<n-1;++i, ++(*strp)){
s[i] = **strp;
if(**strp == '\0')
break;
if(**strp == '\n'){
s[i+1]='\0';
++(*strp);
break;
}
}
if(i==n-1)
s[i] = '\0';
return s;
}
int main(){
const char *data = "abc\nefg\nhhh\nij";
char buff[16];
const char **p = &data;
while(NULL!=sgets(buff, sizeof(buff), p))
printf("%s", buff);
return 0;
}
Reading a character array line by line : What does a line mean ? '\n' Perhaps.
so, iterate through the array.
int main()
{ char array[10]="ab\nbc\ncd\n";
int lines =0;int i=0;
while(array[i]!='\0')
{ if(array[i]!='\n')
printf("%c",array[i++]);
else { lines++;i++; printf("\n"); }
} return 0;
}
In case if you want to keep your separator flexible (e.g. you got "\r\n") and stick to libraries, strtok is handy:
#include <cstring>
int main() {
const char separator[3] = "\r\n";
char text[13] = "ab\r\ncd\r\nef\r\n";
char *line = NULL;
line = strtok(text, separator);
while (line != NULL) {
printf("%s\n", line); // call your function to process line
line = strtok(NULL, separator); // NULL means continue from where the previous successful call to strtok ended
}
system("pause"); // just prevent console from closing
}

Parsing csv file with missing entries

I am trying to parse a csv file with C where the separator is | using strtok. The problem is that some fields are empty and thus two separators are placed next to each other. It seems that strtok is just skipping all empty fields and just outputting the next non-empty field.
The thing is that I need to know at which position the token that is being read belongs to.
Here is a very small example to illustrate.
FILE
node|171933|||traffic_signals|||||40.4200658|-3.7016652
This line for instance has 10 fields, but only field 1,2,9 and 10 have some value in it.
CODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
FILE *fp;
char lineBuf[128];
char *token;
int i=0;
if((fp = fopen("test.txt", "r"))==NULL){
fprintf (stderr, "\nError when opening file\n");
return ;
}
fgets (lineBuf, sizeof(lineBuf), fp);
token=strtok(lineBuf, "|\n");
while(token!=NULL){
printf("Element %d: %s\n",i,token); i++;
token=strtok(NULL, "|\n");
}
}
OUTPUT
Element 0: node
Element 1: 171933
Element 2: traffic_signals
Element 3: 40.4200658
Element 4: -3.7016652
EXPECTED OUTPUT
Element 0: node
Element 1: 171933
Element 4: traffic_signals
Element 9: 40.4200658
Element 10: -3.7016652
Is there any other way to parse a line like this as expected? The number of elements in a line is not defined previously.
I already know that the behaviour shown by strtok is the usual behaviour I am just asking for another way of doing it to obtain the desired results, not for the explanation of why this happens.
I am not sure what platform you are on, but strsep() is the recommended replacement for what you are trying to do.
man strsep
while (fgets(buf, BUFSIZE, fp) != NULL) {
char *line = buf;
char *field;
int index = 0;
while ((field = strsep(&line, "|")) != NULL) {
/* note the trailing field will contain newline. */
printf("element %d = %s\n", index, field);
index++;
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//non skip version strtok
char *my_strtok_r(char *str, const char *delims, char **store){
char *p, *wk;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
//*store += strspn(*store, delims);//skip delimiter
if(**store == '\0') return NULL;
p=strpbrk(wk=*store, delims);
if(p != NULL){
*p='\0';
*store = p + 1;
} else {
*store = NULL;
}
return wk;
}
char *my_strtok(char *str, const char *delims){
static char *p;
return my_strtok_r(str, delims, &p);
}
int main(void){
char lineBuf[128] = "node|171933|||traffic_signals|||||40.4200658|-3.7016652\n";
char *token;
int i=0;
token=my_strtok(lineBuf, "|\n");
while(token!=NULL){
if(*token)//token != "";
printf("Element %d: %s\n",i,token);
i++;
token=my_strtok(NULL, "|\n");
}
return 0;
}

Resources