Close

Tokenising the StdOut String

A project log for Using Zenity for GUI Command Line Programs (in C)

I need a very simple GUI for my command line programs. Pipes and Zenity provide a reasonable solution.

agpcooperagp.cooper 02/15/2022 at 10:330 Comments

Tokenising the StdOut String

I first tried strtok() but it skips consecutive delimiters:

  char* token;
  // Get the first token
  n=0;
  token=strtok(line,",");
  while (token!=NULL) {
    printf("%d %s\n",++n,token);
    token=strtok(NULL,",");
  }

So I wrote my own:

// Tokenise Line
// Note: Returns NULL or Space for absent data)
// Note: A new array is created each time this function is called
char** tokenise(char* line,int n)
{
  char** str=calloc(n,sizeof(char**));
  int ptr=0;
  // Remove non-characters
  for (int i=0;(line[i]>0);i++) if (line[i]<32) line[i]=0;
  char* token=line;
  for (int i=0;(line[i]>=32);i++) if (line[i]==',') {
    line[i]=0;
    *(str+ptr++)=token;
    token=&line[i+1];
  }
  *(str+ptr++)=token;

  return str;
}

Now you just need to create you own parameter types from the strings.

Here is the complete listing:

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

char** zenity(char* cmd,int n)
{
  // create string array
  char** str=calloc(n+1,sizeof(char**));
  for (int i=0;i<=n;i++) *(str+i)=(char*)calloc(256,sizeof(char));
  char line[256]={0};

  // Run Zenity
    FILE* fp=popen(cmd,"r");
  if (fp==NULL) {
    // Error
    perror("Pipe returned a error");
    for (int i=0;i<=n;i++) free(*(str+i));
    free(str);
    return NULL;
  } else {
    fgets(line,sizeof(line),fp);
       sprintf(*str,"%d",WEXITSTATUS(pclose(fp)));
  }

  // Remove non-characters
  for (int i=0;(line[i]>0);i++) if (line[i]<32) line[i]=0;
  int ptr=1;
  char* token=line;
  for (int i=0;(line[i]>=32);i++) if (line[i]==',') {
    line[i]=0;
    strcpy(*(str+ptr),token);
    ptr++;
    token=&line[i+1];
  }
  strcpy(*(str+ptr),token);

  return str;
}

int main(int argc, char *argv[])
{
    char** list=NULL;

  list=zenity("zenity --forms \
      --title='Add Member' \
      --text='Member information' \
      --separator=',' \
      --add-entry='First Name' \
      --add-entry='Family Name' \
      --add-entry='Email' \
    --add-combo='Sex' --combo-values='Male|Female' \
      --add-calendar='Birthday' \
      --add-list='Program' \
      --list-values='Expert|Intermediate|Beginner' \
    ",6);
  if (list!=NULL) {
    for (int i=0;i<=6;i++) printf("%d %s\n",i,*(list+i));
    for (int i=0;i<=6;i++) free(*(list+i));
    free(list);
  }
  return 0;
}

So that is it, AlanX

Discussions