1

I am processing a string in which each word is separated by spaces. The < indicates it is a input redirection, and > indicates it is a output redirection. Ex:

< Hello > World

I want to save the words in different variables (char *in, char *out ) How can I do that? I've looked through the string library and none seems to be able to do the job.

Here's what I have so far concerning this question.

char buff[MAXARGS];
char *str;
char *in;
char *out;

if( strchr(buff, '<') != NULL )
{
  str = strchr(buff, '<');
  str++;
  if( *str == ' ' || *str == '\0' || *str == '\n'  || *str == '\t' )
  {
     fprintf( stdout, "User did not specify file name!\n" );
  }
  else
      in =  str; // This will save Hello > World all together. I don't want that. 
}

Thanks much.

Dino55
  • 431
  • 3
  • 5
  • 13
  • What are you **really** trying to do? If it's "parse the command line", then handling input and output redirection is already done for you by the shell process. If you're trying to read and parse a shell script, or something like that, then C is probably about the worst possible choice of implementation language. – Karl Knechtel Sep 29 '11 at 06:17
  • Thank you for the reply! Yes, I am writing a simplified shell program and this is part of my parse.c Really? I must have done something wrong then.. because my program would carry out all other commands (Ex: ls, exit, cat) perfectly except input, output redirection and backgrounding. Thus, I made extra functions just to handle these three. – Dino55 Sep 29 '11 at 07:14
  • @Karl but the fastest... – YAHOOOOO Sep 29 '11 at 07:15
  • Wait, you're trying to **implement a shell**? What on earth for? – Karl Knechtel Sep 29 '11 at 23:59

4 Answers4

0

u can use this..

char filename[max_path]
 str1 = strchr(buff, '<');
 str2 = strchr(buff, '>');

 memcpy( filename , str1+1 , str2-str1-1 ); 

so the path between < and > will be in filename.

and

 output = str2 + 1;
YAHOOOOO
  • 939
  • 4
  • 19
  • 27
  • Thank you for the reply :) But, the string will be inputted by the user so there's no way to guarantee that the string they inputted will look like my example.. – Dino55 Sep 29 '11 at 05:29
0

supposing your input patter is fixed as < input_name > output_name and you want to be able to extract input_name and output_name respectively.

One solution is to split the str using " <>". Following code will print out Hello , World consecutively. Saving them to in and out is left for you as an exercise :)

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

int main ()
{
  char str[] ="< Hello > World";
  char *in;
  char *out;
  char *pch;
  char *del=" <>";
  pch = strtok (str,del);
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, del);
  }
  return 0;
}
pierrotlefou
  • 39,805
  • 37
  • 135
  • 175
  • what if the input patter is not fixed? I was thinking to check while str not pointing to a white space, copy the char to char array. Maybe use a for loop to let it increase by index. But I cannot find a function that will copy char one at a time? Thank you! – Dino55 Sep 29 '11 at 05:45
0

To get you started, here's how you could do it assuming you are allowed to modify buff, and assuming a simple case (at most one < and at most one >).

First, get the position of the < and >

in  = strchr(buff, '<');
out = strchr(buff, '>');

Then you artificially split the string:

if (in) {
  *in = 0;
  in++;
}
if (out) {
  *out = 0;
  out++;
}

At this point, buff points to a C-terminated string that has no < or >. in is either null, or points to a string that follows < and contains no >. Same for out.

Then you need to "strip" all these strings (remove whitespace), and check that after that they still contain meaningful data.

You'll need a whole lot more logic to get all the cases right, including rejecting invalid input.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • Thank you for the reply! However, I am not sure why you set in/out to 0? (*in = 0; and *out = 0;) – Dino55 Sep 29 '11 at 05:51
  • That replaces `<` with a 0 char, which terminates the string before. Say if `buff` was `hellooutput\0`, after that it will be `hello\0input\0output\0`. So if you use string functions on `buff`, it will look as if it only contains `hello`. `in++` will be the C-string `input`. – Mat Sep 29 '11 at 05:55
0

You need to decide where the storage for the two filenames is allocated, and how you will know how much storage is provided.

static void find_filename(const char *str, char *name)
{
    char c;
    while ((c = *str++) != '\0' && isspace((unsigned char)c))
        ;
    if (c != '\0')
    {
        *name++ = c;
        while ((c = *str++) != '\0' && !isspace((unsigned char)c))
            *name++ = c;
    }
}

int find_io_redirection(const char *str, char *in, char *out)
{
    const char *lt = strchr(str, '<');
    const char *gt = strchr(str, '>');
    if (lt != 0)
        find_filename(lt+1, in);
    if (gt != 0)
        find_filename(gt+1, out);
    return(lt != 0 && gt != 0);
}

This code simply assumes that you provide big enough strings for in and out. If you want to be safer, then you tell the function(s) how big each target string is. You can compress that code. You might decide you want to return the number of redirections. You might decide you should know about double output redirections, or double input redirections. You might decide you should return a bit mask indicating which redirections were present. With a considerably more complex interface, you might be able to indicate which parts of the input line represented the I/O redirection; this would help in the calling function to decide which parts of the line should now be ignored.

You'd use the code above like this:

char buffer[MAXCMDLEN];
char in[MAXFILENAMELEN];
char out[MAXFILENAMELEN];

if (fgets(buffer, sizeof(buffer), stdin) != 0)
{
    if (find_io_redirection(buffer, in, out))
        ...process buffer know that I/O redirection is present...
    else
        ...witter about missing I/O redirection...
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • wow! thank you much for the reply! I never knew there's a built in function called isspace() ! That should come in handy :) I'll have to try your ways when I get home. – Dino55 Sep 29 '11 at 17:46
  • `isspace()` is a macro/function from ``. Compare with the `isblank()` function too - they accept different sets of characters. You might decide that `isblank()` is better than `isspace()`. – Jonathan Leffler Sep 29 '11 at 18:09