views:

55

answers:

3

For example, I have this string: SMUL 9 A B? How can I get 9 (int type) A (char) and B (char). Possible string may be SMUL 12 A C, so it means their positions in the string is not constant.

Further explanation: this is a string inputted by a user for my matrix calculator program. Inputting SMUL "scalar" "matrix-1" "matrix-2" means that the matrix operation is a SCALAR MULTIPLICATION with "scalar" as the number to be multiplied to the matrix, "matrix-1" is the matrix to be multiplied by the scalar, and "matrix-2" is the matrix where the results will be displayed. Hope you could help me. My project is now due 2 days from now.

A: 

You could tokenize your string, using functions such as strtok.

/* strtok example */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main ()
{
  char str[] ="SMUL 9 A B";
  char * pch;
  char * operation;
  int number;
  pch = strtok (str," ");
  while (pch != NULL)
  {
    if (is_operation(pch)) {
      operation = strdup(pch);
    }
    else if (is_number(pch)) {
      number = atoi(pch);
    }
    else {
      add_operand(pch);
    }
    pch = strtok (NULL, " ");
  }

  /* your processing */

  return 0;
}

Of course, in your case, you need to recognize whether the string is an operator, a number, or a matrix identifier. So at each iteration, you can test whether the string is a known operation (with strcmp, for instance), a number, (using ctype functions like isnum), or anything else.

SirDarius
+1  A: 

strtok is not reentrant and shift over empty tokens. sscanf will work and can detect number- or string-column for you.

#include <stdio.h>

typedef struct {
char op[20];
union {int arg1num;char arg1str[20];} arg1;
char arg2[20],arg3[20];
} Value;

main()
{
  Value v;
  char withNumber[]="SMUL 9 A B ";
  char withoutNumber[]="SMUL \"scalar\" \"matrix-1\" \"matrix-2\" ";

  if( 4==sscanf(withNumber,"%[^ ]%d %[^ ] %[^ ]",v.op,&v.arg1.arg1num,v.arg2,v.arg3) )
    printf("wN:%s %d %s %s\n",v.op,v.arg1.arg1num,v.arg2,v.arg3);
  if( 4==sscanf(withoutNumber,"%[^ ] %[^ 0-9] %[^ ] %[^ ]",v.op,v.arg1.arg1str,v.arg2,v.arg3) )
    printf("woN:%s %s %s %s\n",v.op,v.arg1.arg1str,v.arg2,v.arg3);
  if( 4==sscanf(withoutNumber,"%[^ ]%d %[^ ] %[^ ]",v.op,&v.arg1.arg1num,v.arg2,v.arg3) )
    printf("wN:%s %d %s %s\n",v.op,v.arg1.arg1num,v.arg2,v.arg3);
  if( 4==sscanf(withNumber,"%[^ ] %[^ 0-9] %[^ ] %[^ ]",v.op,v.arg1.arg1str,v.arg2,v.arg3) )
    printf("woN:%s %s %s %s\n",v.op,v.arg1.arg1str,v.arg2,v.arg3);
  return 0;
}
sscanf also permits a width specifier for strings (`%19[^ ]`), if you want to limit the number read (for example, 20 chars will overflow these arrays).
Brandon Horsley
+3  A: 

Sounds like you want sscanf.

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

int main(int argc, char *argv[])
{
  char buffer[1024];
  char matrix1;
  char matrix2;
  int scalar;

  /* read a line of input */
  fgets(buffer, sizeof(buffer), stdin);

  /* determine the operation */
  if (strncmp(buffer, "SMUL ", 5) == 0)
  {
    if (sscanf(buffer, "%*s %d %c %c", &scalar, &matrix1, &matrix2) != 3)
    {
      printf("Unexpected Input: %s\n", buffer);

      /* handle error */
      return EXIT_FAILURE;
    }

    /* perform multiplication */
    printf("Using scalar %d on matrices %c and %c.\n",
      scalar, matrix1, matrix2);
  }

  return EXIT_SUCCESS;
}
Brandon Horsley
strncasecmp is not C89 or C99, only POSIX.
@gordongekko, thanks, I adjusted my solution. Also, just saw you also recommended sscanf, didn't mean to copy you!
Brandon Horsley