Home > Back-end >  Split a text using different delimiters
Split a text using different delimiters

Time:04-29

long time no coding in c and i'm a bit in trouble.

I get tex from a file formatted like that:

# 3 10
P1 16 3
P2 8  1
P3 10 2

from the second line every line represent a process with his own attributes divided by space, i need to take every attributes and put them in an array of struct like this one

typedef struct process
{
    char *name;
    int priority;
    int duration;
};

to represent the processes, any hint?

I've tried to use strtok with \n as delimiter to isolate the lines and then to use strtok with " " as delimiter inside of the while of the first strtok but obviously is not working.

CodePudding user response:

As already pointed out in the comments section, nesting of strtok is not allowed, but you can use the function fgets to get the individual lines, and then use strtok to tokenize the contents of these lines.

If you want to solve the problem only with strtok and without fgets, then this is possible, too.

On POSIX (e.g. Linux) systems, you can simply use strtok_r instead of strtok, which allows nesting.

On non-POSIX, since nesting is not allowed, you will first have to perform a sequence of strtok calls to get pointers to the start of the individual lines, and you will have to remember all of these pointers. After finishing the first sequence of strtok calls, you can then use strtok to tokenize the contents of the individual lines:

Here is an example of such a non-POSIX solution:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINES 100

int main( void )
{
    char input[] =
        "# 3 10\n"
        "P1 16 3\n"
        "P2 8  1\n"
        "P3 10 2\n";

    char *lines[MAX_LINES];
    int num_lines;
    char *p;

    //perform the first sequence of strtok
    p = strtok( input, "\n" );
    for ( num_lines = 0; p != NULL; num_lines   )
    {
        if ( num_lines == MAX_LINES )
        {
            fprintf( stderr, "Too many lines!\n" );
            exit( EXIT_FAILURE );
        }

        //remember line
        lines[num_lines] = p;

        p = strtok( NULL, "\n" );
    }

    //perform additional sequence of strtok for every line
    for ( int i = 0; i < num_lines; i   )
    {
        p = strtok( lines[i], " " );

        printf( "Line %d:\n", i   1 );

        for ( int j = 0; p != NULL ; j   )
        {
            printf( "Token #%d: %s\n", j   1, p );
            p = strtok( NULL, " " );
        }

        printf( "\n" );
    }
}

This program has the following output:

Line 1:
Token #1: #
Token #2: 3
Token #3: 10

Line 2:
Token #1: P1
Token #2: 16
Token #3: 3

Line 3:
Token #1: P2
Token #2: 8
Token #3: 1

Line 4:
Token #1: P3
Token #2: 10
Token #3: 2

How to write the individual tokens into a struct process is a completely different issue.

In order to convert the strings of the individual tokens to numbers, you can use the function strtol. Afterwards, you can write these numbers to the individual struct members.

In order to write to the name member of struct process, you can use the function strdup, if your platform already supports it. Otherwise, you will have to malloc sufficient space for the copy of the string, and then use strcpy. You could also make name point directly inside the input buffer, if that input buffer is not used for something else and the lifetime of that buffer is guaranteed to be at least as long as the lifetime of the struct process object. In that case, it is not necessary to copy the string.

  • Related