c++ - 程序吃掉一行的第一个字母
问题描述
所以我正在练习使用 C++ 处理文件。我创建了一个简单的程序,它从 加载学生的姓名、索引号、出生日期和成绩STUDENT.txt
,计算学生的平均成绩,然后以下面的表格将其全部写到不同的文件中。
这一切都像一个魅力,除了一件事:它吃掉了每一行的第一个字母。示例:我有一个 STUDENT.txt 文件,如下所示:
Alice Cooper
225883
21/6/1986
6,6,8,9,10
Zakk Wylde
27568
14/5/1978
6,6,6,6,6
因此,第一个学生 Cooper 将被正确处理,但文件中的其他所有人都不会。他们将被写成'akk Wylde'......所以除了名字之外的一切都可以。我希望有人能告诉我到底发生了什么,我猜它正在吃掉一个 '\n' 和另一个字符,但我无法通过调试找到它。
// Student_datoteka.cpp : 定义控制台应用程序的入口点。//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
std::string toString(int day, int month, int year) {
std::string d, m, g, ret;
d = std::to_string(day);
m = std::to_string(month);
g = std::to_string(year);
ret += d;
ret += "/";
ret += m;
ret += "/";
ret += g;
return ret;
}
int main()
{
std::fstream load("STUDENTI.txt", std::ios::in);
std::ofstream write("IZVJESTAJ.txt");
write << std::setw(30) << std::left << "Student"
<< std::setw(10) << "Indeks"
<< std::setw(20) << "Datum rodjenja"
<< std::setw(10) << "Prosjek" << std::endl;
write << std::setw(30) << std::left << "-------"
<< std::setw(10) << "------"
<< std::setw(20) << "--------------"
<< std::setw(10) << "-------" << std::endl;
if (!write)
std::cout << "ERROR!";
std::string name;
int indeks(0), day(0), month(0), year(0);
char sign(0), sign2(0);
int grades[30];
double average(0);
while (std::getline(load, name)) {
if (load.eof()) break;
load >> indeks;
load >> day >> sign >> mjesec >> sign2 >> year;
int i(0);
while (load >> grades[i]) {
load >> sign;
average += grades[i];
i++;
}
average /= double(i);
std::string datum = toString(day, month, year);
write << std::setw(30) << std::left << name
<< std::setw(10) << indeks
<< std::setw(20) << datum
<< std::setw(10) << std::setprecision(2)
<< average<< std::endl;
average = 0;
if (load.eof()) break;
load.clear();
}
return 0;
}
这是输出: http: //prntscr.com/jvm3jn
解决方案
我对您的代码做了一些小的改进,所以如果您不喜欢,请只使用工作部分。请注意,我的代码可以进一步改进和推广,但我将把它留给你。
希望你喜欢我的解决方案:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>
typedef struct Student
{
std::string name;
int index_no;
int day_of_birth;
int month_of_birth;
int year_of_birth;
std::vector<int> grades;
double avg_grade;
} Student;
std::string date_to_string(int day, int month, int year)
{
std::string d, m, g, ret;
d = std::to_string(day);
m = std::to_string(month);
g = std::to_string(year);
ret += d;
ret += "/";
ret += m;
ret += "/";
ret += g;
return ret;
}
void get_date_from_str(int& day, int& month, int& year, std::string const& str)
{
std::stringstream ss(str);
ss >> day;
ss.ignore(1);
ss >> month;
ss.ignore(1);
ss >> year;
}
void get_numbers_from_str(std::vector<int>& vec, std::string const& str)
{
std::stringstream ss(str);
int i;
while (ss >> i)
{
vec.push_back(i);
ss.ignore(1);
}
}
double calculate_avg(std::vector<int> const& vec)
{
int sum = 0;
for (auto item : vec)
{
sum += item;
}
return (double) sum / vec.size();
}
int main()
{
std::ifstream students_file("students.txt");
std::ofstream report_file("report.txt");
if (students_file.is_open() && report_file.is_open())
{
report_file << std::setw(30) << std::left << "Student"
<< std::setw(10) << "Indeks"
<< std::setw(20) << "Datum rodjenja"
<< std::setw(10) << "Prosjek" << std::endl;
report_file << std::setw(30) << std::left << "-------"
<< std::setw(10) << "------"
<< std::setw(20) << "--------------"
<< std::setw(10) << "-------" << std::endl;
std::vector<Student> students;
std::string name;
while (std::getline(students_file, name))
{
std::string index_no;
std::string date_of_birth;
std::string grades;
Student student;
student.name = name;
std::getline(students_file, index_no);
std::stringstream(index_no) >> student.index_no;
std::getline(students_file, date_of_birth);
std::getline(students_file, grades);
get_date_from_str(student.day_of_birth, student.month_of_birth, student.year_of_birth, date_of_birth);
get_numbers_from_str(student.grades, grades);
student.avg_grade = calculate_avg(student.grades);
students.push_back(student);
}
for (auto student : students)
{
report_file << std::setw(30) << std::left << student.name
<< std::setw(10) << student.index_no
<< std::setw(20) << date_to_string(student.day_of_birth, student.month_of_birth, student.year_of_birth)
<< std::setw(10) << std::setprecision(2)
<< student.avg_grade << std::endl;
}
}
else
{
std::cout << "Unable to open one of the files!" << std::endl;
}
return 0;
}
首先,我认为你已经把你的代码复杂化了,阅读和理解它,而你有一些 C++ 特性可以通过符号和解析日期和等级来简化这部分。
我还创建了struct Student
一些代码并将其拆分为函数。
而且,关于您的解决方案。正如评论中已经提到的那样,错误在于以下几行:
while (load >> grades[i])
{
load >> sign;
average += grades[i];
i++;
}
你比你需要的多“吃”了一个角色。而这个字符就是第二个学生名字的第一个字符。因此,如果您将代码更改为以下代码,您将看到我在说什么:
while (load >> grades[i])
{
if (i != 4) // just a temporary solution, since the first student has 5 grades
load >> sign;
average += grades[i];
i++;
}
推荐阅读
- javascript - 云存储问题
- java - kotlin @Interface 的别名
- c++ - 检查数字是否在特定范围内
- ios - 选择自定义标签栏项目时出现问题(cbflashytabbarcontroller)
- reactjs - 我想访问另一个组件中处于另一个状态的数据到这个组件
- javascript - 使用 video.js 播放 youtube 视频
- next.js - NextJs 最佳实践/在哪里将页面设置为全屏
- ios - 在 Xcode 中为 Firebase 身份验证添加 URL 方案后,Ionic App 崩溃
- sql - 在 30 分钟内查找为相同描述创建的值
- javascript - SVELTE:未捕获(承诺)类型错误:无法读取属性“配置文件”