Parsing

Hello,

I practise C parsing, I want to parse a simple FEN string and print it to the console. Here is what I have so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>



int main(int arg, char **argv)
{
	
	char fenstr[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
	char *p;
	printf ("Splitting string \"%s\" into tokens:\n",fenstr);
	p = strtok(fenstr,"/");
	while (p != NULL)
	  {
	    printf ("%s\n",p);
	    p = strtok (NULL, "/");
	  }
	 
	 return 0;
}
			


This produces the output:

Splitting string "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBGKBNR w KQkq - 0 1" into tokens:
rnbqkbnr
pppppppp
8
8
8
8
PPPPPPPP
RNBQKBNR w KQkq - 0 1


I would rather like to have 8 dashes instead of just 8, because it describes the number of dashes to be printed on the screen.
Last edited on
You need to check if the token is "8" and instead of printing the token you print 8 dashes.
1
2
3
4
5
6
7
8
while (p != NULL)
{
   if (*p == '8')
      // print your dashes
   else
      printf ("%s\n",p);
   p = strtok (NULL, "/"); 
}
Hi Thomas, my original description was a bit confusing. Fen describes a chess position, so the number of dashes can vary. What I asked was some milesteps how to do this.

Also, my fen string in not the only fen, there can be others also.
Last edited on
Do you mean that instead of 8 it can be any number between 1 and 8 ?

In this case you need to check if the token is a number with isdigit(*p) and when it is convert it to an integer and print the dashes accordingly.
Thank you Thomas, I really have trouble thinking about this, can you provide a program (to get me started with this).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <ctype.h>

int main()
{
    const char fenstr[] = "r2qrbk1/1bp2p1p/p1np1np1/1p2p3/3PP3/1BP2NN1/PP3PPP/R1BQR1K1 w - - 2 13";
    printf ("FEN: \"%s\"\n\n\n ", fenstr );

    const char *p = fenstr ;
    for(  ; *p != ' ' ; ++p )
    {
        const char ch = *p ;

        if( isdigit(ch) ) for( int i = 0 ; i < ( ch - '0' ) ; ++i ) printf( " %c", '-' ) ;
        else if( ch == '/' ) printf( "\n\n ") ;
        else printf( " %c", ch ) ;
    }

    printf( "\n\n\n%s\n", p+1 ) ;
}

http://coliru.stacked-crooked.com/a/fb7ed89d5933d63f
Last edited on
Here you go:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int main(int arg, char **argv)
{
  char fenstr[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
  char *p;
  printf ("Splitting string \"%s\" into tokens:\n",fenstr);
  p = strtok(fenstr,"/");
  while (p != NULL)
  {
    if (isdigit(*p))
    {
      int num = *p - '0';
      for (int i = 0; i < num; i++)
      {
         printf("-"); 
      }
      printf("\n");
    }
    else
    {
      printf ("%s\n",p);
    }
    p = strtok (NULL, "/");
  }

  system("pause");

  return 0;
}


Output:
Splitting string "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" into
tokens:
rnbqkbnr
pppppppp
--------
--------
--------
--------
PPPPPPPP
RNBQKBNR w KQkq - 0 1
Thank you... Thomas1965: I tried your program and it revealed a bug...
What if the fen string is
rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2 ?
I don't know yet where the problem is, but I will keep noticing if I find any.
What if the fen string is
rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2 ?


Of course it won't work then. You wanted a single digit replaced with dashes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <ctype.h>

int main()
{
    const char fenstr[] = "r1b1k2r/ppq1ppbp/2n3p1/2p5/2BPP3/2P1BN2/P4PPP/2RQK2R b Kkq - 5 10";
    printf ("FEN: \"%s\"\n\n\n ", fenstr );

    {
        int num_spaces = 0 ;
        int num_rows = 1 ;
        for( const char *p = fenstr ; *p != 0 ; ++p )
            if( *p == ' ' ) ++num_spaces ; else if ( *p == '/' ) ++num_rows ;

        if( num_spaces != 5 || num_rows != 8 ) return fprintf( stderr, "invalid FEN\n" ), 1 ;
    }

    const char *p = fenstr ;
    for(  ; *p != ' ' ; ++p )
    {
        const char ch = *p ;

        if( isdigit(ch) ) for( int i = 0 ; i < ( ch - '0' ) ; ++i ) printf( " %c", '-' ) ;
        else if( ch == '/' ) printf( "\n\n ") ;
        else printf( " %c", ch ) ;
    }

    const char next = tolower(*++p) ;
    printf( "\n\n\nnext move: %s\ncastling availability: ", next == 'w' ? "white" : "black"  ) ;
    for( p+= 2 ; *p != ' ' ; ++p ) putchar(*p) ;

    printf( "\nen passant: " ) ; for( ++p ; *p != ' ' ; ++p ) putchar(*p) ;
    printf( "\nhalf-moves since last pawn move/capture: " ) ; for( ++p ; *p != ' ' ; ++p ) putchar(*p) ;
    printf( "\n(full) move number: %s\n", ++p ) ;
}

> clang -std=c99 -O3 -Wall -Wextra -pedantic-errors -x c main.cpp && ./a.out

FEN: "r1b1k2r/ppq1ppbp/2n3p1/2p5/2BPP3/2P1BN2/P4PPP/2RQK2R b Kkq - 5 10"


  r - b - k - - r

  p p q - p p b p

  - - n - - - p -

  - - p - - - - -

  - - B P P - - -

  - - P - B N - -

  P - - - - P P P

  - - R Q K - - R


next move: black
castling availability: Kkq
en passant: -
half-moves since last pawn move/capture: 5
(full) move number: 10

http://coliru.stacked-crooked.com/a/5999cd03c92abc95
Hi JLBorges, I took some idea of your previous post and came up with this, I think this should be sufficient for me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

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

int main(int arg, char **argv)
{
  int i, j;
  char fenstr[] = "r1b1k2r/ppq1ppbp/2n3p1/2p5/2BPP3/2P1BN2/P4PPP/2RQK2R b Kkq - 5 10";
  char *p = fenstr;
  
  for(  ; *p != ' ' ; ++p )
  
  {
    if (isdigit(*p))
    {
      int num = *p - '0';
      for (j = 0; j < num; j++)
      {
         printf("-"); 
		 
      }
      
    }
    else if (*p == '/')
    {
      printf ("\n");
    }	
	
	else  printf("%c", *p);
		
  }
  
  printf("\n\n");
  
  return 0;
}


Output on console:

r-b-k--r
ppq-ppbp
--n---p-
--p-----
--BPP---
--P-BN--
P----PPP
--RQK--R

Now it is more like what I want, but I don't still understand line 12.
Last edited on
> don't still understand line 12.

Come on! It's a classical for loop, straight and simple. for( ; *p != ' ' ; ++p )

Initialisation: none (p was already initialised to point to the first character in fenstr)

Condition: *p !- ' ' => carry on with the iteration till we hit encounter a space

Increment: ++p => at the end of each iteration, increment p (make it point to the next character in fenstr
Topic archived. No new replies allowed.