2016-05-06 84 views
0

同様のエラーを処理するスレッドをいくつか見てきましたが、遭遇した(「私はそれらを理解するにはグリーンすぎる」というコード)。タイプ "char *"の値を使用して "char"タイプのエンティティを初期化することはできません

#include <iostream> 
    #include <array> 
    #include <sstream> 
    using namespace std; 

    struct StudentRecord 
    { 
     char name[20]; 
     int id; 
     float gpa; 
    }; 

    int main() 
    { 
     cout << "Enter your name:" << endl; 
     char nameInput[20]; 
     cin >> nameInput; 

     cout << "Enter your student ID:" << endl; 
     int idInput; 
     cin >> idInput; 

     cout << "Enter your GPA:" << endl; 
     float gpaInput; 
     cin >> gpaInput; 

     StudentRecord TESCStudent = 
     { { nameInput }, idInput, gpaInput }; // TROUBLE STARTS HERE 

    cout << "Name: " << TESCStudent.name << "\nID: " << TESCStudent.id << "\nGPA: " 
     << TESCStudent.gpa << endl; 
} 

StudentRecord TESCStudent = {...}初期化は、次のエラーを与える: エラーC2440: '初期化する':タイプの値: '文字' のIntelliSenseに 'CHAR [20]' から変換することはできませんが"char *"を使って "char"型のエンティティを初期化することはできません

文字列は多くの問題を解決すると思いますが、このプロジェクトでは20文字の配列として名前を取得するように求めました。

これは私の初めての構造体を使用しているので、意味がない恐ろしいことをしているかもしれません。

StudentRecord TESCStudent = 
     { { *nameInput }, idInput, gpaInput }; 

修正問題:

答えて

1

あなたは書いている:基本的に

StudentRecord TESCStudent = { { nameInput }, idInput, gpaInput };

:あなたはそれを行うことはできません。 Cスタイルの配列は直感的ではない構文と意味を持ちます。別のCスタイルの配列を使ってCスタイルの配列の要素を初期化する方法はありません。

私の助言は、それらをまったく使用しないことです。名前配列の代わりにstd::stringを使用した場合は、単にStudentRecord TESCStudent = { nameInput , idInput, gpaInput };と書くことができます。また、人が長さ20文字以上の名前を入力すると、コードによってバッファオーバーフローが発生するという問題も修正されます。

StudentRecord TESCStudent = {}; 

cout << "Enter your name:" << endl; 
cin >> setw(sizeof(TESCStudent.name)) >> TESCStudent.name; 

cout << "Enter your student ID:" << endl; 
cin >> TESCStudent.id; 

cout << "Enter your GPA:" << endl; 
cin >> TESCStudent.gpa; 

if (!cin) 
{ 
    cout << "Invalid input, sorry.\n"; 
    return EXIT_FAILURE; 
} 
+0

あなたのコードが入力を20文字に制限する方法は100%明確ではありません。あなたはそれについて詳述できますか?また、私はアレイを使用することを余儀なくされましたが、私はあなたがアレイに直接読み込む方法に興味があります、私は将来それを試みます! –

+0

@KeeperofSecrets 'setw'は、次の読み取りの最大サイズを設定します(文字配列の場合はnull終了を含む)。 –

+0

Cool。これは素晴らしいソリューションであり、私が使用したforループよりもはるかに洗練されてエレガントです。 –

-1

に問題のある行を変更します。

文字列について覚えておくべきことは、文字列自体が配列であることです。 あなたの例では、 "nameInput"それ自体はchar値を保持しません、実際には最初のchar値へのポインタを保持します。 (値を保持する)変数と(値を保持する場所を指し示すアドレスポインタである)ポインタを区別

文字列と(INTとフロートのような)他のリテラル値の差の重要な部分である

アスタリスクでnameInput(ポインタ)をあらかじめ固定することによって、ポインティングする値が必要であることが示されます。

+0

:あなたはやがて要件その後、私は例えば、配列に直接読み込むことで問題を回避し、オーバーフロー保護およびエラーチェックを追加することをお勧めしたいのchar配列に固執することを余儀なくされている場合は

それが大きな疑問に答える。私はchar配列を使っていたやり方に間違ったことがあることを知っていましたが、それを修正する方法を理解できませんでした。ちなみに、 '* nameInput'は配列の最初の要素を' name'配列に追加するだけです。 forループを使って名前の初期化を修正しました。 –

+0

'* nameInput'は配列の最初の文字を意味します –

0

@yinchは、私がidInputを配列の代わりに値として扱っていることを正しく指摘しました。それを書く:

StudentRecord TESCStudent = { { *nameInput }, idInput, gpaInput };

すると、エラーを削除しますが、唯一のnameInput[20]からTESCStudent.name[20]への最初の値を追加します。私はこのようTESCStudentに値を追加することを決定した:

StudentRecord TESCStudent; // create a variable from StudentRecord 

    cout << "Enter your name:" << endl; // prompt for name 
    char nameInput[20]; 
    cin >> nameInput; 

    for(size_t i = 0; i < 20; i++) // assign each element of nameInput 
            // to TESCStudent.name explicitly 
    { 
     TESCStudent.name[ i ] = nameInput[ i ]; 
    } 

    cout << "\nEnter your student ID:" << endl; // prompt for ID 
    int idInput; 
    cin >> idInput; 
    TESCStudent.id = idInput; // assign idInput to TESCStudent.id 

    cout << "\nEnter your GPA:" << endl; // prompt for GPA 
    float gpaInput; 
    cin >> gpaInput; 
    TESCStudent.gpa = gpaInput; // assign gpaInput to TESCStudent.gpa 

ザ・ループのために明示的TESCStudent.nameに各アレイ値を割り当てることによって、問題を解決します。助けてくれてありがとう!

関連する問題