2016-12-16 2 views
0

これを分析するには、大括弧で囲んだ文字列を読む必要があります。 動的に生成される配列に挿入する文字列を読み取るにはどうすればよいですか?Cの文字列を読み込み、ブラケットだけを動的に受け入れる

scanfを使用して角括弧以外のすべての文字を読み取ることを避けるにはどうすればよいですか? [] {}()

ありがとうございます。

編集: キーボードから一連の角括弧を読み取る必要がありますが、長さはわかりません。だから私は動的に生成された配列を作成しなければなりません(これは要件です)、大括弧のスペースだけを含んでいます。 私が読んでいる間、角括弧のみを受け入れ、他のすべての文字を避けたいのですが、これは正規表現でscanfで可能でしょうか?

+1

は 'scanf'が、' fgets'を使用しないでください。 –

+0

なぜですか? fgetsは動的に配列を生成するのに役立ちますか? –

+0

私はファイルを使用しません。 –

答えて

1

ifの条件を使用してすべての角括弧をチェックしてください。私はscanf関数を使用してブラケットを除いて読んでからのすべての文字を避けることができますどのように

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

私はこのメソッドを避け、scanfで正規表現を使用したいと思います...可能でしょうか? –

+0

@ user3122577あなたの質問に_regex_は言及していませんでした。 –

+0

私は正しいです、私は質問を修正しました。ごめんなさい。 –

0

chが配列その後、入力文字列を保持している場合と仮定? [] {}()

コードできません。あるレベルでは、コードは[ ] { } ()などのユーザーの種類を問わず読み込みます。コードが入力を読み取るのが最善で、データを読み込んで投げることを意味するとしても、選択性はその上で動作します。いずれにしても、OPはいつでもいつ終了するかを知るために'\n'を読むことを望んでいます。

fgets()を使用するのは、ユーザー入力@Michael Walzに最適ですが、OP reportsscanf()でなければなりません。

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); 
    } 
} 
0

だから、私はあなたの簡単な入力テキストからブラケットの文字を削除し、後で分析するためにそれらを格納することであると仮定しています。それが正しいだと仮定すると、ここにあなたが有用見つけることができる1つのパスです:

#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: ((()))[[[[]]]]{}()[]{}[] 
関連する問題