2017-11-12 13 views
-2

私は学校向けのプロジェクトに取り組んでおり、このコード構造を正しく理解して動作させる必要があります。 問題:ランダムなチャンクのメモリデータを取得せずに、ユニオンメンバー(hとs)に正しくアクセスする必要があります。実際に保存した番号を返す必要があります。私は組合がどのように働くのか理解しています。なぜ私のコードが私にそこに格納された番号ではなくランダムなデータを与えているのか混乱しています。 注::私はこの問題に対する他の答えを探しましたが(これはかなり一般的な構文問題のように聞こえました)、他の解決策は私の状況にはまったく適合しませんでした。あなたがで以来、チャンクを取得しているC++ - ネストされた構造体を正しくユニオンにアクセスする

#include <iostream> 
#include <string> 
#include <iomanip> 
using namespace std; 

struct worker { 
    enum kind {NOTSALARIED, ISSALRIED}; 
    bool isSalaried; 

    union { 
     struct hourly{ 
      double numberHours; 
      double hourlyRate; 
     } h; // end of 'hourly' struct 
     struct salaried{ 
      double salaryAmount; 
      double bonusAmount; 
     } s; // end of 'salaried' struct 
    } info; // end of 'info' union 
}; 

/// PROTOTYPE section 
worker* getHourly(); 
worker* getSalaried(); 
void printWorker(worker); 

int main() { 
    worker *theWorker; // avoids making another 'worker' object for no reason 

    // format code for 'double' values 
    cout << fixed << showpoint << setprecision(2); 

    // used string so avoid user entering name with the correct first character 
    string choice; 
    cout << "(H)ourly or (S)alary? "; 
    getline(cin, choice); 

    /// LOGIC SECTION: Checks what the user entered 
    if(choice == "H" || choice == "h") { 
     // get the salary 
     theWorker = getHourly(); 
     // pass in the dereferenced pointer to print out the info 
     printWorker(*theWorker); 
    } 
    if(choice == "S" || choice == "s") { 
     // get the salary 
     theWorker = getSalaried(); 
     // pass in the dereferenced pointer to print out the info 
     printWorker(*theWorker); 
    } 

    return 0; 
} 

// method that gets the information -- creates a new worker object --  returns a pointer to the object 
worker* getHourly() { 
    worker newWorker; 

    // set the isSalaried equal to false 
    newWorker.isSalaried = worker::NOTSALARIED; // equals 0 -- FALSE 

    cout << "Enter the number of hours worked: "; 
    // take in the hours worked 
    cin >> newWorker.info.h.numberHours; 

    cout << "Enter the hourly pay rate: "; 
    // take in the hourly rate 
    cin >> newWorker.info.h.hourlyRate; 

    return &newWorker; 
} 

worker* getSalaried() { 
    worker newWorker; 

    // set the kind equal to SALARIED 
    newWorker.isSalaried = worker::ISSALARIED; // equals 1 -- TRUE 

    cout << "Enter the salary amount: "; 
    // take in the salary 
    cin >> newWorker.info.s.salaryAmount; 

    cout << "Enter the bonus amount: "; 
    // take in the bonus 
    cin >> newWorker.info.s.bonusAmount; 

    return &newWorker; 
} 

void printWorker(worker theWorker) { 
    double grossPay; 

    // take care of the SALARIED first 
    if (theWorker.isSalaried) { 
     // add the salary to the bonus amount 
     grossPay = (theWorker.info.s.salaryAmount + theWorker.info.s.bonusAmount); 

     // print out the info 
     cout << "Salaried Worker" << endl; 
     // print out the salary 
     cout << "Salary: $" << theWorker.info.s.salaryAmount << endl; 
     // print out the bonus 
     cout << "Bonus: $" << theWorker.info.s.bonusAmount << endl; 
    } 
    // now, take care of the HOURLY 
    if (!(theWorker.isSalaried)) { 
     // get the product of the number of hours worked and the hourly rate 
     grossPay = (theWorker.info.h.numberHours * theWorker.info.h.hourlyRate); 

     // print out the info 
     cout << "Hourly Worker" << endl; 
     // print out the number of hours worked 
     cout << "\tHours: " << theWorker.info.h.numberHours << endl; 
     // print out the rate 
     cout << "\tRate: $" << theWorker.info.h.hourlyRate << endl; 
    } 

    // print out the last portion here, since this code will be executed for both 
    cout << "\t--------" << endl; 
    cout << "\tGross Pay: $" << grossPay << endl; 
} 
+0

'リターン&newWorker;' - あなたはローカル変数 – RbMm

+1

のアドレスを返すなぜタグCをしましたか? – kabanus

+0

Cのプログラマーがこの状況でも助けてくれるので、私はCにタグを付けました。組合と構造体は両方ともC言語であるため。構造体は間違いありませんが、Cプログラマは依然として手助けをすることができます。 – Nik

答えて

0

私はコードブロックで上記のコードを試してみましたが、動作しますが、このコードは毎回実行するのが安全ではないと確信しています。 問題の理由がある:あなたの2機能を使用すると、労働者からのローカル変数を作成し、これらの2機能で

worker* getHourly() 
{ 
    worker newWorker; 
     ... 
     return &newWorker; 
} 

worker* getSalaried() { 
    worker newWorker; 
    ... 
    return &newWorker; 
} 

、あなたがメインで、呼び出し元にそのアドレスが返されました。 ローカル変数がメモリから削除されているので、関数が終了した後、メインのポインタ "theWorker"があなたに属していないメモリにアドレスを保持します。 次の2つの解決策の一つ確認する必要があります:、 最初のものをそのままの機能を維持しますが、機能には、代わりに変数のポインタを定義し、次のようにダイナミックアロケーションとしてそれを割り当てる:

worker* getHourly() 
{ 
    worker* newWorker; 
    newWorker = new (worker)   
    ... 
     return newWorker; 
} 

worker* getSalaried() { 
    worker* newWorker; 
    newWorker = new (worker); 
    ... 
    return &newWorker; 
} 

第二1:2の機能は、次のように変数の代わりのアドレスを返してみましょう:

worker getHourly() 
{ 
    worker newWorker; 
    ... 
     return newWorker; 
} 

worker getSalaried() { 
    worker newWorker; 
    ... 
    return &newWorker; 
} 
1

...

worker* getSalaried() { 
    worker newWorker; 
    ... 
    return &newWorker; 
} 

は、ローカル変数のアドレスを返します。そのため、生涯がgetSalariedに終わったら、newWorkerの生涯は終了し、生涯が終わった後にオブジェクトにアクセスすることは未定義の動作です(例えば、 "チャンク"を提供する)。これを克服するには、workerの構造体(ポインタではなく)を返すか、workerのインスタンスを関数に渡して、関数に直接書き込むことができます。

0

答えのコメントを具体的に示すために、実際にコンパイラが何を言いたいのかを実際に読むことをお勧めします。例:

bla.cpp:57:12: warning: address of local variable ‘newWorker’ returned [-Wreturn-local-addr] 
worker newWorker; 

これが表示されない場合は、警告フラグをオンにする必要があります。関連のない別のエラー:

bla.cpp:77:28: error: ‘ISSALARIED’ is not a member of ‘worker’ 
newWorker.isSalaried = worker::ISSALARIED; // equals 1 -- TRUE 

これはタイプミスです。あなたがする必要があるのは、値で物を渡すか、構造体がコピーされるか、動的メモリを処理することです。値(structをコピー)または例で戻るには:

worker getSalaried() { 
    worker newWorker; 

    // set the kind equal to SALARIED 
    newWorker.isSalaried = worker::ISSALARIED; // equals 1 -- TRUE 

    cout << "Enter the salary amount: "; 
    // take in the salary 
    cin >> newWorker.info.s.salaryAmount; 

    cout << "Enter the bonus amount: "; 
    // take in the bonus 
    cin >> newWorker.info.s.bonusAmount; 

    return newWorker; 
} 

あなたがオブジェクト指向プログラミングを開始している場合、私はわからないんだけど、彼らはあなたの労働者の単一コンストラクタでなければなりませんように2つのget機能は見て、パブリックメソッドを印刷します。この方法では、おそらくこれを全く扱わないでください。

+0

"flak"について - SO上のコミュニティは、情報の追加方法について非常に厳格です。タグは将来の読者のための質問であり、おそらくあなたを助けることができる人すべてを対象とするものではありません。そのロジックを使って、Python、Java、R、Prologなどを追加することができます。これを犯してはいけません.SO編集の観点から考えると、あなたの次の質問を学びましょう。 – kabanus

+0

有用なコメントありがとうございます!私は仕様に従っているので、実際にはこのようにしています。私はこのプロジェクトのために特定の仕様に従わなくても間違いなくそれを行うだろう。 – Nik

+0

私は多くを推測しました。これは値によって小さな 'struct 'なので、おそらく最も良いでしょう。しかし、コンパイラの警告を取り除いてみてください。それはもっとうまくいっていますが、 '-Werror'を使うと、長期的にあなたを救うことができます! – kabanus

関連する問題