2

以下の私のコードで何か奇妙なことが起こっているようです。nthtoken()のprintfのいずれかがコメント化されている場合、main()にトークンは表示されませんが、nthtoken()のprintfのいずれかがコメント化されていない場合、トークンはmainに表示されます。

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

 char *nthtoken (char *origStr, char *delimiters, int nth);

 int main (void) {

      char *str = "in principio creavit deus caelum et terram";
      char *delims = " ";

      char *tok = nthtoken (str, delims, 3);
      printf ("token: %s\n", tok);

      return (EXIT_SUCCESS);
 }

 char *nthtoken (char *origStr, char *delimiters, int nth) {

      char str[strlen (origStr)];
      strncpy (str, origStr, strlen (origStr) + 1);

      char *token = NULL;
      token = strtok (str, delimiters);
      // printf ("first token: %s\n", token);

      int i = 0;
      for (i = 0; i < nth; i++) {
           token = strtok (NULL, delimiters);
           //printf ("token inside the loop: %s\n", token); 
      }
      // printf ("token before returning to main(): %s\n", token);
      return token;
 }
4

3 に答える 3

3

これは古典的な間違いです。トークンはローカルです。それを返すと、予測できない結果が生じます。上書きされていない場合はprintfで取得できますが、保証されていないため、実行しないでください。結論として、関数の終了時にローカル変数はスコープ外になり、技術的にはコンパイラーまたは実行時に存在しなくなります。

たとえば、mallocしてトークンをコピーする(そしてmainで解放する)か、outパラメーターとして関数に渡します。

char * ret_string = malloc(MAX_SIZE); // ensure this is always sufficiently large
strcpy(ret_string, token);
return ret_string;

mainのmallocメモリを解放することを忘れないでください。

編集:スレッドセーフノート-@grhegdeが提案したように、念のために言っておきますが、strtokはスレッドセーフではありません。マルチスレッド環境を使用している場合は、別の方法を見つけることをお勧めします。

これをさらに説明するために、strtokはグローバルバッファを使用してトークンを追跡します。これは、1つの文字列がトークン化されている間は、別の文字列をトークン化するために呼び出すことができないことを意味し ます。これを行うための標準ソリューションは、strtok_r(r for re-entrant)実装は呼び出しごとにローカルバッファを使用するため、複数のスレッドから簡単に呼び出すことができます。

于 2012-11-02T05:26:51.140 に答える
1

mallocを使用して無料のオーバーヘッドを取る代わりに、この方法で作業することもできます...

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

 char *nthtoken (char *str, char *delimiters, int nth);

 int main (void) {

      char str[] = "in principio creavit deus caelum et terram";
      char *delims = " ";

      char *tok = nthtoken (str, delims, 3);
      printf ("token: %s\n", tok);

      return (EXIT_SUCCESS);
 }

 char *nthtoken (char *str, char *delimiters, int nth) {

      char *token = NULL;
      token = strtok (str, delimiters);
      // printf ("first token: %s\n", token);

      int i = 0;
      for (i = 0; i < nth; i++) {
                token = strtok (NULL, delimiters);
               //printf ("token inside the loop: %s\n", token); 
      }
      // printf ("token before returning to main(): %s\n", token);
       return token;
}
于 2012-11-02T05:58:35.313 に答える
0

これは、ダングリングポインタの問題と呼ばれます。

{
  char *token = NULL;
  ....

  return token;
} 

http://en.wikipedia.org/wiki/Dangling_pointer

于 2012-11-02T05:30:01.807 に答える