2009-05-21 10 views
2

私は、数値を表すchar配列とその配列の数字へのポインタをとる再帰関数を書いています。関数のポイントは、++演算子のように数値をインクリメントすることです。しかし、私が数字「819」でそれを試してみると。それは '820'にインクリメントするのではなく、 '810'に変更します(最後の数字をインクリメントしますが、必要な再帰は行いません)。誰かがこれで私を助けることができますか?ありがとう。再帰インクリメンタ

#include <stdio.h> 

char* inc(char *num, char* p) 
{ 
    if(*p>='0' && *p<='8') 
    { 
     *p++; 
    } 
    else if (*p=='9') 
    { 
     *p = '0'; 
     inc(num, --p); 
    } 

    return num; 
} 

main() 
{ 
    char x[] = "819"; 

    printf("%s\n", inc(x, x+strlen(x)-1)); //pass the number and a pointer to the last digit 
} 

答えて

11

変更*p++ to (*p)++; pに含まれる数を増やしたいとします。

char* inc(char *num, char* p) 
    { 
     if(*p>='0' && *p<='8') 
     { 
      (*p)++;  //==> change 
     } 
     else if (*p=='9') 
     { 
      *p = '0'; 
      inc(num, --p); 
     } 

     return num; 
    } 

EDIT:

++オペレータは*よりも優先されています。したがって、

*p++ ==> *p then p++; // p's value before the increment. 

は、優先度テーブルhere参照します。

+0

pが実際にインクリメントされる前に* p ++が* pの値を返すと思ったのですが? –

+0

編集が間違っています。私はあなたの優先権声明が正しいことを意味するが、ポストインクリメントが声明の終わりまで延期されていることを考慮していない。 – paxdiablo

+0

私はコードビットをあまりにも分割しました。私は同じことを編集しました。 @Pax、ありがとう –

4

これは、*p++が文字を取得してから、ポインタをインクリメントするためです。あなたが次の桁アップのための余地を残してきたことを確認する必要がありますので、あなたが9XXX上記の文字列でこれを実行するには非常に注意しなければなりません

#include <stdio.h> 

char *inc (char *num, char* p) { 
    if (*p >= '0' && *p <= '8') { 
     (*p)++; 
    } else if (*p == '9') { 
     *p = '0'; 
     inc(num, --p); 
    } 
    return num; 
} 

(前:あなたは、そのポインタで文字をインクリメント(*p)++をしたいです必要に応じて0を記入してください)。予想通り

820 
9000 
0000 
aaa73 
aaa280 
aaa0000 

:中

#include <stdio.h> 

char *inc (char *num, char* p) { 
    if (p < num) 
     return num; 
    if ((*p < '0') || (*p > '9')) 
     return num; 
    if (*p < '9') { 
     (*p)++; 
     return num; 
    } 
    *p = '0'; 
    return inc(num, --p); 
} 

int main (int argc, char *argv[]) { 
    char x[] = "819"; 
    char y[] = "8999"; 
    char z[] = "9999"; 
    char a[] = "aaa72"; 
    char b[] = "aaa279"; 
    char c[] = "aaa9999"; 
    printf("%s\n", inc(x, x+strlen(x)-1)); 
    printf("%s\n", inc(y, y+strlen(y)-1)); 
    printf("%s\n", inc(z, z+strlen(z)-1)); 
    printf("%s\n", inc(a, a+strlen(a)-1)); 
    printf("%s\n", inc(b, b+strlen(b)-1)); 
    printf("%s\n", inc(c, c+strlen(c)-1)); 
    return 0; 
} 

このコードの結果:それ以外の場合は、以下のラップ機能として保護を追加します。

1

私はいつもC++でコーディングする際に正確さを達成に役立ついくつかのガイドラインに従ってください。

  • は同じ命令で 何の値を変更し、取得しないでください。 つまりinc(num, --p);は と禁止されています。これは、incの2番目の引数が でないためです。
  • ポインタを参照せずに、同じ行の で何かを実行しないでください。すなわち、 (*p)++;のすべての書式が禁止されています。
  • 常には、関数パラメータでconst-correctnessを保証します。
  • コマンド/クエリ分離:関数は一般にconstまたはvoidのいずれかである必要があります。
  • 回帰を使用しないでください。回避することはできません。つまり、必ず最初に非再帰的な代替を探します。 (この質問はあなたがそれを避けることができる例です)。
  • 契約による設計。 に前提条件を追加し、機能の末尾に の後ろに条件を追加します。

これらを関数に適用すると、バグを削除するのに役立ちます。

+0

これは安全のための良いアドバイスですが、Cを使用している人にとっては不要です。脳に問題を起こすことなく、脊髄のニューロンから優先ルールにアクセスできるようになりました。ちょうど最近私のMSDOS 2.11日からWordstar 3.3終了コマンドを忘れてしまったので、私はviコマンドを含むニューロンが私の腐っている死体から崩壊する最後のものになると思います。深刻なことに、私は反復を使わないことで激しく反対しますが、ダウンボトムには十分ではありませんが、それはしばしば最も洗練されたソリューションです。 – paxdiablo

+0

私は過激派に生まれていませんでした:)私はこのアドバイスを難しいやり方で学んだのです。おそらく、私のキャリアの中で、私が保守しなければならなかったコードは、Cを使ってきた人達によって書かれたものではなく、脳を悩ますことなく、脊髄のニューロンからアクセスすることができます。 (悪いのうちのいくつかは、彼らが何をしているかを知っていると思っていたようでしたが、実際にはそうしませんでした) –

+0

再帰は、自然で簡単な方法で多くの日常の問題を解決するために絶対に不可欠なツールです。ばかげた! –

0

オリジナルプログラムの副作用の例GCCでコンパイルされるように、(この副作用は@Paxプログラムに起こらない)

int 
main() 
{ 
char x[] = "9"; 
char z[] = {57,57,57,57}; 

int t=0; 
for(t=0;t<4;++t) 
    printf("z == %d\n",z[t]); 

inc(x, x+strlen(x)-1); 

for(t=0;t<4;++t) 
    printf("z == %d\n",z[t]); 

}

出力: Z == 57 Z == 57 Z == 57 Z == 57 Z == 48 Z == 48 Z == 48 Z == 48