0

これは単純な関数 (文字列内の一意の文字数をカウントする) のはずですが、奇妙な問題が発生しています。私のコードの使用では、ASCII 文字の az と AZ のみが想定されていることに注意してください。

int unique_chars(char* my_str) {
//printf("starting unique_chars\n");
  char seen_buffer[52]; // max 52 letters a-z & A-Z
  int seen_count = 1; // not ever expecting my_str to be NULL 
  int i, j;
  char next;
//printf("first char is %c\n", my_str[0]);
  seen_buffer[0] = my_str[0]; // first char must be unique

  for (i=1; i<strlen(my_str); i++) { // walk along the rest of my_str
    next = my_str[i];

    if (next >= 97) {
      next = next - 32; // the next char will always be capital, for convenience
    }

    for (j=0; j<seen_count; j++) { // compare next to all the unique chars seen before
//printf("current char is %c, checking against %c\n", next, seen_buffer[j]);
      if ((next==seen_buffer[j]) || (next+32==seen_buffer[j])) {
//printf("breaking\n");
        break; // jump to the next char in my_str if we find a match
      }
      if (j==seen_count-1) { // at this point, we're sure that next hasn't been seen yet
//printf("new unique char is %c\n", next);
        seen_count++;
        seen_buffer[seen_count] = next;
//printf("new char val is %c, should be %c\n", seen_buffer[seen_count], next);
        break;
      }
    }
  }
  return seen_count;
}

int main(int argc, char* argv[]){
  char* to_encode = argv[1];
  printf("unique chars: %d\n", unique_chars(to_encode));
}

特定の文字列で呼び出すと、間違った結果が得られます。たとえば、次を試してください。

./a.out gghhiijj

これにより、(printfのコメントが解除された状態で)次の結果が得られます。

starting unique_chars
first char is g
current char is G, checking against g
breaking
current char is H, checking against g
new unique char is H
new char val is H, should be H
current char is H, checking against g
current char is H, checking against 
new unique char is H
new char val is H, should be H
current char is I, checking against g
current char is I, checking against 
current char is I, checking against H
new unique char is I
new char val is I, should be I
current char is I, checking against g
current char is I, checking against 
current char is I, checking against H
current char is I, checking against H
new unique char is I
new char val is I, should be I
current char is J, checking against g
current char is J, checking against 
current char is J, checking against H
current char is J, checking against H
current char is J, checking against I
new unique char is J
new char val is J, should be J
current char is J, checking against g
current char is J, checking against 
current char is J, checking against H
current char is J, checking against H
current char is J, checking against I
current char is J, checking against I
new unique char is J
new char val is J, should be J

そのため、seen_buffer に重複が発生し続けます。そこにあるはずのアルファベット文字ではなく、空白文字がそこに格納されているからです。しかし、seen_buffer に書き込んだ直後に比較を行うと (つまり、新しい char val は %c で、%c\n である必要があります)、正しい char が表示されます!

どんな助けでも大歓迎です!

4

2 に答える 2

1

ここにオフバイワンエラーがあります:

    seen_count++;
    seen_buffer[seen_count] = next;

最初の文字が入力されseen_buffer[0]seen_count1 に設定されます。これは、2 にインクリメントされた後に次の新しい文字が入力されることを意味します。 、入力した最後の文字に対してチェックすることはありません。seen_buffer[2]seen_countseen_buffer[1]seen_buffer

これらの行を交換すると、機能するはずです。

于 2013-02-28T04:07:38.127 に答える
0

入力された値が A から Z と a から z の間にあるかどうかをチェックしていません

また、現在のコードでは char seen_buffer[52] でバッファ オーバーフローが発生する可能性があるため、コードに境界チェックを追加します

あなたのコードはとても簡単だと思います

ここにあなたのための簡単なアルゴリズムがあります

 unsigned int returnUniqueChar (const char *input)
 {
     int count[52] = {0}; // initialize all the memory with zero
     int unique = 0;

     while (*input != '\0')
     {
          if ( (input >= 'A' && input <= 'Z') 
          {
                count[input -'A']++;
          }

           else if (input >= 'a' && input <= 'z')
          {
              count[input -'a'+ 26]++;
          }
          input++;
     }

     for (int i = 0; i < 56 && (count[i] == 1) ; i++ )
            unique++;

    return unique;

 }
于 2013-02-28T03:57:51.310 に答える