у меня есть .txt
файл, в котором хранятся имена учеников и две их лучшие оценки. Если студент по какой-то причине, то есть бросает учебу, не проходит курс, то оценки не записываются.
Мой файл выглядит так
Samuel= 90.5, 95.9
Bill= 25.2, 45.3
Tim
Anthony= 99.9, 12.5
Mark
Rob
В принципе, Tim
, Mark
а также Rob
провалил курс и следовательно их оценки не сохраняются. Кроме того, чтобы провести различие между неудавшейся отметкой и проходной отметкой, я использовал =
условное обозначение. По сути, я хочу сохранить все имена в памяти вместе с соответствующими значениями.
Это моя реализация, однако она несовершенна в том смысле, что я объявил double *marks[2]
массив для хранения всех шести меток, когда ясно, что он будет хранить только 3. У меня проблемы с сохранением значений в double
массив.
Это мой код …
istream& operator>> (istream& is, Students& student)
{
student.names = new char*[6];
for (int i=0; i<10; i++)
{
student.names[i] = new char[256];
student.marks[i] = new double[2];
is.getline(student.names[i], sizeof(student.names));
for (int j=0; j < 256; j++)
{
if((student.names[i][j] == '='))
{
int newPos = j + 1;
for (int k = newPos; k < 256; k++)
{
student.names[i][k - newPos] = student.names[k];
}
}
}
}
}
Как я могу хранить ценности учеников с действительными оценками? Пожалуйста, не используйте vectors
или же stringstreams
, просто чистый C / C ++ char arrays
У вас есть несколько вариантов, вы можете использовать struct
вот так
struct Record {
std::string name;
double marks[2];
};
А потом воткнуть это во что-то вроде std::vector<Record>
или массив из них, как
Records *r = new Records[1000];
Вы также можете сохранить три разных массива (автоматически или динамически или даже std::vector
), один, чтобы держать имя, два, чтобы держать знаки.
В каждом случае вы просто указали бы на сбой с помощью некоторой вещи, например, отметки равны нулю.
Также вы можете использовать
std::string name;
double first, second;
std::cin >> name;
if (name[name.size() - 1] == '=')
std::cin >> first >> second;
И это будет анализировать ввод, как вы хотите, для одной строки. Как только вы это сделаете, вы можете обернуть все это в цикл, вставив значения, которые вы получите в какую-то структуру данных, которую я уже описал.
Надеюсь, что это даст вам несколько идей о том, куда идти!
Вот стратегия:
Прежде всего вам нужно реализовать struct
для хранения пары ключ-значение я предлагаю следующее:
struct Student {
char name[30];
double marks[2];
};
Обратите внимание, что вы можете указать размер массива char внутри struct
если вы знаете, что длина никогда не будет выше. (что дано здесь)
Теперь вам нужно знать, сколько строк в вашем ifstream
Вы могли бы сделать петлю is.getline()
звонки, чтобы добраться туда. (не забудьте позвонить is.clear()
а также is.seekg(0)
когда закончите, чтобы быть в начале для реального цикла)
Когда вы знаете, сколько строк в вашем потоке ifstream, вы можете динамически использовать массив ваших struct
с фактической длиной вашего файла:
Student * students = new Student[lineCount]; // line count of is
Как видите, нет необходимости иметь std::vector
держать значения. Считайте, что getline()
Цикл может быть излишним просто для того, чтобы получить количество строк, или же вы можете указать длину для студентов во время компиляции, создав массив с длиной, которая никогда не будет превышена.
(например. Student students[128];
)
Теперь вам нужно разобрать строки, я бы посоветовал сделать цикл, подобный следующему (строка за строкой):
// int parseLine ( char* line, char* name, double* marks ) { ...
bool hasMarks=false;
int iLine=0; // Line pos iterator
int iName=0; // Name pos iterator
char mk1Str[4]; // String buffer, Mark 1
char mk2Str[4]; // String buffer, Mark 2
while(line[iLine]!='\0')
{
if(line[iLine]=='=')
{
hasMarks=true;
name[iLine]='\0';
for(int iMark=0;iMark<4;iMark++)
{
mk1Str[iMark]=line[iLine+iMark+2];
mk2Str[iMark]=line[iLine+iMark+8];
// ^^ You can harcode the offsets (2,8) since they don't change
}
break;
}
name[iName++]=line[iLine];
iLine++;
}
Теперь вам нужно разобрать оценки double
значения, для этого вы можете использовать atof()
функция, которая работает с char*
, Бул hasMarks
поможет вам узнать, если ученик определил оценки, если нет, вы можете определить фиктивные значения, такие как -1, для полей оценки вашего struct
,
Я думаю, что это работает довольно хорошо для вашего случая …