0

簡単な質問です。ここで何が間違っていましたか。このコードの目的は、入力を文字列に取得することです。入力は "12 34" で、"12" と "32" の間にスペースがあります。番号。関数 copyTemp の 2 回目の呼び出しで値 34 が生成されないのはなぜですか? 文字列インデックスを追跡する index_counter 変数があり、「スペース」文字をスキップすることを意図していますか?? 私は何を間違えましたか?

ありがとう。

#include <stdio.h>
#include <string.h>
int index_counter = 0;
int number;
void copyTemp(char *expr,char *temp);

int main(){
 char exprstn[80]; //as global?
 char tempstr[80];

 gets(exprstn);
 copyTemp(exprstn,tempstr);
 printf("Expression: %s\n",exprstn);
 printf("Temporary: %s\n",tempstr);
 printf("number is: %d\n",number);
 copyTemp(exprstn,tempstr);      //second call produces same output shouldnt it now produce 34 in the variable number?
 printf("Expression: %s\n",exprstn);
 printf("Temporary: %s\n",tempstr);
 printf("number is: %d\n",number);

 return 0;
}
void copyTemp(char *expr,char *temp){
 int i;
 for(i = index_counter; expr[i] != '\0'; i++){
  if (expr[i] == '0'){
   temp[i] = expr[i];
  }
  if (expr[i] == '1'){
   temp[i] = expr[i];
  }
  if (expr[i] == '2'){
   temp[i] = expr[i];
  }
  if (expr[i] == '3'){
   temp[i] = expr[i];
  }
  if (expr[i] == '4'){
   temp[i] = expr[i];
  }
  if (expr[i] == '5'){
   temp[i] = expr[i];
  }
  if (expr[i] == '6'){
   temp[i] = expr[i];
  }
  if (expr[i] == '7'){
   temp[i] = expr[i];
  }
  if (expr[i] == '8'){
   temp[i] = expr[i];
  }
  if (expr[i] == '9'){
   temp[i] = expr[i];
  }
  if (expr[i] == ' '){ 
   temp[i] = '\0';
   sscanf(temp,"%d",&number); 
   index_counter = i+1; //skips?
  }
 }
 // is this included here? temp[i] = '\0'; 
}
4

2 に答える 2

4

あなたのプログラムにはいくつかの問題があります:

  • exprtemp配列に同じインデックスを使用してい ます。両方が最初から機能するため、これは初めて機能しますが、数値0 を処理する場合は、配列2ndのインデックスを にリセットする必要があります。明らかに、これは単一のインデックスを使用して行うことはできません。2 つのインデックスを使用する必要があります。temp0ij
  • 342 番目の数値 ( in )の処理が完了する"12 34"までに、文字列の末尾に到達するためsscanf、2 番目の機会 (一般的には最後の機会) で実行されることはありません。したがって、for ループの後、最後の数値を抽出するために別の sscanf が必要です。また、文字列から数値を抽出して i をインクリメントしたら、関数から戻る必要があります。
  • セキュリティ上の理由から、()の使用は避け、代わりに ( gets) を使用 する必要があります。fgets
  • 次のように、数字の複数のテストを 1 つのテストに組み合わせることができます。

このようなもの。

void copyTemp(char *expr,char *temp){
    int i;
    int j = 0;
    for(i = index_counter; expr[i] != '\0'; i++){

        if (expr[i] >= '0' && expr[i]<='9'){
            temp[j++] = expr[i]; // copy the digit into temp..increment j.
        }    
        else if (expr[i] == ' '){ // space found..time to extract number.
            temp[j] = '\0'; // terminate the temp.
            sscanf(temp,"%d",&number); // extract.
            index_counter = i+1; // skip the space.
                    return; // done converting...return..must not continue.
        }
    }
    // have reached the end of the input string..and still need to extract a 
    // the last number from temp string.
    temp[j] = '\0';
    sscanf(temp,"%d",&number);
}

これらの変更後、期待どおりに動作します。

$ gcc b.c 2> /dev/null && ./a.out
12 34
Expression: 12 34
Temporary: 12
number is: 12
Expression: 12 34
Temporary: 34
number is: 34

あなたのアプローチは非常に脆弱です...ユーザーが入力番号の間に複数のスペースを指定すると、プログラムは失敗します。

于 2010-03-08T09:29:22.023 に答える
0

主な問題は、へのcopyTemp書き込みですが、 へtemp[i]の各呼び出しは 0 ではなく にcopyTemp初期化iされることです。これは、 への各呼び出しが古い内容を上書きするのではなく、既存のバッファーに追加することを意味します。したがって、常に同じ文字列を再読み取りします。入力バッファーから読み取る場所と出力バッファーに書き込む場所を追跡するには、個別のインデックスを使用する必要があります。index_countercopyTemptempsscanf

追加の問題: * 決して** 使用しないでくださいggets今までfgets代わりに使用してください。* で多くのコードを複製しcopyTempます。代わりに次のことができます。

if (expr[i] == '0' || expr[i] == '1' || ...)

またはそれ以上:

if (isdigit(expr[i]))
  • copyTemp宛先バッファがオーバーフローしないように、いくつかの予防策を講じる必要があります。(copyTemp宛先バッファを引数として取る必要さえないことに注意してください。)

  • グローバル変数の使用は避ける必要があります。copyTemp入力文字列から読み取りを開始する場所を指定する引数を取り、中断した場所のインデックスを返す場合は、より良いでしょう。

于 2010-03-08T09:30:38.290 に答える