C读取字符串并动态接受括号

时间:2016-12-16 12:27:25

标签: c arrays dynamic brackets

我已经阅读了一串括号来分析它。 如何读取要插入动态生成的数组中的字符串?

除了使用scanf的括号外,如何避免读取所有字符? [] {}()

谢谢。

编辑: 我必须从键盘上读一系列括号,但我不知道它的长度。所以我创建了一个动态生成的数组(这是一个要求),只包含括号的空格。 虽然我在阅读时想要只接受括号并避免使用其他所有字符,但这与scanf和正则表达式有可能吗?

3 个答案:

答案 0 :(得分:1)

只需使用if条件检查所有括号即可。假设ch是否是包含输入字符串的数组:

if(ch[0]=='[' || ch[0]==']'||...){
// process the bracket and do same for all other ch indeces.
}

答案 1 :(得分:0)

  

除了使用scanf的括号外,如何避免读取所有字符? [] {}()

代码不能。在某种程度上,代码正在读取用户类型的任何内容,包括[ ] { } ( )和不包含的字符。最好是代码读取输入然后选择性操作它,即使这意味着读取和抛掷数据。在任何情况下,OP当然也希望阅读'\n'以了解何时停止。

使用fgets()最适合用户输入@Michael Walz,但OP reports必须使用scanf()

scanf()有一个扫描集说明符,只允许读取选定的字符,而其他字符则保留在stdin中。 扫描集"%[...]"...为所需字符。如果希望]成为扫描集的一部分,那么它应该是第一个。

由于未指明输入长度的上限,因此代码可以危险地,只需根据需要重新分配内存,以便通过一次读取1个字符来容纳用户输入。

以下是一些不能实现目标的高效代码:

char *bracket_read(void) {
  size_t brackets_length = 0;
  // Allocate +2, 1 for the null character and 1 for the potential next character
  char *brackets = malloc(brackets_length + 2);
  assert(brackets);
  brackets[brackets_length] = '\0';

  char non_bracket = 0;
  while (non_bracket != '\n') {
    #define SCAN_SET "][(){}"
    int cnt = scanf("%1[" SCAN_SET "]", &brackets[brackets_length]);
    if (cnt == 1) {
      brackets_length++;
      char *t = realloc(brackets, brackets_length + 2);
      assert(t);
      brackets = t;
    } else {
      // Quietly consume other characters
      if (scanf("%c", &non_bracket) == EOF) {
        if (brackets_length == 0) {
          free(brackets);
          return NULL;
        }
        non_bracket = '\n';
      }
    }
  }
  return brackets;
}

int main() {
  char *s;
  while ((s = bracket_read()) != NULL) {
    printf(".%s.\n", s);
    fflush(stdout);
    free(s);
  }
}

答案 2 :(得分:0)

因此,我假设你的简介是从输入文本中删除括号字符并存储它们以供以后分析。假设这是正确的,这是您可能觉得有用的一遍:

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

/**
 * Input buffer size
 */
#define BUFSIZE 20

/**
 * Extends the target buffer by doubling its size.
 * If the realloc call fails, the original buffer
 * is left intact.
 */
int extend( char **buffer, size_t *bufferSize )
{
  char *tmp = realloc( *buffer, *bufferSize * 2 );
  if ( tmp )
  {
    *buffer = tmp;
    *bufferSize *= 2;
  }

  return tmp != NULL;
}

int main( void )
{
  /**
   * Fixed buffer for reading from input stream
   */
  char inputBuffer[BUFSIZE+1] = {0};
  /**
   * Dynamically allocated target buffer that can be extended as necessary
   */
  char *targetBuffer = NULL;
  size_t targetBufferSize = sizeof *targetBuffer * sizeof inputBuffer;
  size_t targetBufferPos = 0;
  int done = 0;
  char fmt[20] = {0};

  /**
   * Allocate the target buffer, which is initially the same size as the input buffer.
   */
  if ( !(targetBuffer = malloc( targetBufferSize )) )
  {
    fprintf( stderr, "FATAL: could not allocate memory for targetBuffer\n" );
    exit( EXIT_FAILURE );
  }

  /**
   * Create our input format string.  Since we're using the [ conversion
   * specficier, we need to also specify the max size we want to read at
   * one time using the field width specifier.  Unfortunately, you can't
   * pass the field width as an argument in scanf the way you can with
   * printf, so we have to create the format string and save it to its
   * own buffer.  When we're done, it will be "%20[^\n]%c".  
   */
  sprintf( fmt, "%%%zu[^\n]%%c", sizeof inputBuffer - 1 );

  while ( !done )
  {
    char follow;

    /**
     * Read BUFIZE characters plus a "follow" character.  If the "follow" character
     * is a newline, then we've read the complete input line and don't need
     * to loop again.  Otherwise, push the "follow" character back onto the input
     * stream for the next read.
     */
     if ( scanf( fmt, inputBuffer, &follow ) < 1 )
     {
       fprintf( stderr, "FATAL: error on read\n" );
       free( targetBuffer );
       exit( EXIT_FAILURE );
     }

     if ( follow == '\n' )
       done = 1;
     else
       ungetc( (int) follow, stdin );

     /**
      * Walk down our input buffer; if the next character is one of '[', ']', '{' , '}',
      * '(', or ')', append it to the target buffer.
      */
     char *p = inputBuffer;
     while ( *p )
     {
       if ( *p == '[' || *p == ']' || *p == '{' || *p == '}' || *p == '(' || *p == ')' )
       {
         /**
          * Before we append a character to the target buffer, we first need to make
          * sure there's room left (targetBufPos < targetBufSize).  If there isn't
          * any room left, we need to extend the target buffer before appending to it.
          *
          * We're taking advantage of the short-circuit nature of the || operator. Remember
          * that given the expression a || b, if a evaluates to true, then the whole
          * expression evaluates to true regardless of the value of b, so b isn't
          * evaluated at all.
          *
          * If targetBufferPos < targetBufferSize evaluates to true (non-zero), then
          * the extend function isn't called; we simply append to the target buffer.
          *
          * If targetBufferPos < targetBufferSize is *not* true, then the extend
          * function is called.  If extend returns true (non-zero), then the operation
          * succeeded and we append to the now-lengthened target buffer.  If extend
          * returns false (zero), then the operation failed and we bail out with an error.
          */
         if ( targetBufferPos < targetBufferSize || extend( &targetBuffer,  &targetBufferSize ) )
         {
           targetBuffer[targetBufferPos++] = *p;
         }
         else
         { 
           fprintf( stderr, "FATAL: could not extend memory for  targetBuffer\n" );
           free( targetBuffer );
           exit( EXIT_FAILURE );
         }
       }
       p++;
     }
   } 
   /**
    * We're treating targetBuffer as a string, so we need to add
    * the 0 terminator to the end.  Again, we first need to make
    * sure there's room in the buffer, and if not, to extend it.
    *
    * Yes, there's a corner case here where you're doubling the buffer
    * size to add one more character.  I'm not going to worry about it
    * here, but it's easy enough to fix.  
    */
   if ( targetBufferPos < targetBufferSize || extend( &targetBuffer,  &targetBufferSize ) )
   {
     targetBuffer[targetBufferPos++] = 0;
   }
   else
   {
     fprintf( stderr, "FATAL: could not extend memory for targetBuffer\n" );
     free( targetBuffer );
     exit( EXIT_FAILURE );
   }

   printf( "Found the following bracket characters in the input string: %s\n", targetBuffer );
   free( targetBuffer );
   return EXIT_SUCCESS;
 }

示例运行:

$ ./scanner
(((This))) [[[[is]]]] {a} (T)[e]{s}[t]
Found the following bracket characters in the input string: ((()))[[[[]]]]{}()[]{}[]