2013-08-27 2 views
0

나는 배열, 포인터, 구조체 및 de/referencing과 관련된 문제를 연구하고 있습니다. 각각의 의미가 각각 무엇인지에 대해 이해하고 각각을 초기화하는 것이 일반적이지만 프로그램에서 제대로 사용하지 않는 것 같습니다. 내가 가지고있는 것/잘 작동하지만, 이것들을 사용하는 더 좋은 방법이 있는지 알고 싶습니까?C++ 포인터 및 배열 ... [], * 및 &

일반적인 프로그램 요구 사항은 다음과 같습니다. (각 질문에 대해 생각하는 선을 포함 시켰습니다. 각 행을 프로그램에 올바르게 사용하고 통합하고 싶습니다.) 주로 사용 위치 StudentData[i].testArray)

1 - 구조체를 사용하여 name, id #, test ( 포인터를 가리키는 포인터), 평균, 문자 등급을 저장하십시오.

struct StudentData {...}; 

2 - 학생의 수와 시험의 수 (각 학생을위한 동일)

3 요청 - 동적 구조의 배열을 할당

StudentData *allStudents; 
allStudents = new StudentData[numStudents]; 

4 - 각 구조체의 Tests 구성원은 동적으로 할당 된 배열을 가리켜 야합니다. est 점수.

double *testsArray; 
for (int i=0; i < numStudents; i++) 
{ 
    allStudents[i].testsArray = new double[numTests]; 
} 
//does this need to be deleted with a for loop as well?? 

5 - 계산 시험 평균 성적 등급

6 - 디스플레이 정보

전체 코드 :

// Course Grade 
// A program to gather and display a collection of student information. 
// Programmer Name : Chuck 
// C++ II 

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

//structure to hold data for each student 
struct StudentData 
{ 
    string studentName; 
    int studentID; 
    double *testsArray;  //pointer to an array of test scores 
    double testAverage;  //calculated average test score 
    char courseGrade;  //calculated course letter grade (A-F) 
}; 


//function prototypes 
string getName(); 
int getID(); 
double getScore(int count); 
char calcGradeLetter(double *testAverage); 
void displayData (StudentData allStudents[], int sCount); 



int main() 
{ cout << " Welcome to the Test Score Storer. This program will gather test\n"; 
    cout << "scores for a given student name/id#. We'll start with some questions.\n\n"; 

    int numTests; 
    cout << "How many test scores per student? : "; 
    cin >> numTests; 

    int numStudents; 
    cout << "How many students?    : "; 
    cin >> numStudents; 

    cout << "Creating Database..."; 
    //create array to hold all studentData structs 
    StudentData *allStudents; 
    allStudents = new StudentData[numStudents]; 
    cout << "..."; 
    //create a tests member array for each student struct 
    double *testsArray; 
    for (int i=0; i < numStudents; i++) 
    { 
     allStudents[i].testsArray = new double[numTests]; 
    } 
    cout <<"...Done!\n"; 
    system ("pause"); 
    system ("CLS"); 


    //TRYING 
    for (int i=0; i < numStudents; i++) 
    { 
     cout << "Student " << i+1 << " of " << numStudents << endl; 
     cout << "=================================\n"; 
     allStudents[i].studentName = getName(); 
     allStudents[i].studentID = getID(); 
     double testTotal = 0.0; 
     for (int j=0; j < numTests; j++) 
     { 
      allStudents[i].testsArray[j] = getScore(j); 
      testTotal += allStudents[i].testsArray[j]; 
      allStudents[i].testAverage = testTotal/numTests; 
     } 
     //calculate letter grade 
     allStudents[i].courseGrade = calcGradeLetter(&allStudents[i].testAverage); 
     cout << "Student, " << allStudents[i].studentName << ", completed.\n"; 
     system ("pause"); 
     system ("CLS"); 
    } 

    //Display all collected student data in chart form 
    displayData(allStudents, numStudents); 


    delete [] allStudents; 
    system ("pause"); 
    return (0); 
} 


//===========FUNCTIONS===========FUNCTIONS===========FUNCTIONS 
string getName() 
{ 
    string name; 
    cout << "Student Name : "; 
    cin >> name; 
    return name; 
} 

int getID() 
{ 
    int IDnum; 
    cout << "Student ID : "; 
    cin >> IDnum; 
    return IDnum; 
} 

double getScore(int count) 
{ 
    double score; 
    score = -500; 
    while (score <0) 
    { cout << "Test Score #" << count+1 <<" : "; 
     cin >> score; 
     if (score < 0) 
     { 
      cout << "Scores cannot be less than 0, try again.\n"; 
     } 
    } 
    return score; 
} 


char calcGradeLetter(double *testAverage) 
{ 
    if (*testAverage >= 90) return 'A'; 
    else if (*testAverage >= 80) return 'B'; 
    else if (*testAverage >= 70) return 'C'; 
    else if (*testAverage < 70) return 'F'; 
    else return ('X'); 
} 

void displayData(StudentData allStudents[], int sCount) 
{ 
    cout << "Student Data Chart:\n"; 
    cout << "=================================================\n"; 
    cout << "NAME    ID#   TEST AVE. GRADE\n"; 
    for (int i = 0; i < sCount; i++) 
    { 
     cout << left << setw(18) << allStudents[i].studentName << " " 
      << left << setw(12) << allStudents[i].studentID << " " 
      << left << setw(11) << setprecision(4) << allStudents[i].testAverage << " " 
      << allStudents[i].courseGrade << endl; 
    } 
    cout << "\nTable complete. "; 
    } 

이 스택 내 첫 번째 게시물입니다, 죄송합니다.이 장소가 잘못된 장소에 있거나 숙제가 필요하다면 y, 나는 쉬운 대답만을 찾고있는 것이 아니다. 나는 새로운 개발자로서 열심히 배워야한다. 이 주제는 내가 작업하는데 많은 어려움을 겪고있는 것입니다.

+4

동적 배열 인'new []'대신'std :: vector'를 사용하는 것이 훨씬 쉽습니다. – chris

+3

단지 두 군데에서'std :; vector <> '를 사용하여이 cruft *가 얼마나 많이 사라지는 지 당신이 알고 있다면. 'std :: string','operator new()'및 콘솔 출력의 가짜 사용 외에 C 코드 일 수도 있습니다. 또한, 당신의'StudentData'는 생성자와 소멸자에 대해 * begging *입니다. – WhozCraig

답변

1

귀하의 질문에 대한 짧은 대답은 '예'입니다. 결과를 얻는 더 좋은 방법이 있습니다.

더 긴 대답은 할당의 성격과 메모리 할당과 할당 해제를 특별히 처리해야한다는 요구 사항 때문입니다. (그런데 어디에서 각 테스트 코드 할당을 해제하는지는 알 수 없습니다. 학생. 삭제하기 전에 각 학생을 반복해야하고 시험 점수 배열을 삭제해야합니다.) 배열 문제를 모두 처리하는 std::vector과 같은 것을 사용하지 못하도록 제한합니다. 당신이 학생 배열을 삭제하면, 그 다음

struct StudentData 
{ 
    StudnetData() : studentID(0), testsArray(NULL), testAverage(0.0), courseGrade('N') 
    { 

    } 

    ~StudentData() 
    { 
     delete [] testsArray; 
    } 

    string studentName; 
    int studentID; 
    double *testsArray;  //pointer to an array of test scores 
    double testAverage;  //calculated average test score 
    char courseGrade;  //calculated course letter grade (A-F) 
private: 
    StudentData(const StudentData&); // unimplemented intentionally 
    StudentData& operator= (const StudentData&); // unimplemented intentionally 
}; 

:

그냥 메모리 관리에 조금 도움 그들은 또한 삭제됩니다이

delete [] allStudents; 

모든 테스트를.

+0

벡터에 대해 배웠고 여기서 어떻게 유용하게 쓸 수 있는지 보았습니다. 그러나 유감스럽게도 배열은 언급 된대로 사용해야합니다. Zac, allStudents 배열을 삭제하면 테스트 점수 배열이 삭제되는지 확실하지 않았습니다. 루프를 거쳐 다음과 같이 삭제합니다 : –

+0

구조체에 소멸자를 추가하면 학생이 삭제 될 때 테스트 점수 배열을 삭제할 수 있습니다. –

+0

죄송합니다 ... shift + enter를 잊어 버렸습니다. 은 본 것이 적절 삭제 INT (X = 0, X

1

std::vector과 같은 유형의 표준 사례가 아닌 new을 사용하라는 요청을 받으면이 기능을 사용할 수 있습니다.

C++에는이 요구 사항을 준수하면서 더 편리하고 안전하며 자동으로 사용할 수 있도록 new이라는 사용법을 마무리하는 데 사용할 수있는 도구가 있습니다. 기본적으로 vector의 단순화 된 버전을 구현할 것입니다. 그러나 C++의 모든 필요한 부분을 배우지 않았을 것입니다. 당신이 어딘가에 잘못된 등급 (예를 들어, '전자')가 발생할 가능성이 낮아

enum Grade { A, B, C, D, F}; 

이 방법 :

structs TestsArray { 
    double *scores; 
    // constructors, destructors, etc. to make this behave properly 
    // ... 
}; 

structs StudentsArray { 
    StudentData *students; 
    // basically the same as for TestArray; templates avoid this duplication 
}; 

또한 등급에 대한 당신은 열거를 정의 할 수 있습니다.

struct StudentData 
{ 
    string studentName; 
    int studentID; 
    TestsArray testsArray; 
    double testAverage; 
    Grade courseGrade; 
}; 


cout << "Creating Database..."; 
//create array to hold all studentData structs 
StudentsArray allStudents(numStudents, numTests); 
cout <<"...Done!\n"; 

// allStudents will automatically be cleaned up at the end 

//

이 필요뿐만 아니라 for 루프로 삭제해야합니까?

예, 아니면 적어도 모든 학생의 testsArray가 삭제되도록 조정해야합니다.

+0

for-loop 일 필요는 없지만이를 수행하는 방법은 하나입니다 (학생 구조에 소멸자를 추가하는 것도 또 다른 방법입니다). –

+0

@ZacHowland 아, 그저 바뀌 었습니다.필자가 선호하는 메소드 ('std :: vector'는 테이블에서 제외됨)가 자체적으로 처리하는 배열 타입을 구현할 것이다. (그래서'Student'가 디폴트 소멸자를 사용할 수 있고 전체'Student' 배열은 a 비슷한 유형 (또는 동일한 배열 템플릿의 또 다른 인스턴스화). – bames53

+0

동의합니다. 나는 항상 나쁜 습관 인 무언가를하도록 강요 한 과제를 싫어했다. 적어도 스마트 포인터의 통합을 허용해야합니다. –