【问题标题】:cin crashing my program after 12 for loop iterations?cin 在 12 次 for 循环迭代后使我的程序崩溃?
【发布时间】:2015-03-17 11:40:38
【问题描述】:

我以前从未在这里发过帖子,但我真的被困住了,所以我想我会试一试。我一直在研究这段代码,目的是输入一些学生的分数,并将它们输出到带有平均值和总数的表格中。我得到了一个这样的文件:

15
Albert Einstein 52 67 63
Steve Abrew 90 86 90 93
David Nagasake 100 85 93 89
Mike Black 81 87 81 85
Andrew Van Den 90 82 95 87
Joanne Dong Nguyen 84 80 95 91
Chris Walljasper 86 100 96 89
Fred Albert 70 68
Dennis Dudley 74 79 77 81
Leo Rice 95
Fred Flintstone 73 81 78 74
Frances Dupre 82 76 79
Dave Light 89 76 91 83
Hua Tran Du 91 81 87 94
Sarah Trapp 83 98

我的问题是,当我输入名称时,程序在 Fred Flinstone 之后崩溃,我知道下一个名称 (Frances Dupre) 的格式没有问题,因为当我将他移到列表上时,它读起来很好。

我已经找到程序在读取过程的不同阶段因“cerr”输出而崩溃的位置,并且在尝试读取 Frances 的标记时崩溃。

a1main.cpp

#include <iostream>
#include "student.h"
using namespace std;

int main()
{
    int numStds;
    cin >> numStds;

    cerr << endl << "Num Stds: " << numStds << endl;

    Student std[numStds+1];

    for(int i = 0; i <= numStds; i++)
    {
        std[i].readData();
        std[i].printStudent();  
    }

    // delete [] std;

    return 0;
}

student.h

#include <iostream>
using namespace std;

class Student {

    private:

        char* name;
        int mark[4];
        int num;

    public:

        Student();
        ~Student();

        void readData();
        void printStudent();
        float getTotal();
        float getAverage();
};

student.cpp

#include <iostream>
#include <cstring>
#include <cctype>
#include "student.h"
using namespace std;

Student::Student()
{
        name = new char;
        mark[0] = 0;
        mark[1] = 0;
        mark[2] = 0;
        mark[3] = 0;
        num = 0;
}

Student::~Student()
{
    // Doesn't work?

    // delete name;
}

void Student::readData()
{   
    int l = 0;

    // Reading the Name
    cin >> name;        // Read in the first name
    l = strlen(name);   // get the strlength
    name[l] = ' ';      // Putting a space between the first and last name
    cin >> &name[l+1];  // Read in the last name

    cerr << endl << "I have read the name!" << endl;

    // Checking if there is a third name
    if(cin.peek() == ' ')
        cin >> ws;      // checking and navigating past the whitespace

    char next = cin.peek();
    if( isalpha(next) )     // Checking whether the next cin is a char
    {
        l = 0;
        l = strlen(name);
        name[l] = ' ';
        cin >> &name[l+1];
    }

    cerr << "I've checked for a third name!" << endl;

    // Reading in the marks
    for(int i = 0; i < 4; i++)
    {
        // Checks if the next cin is a newline
        if (cin.peek() == '\n')
            break;

        cin >> mark[i];
    }

    cerr << "I've read in the marks!" << endl;

    //cerr << endl << "I have read " << name << "'s marks!" << endl << endl;

    for(int m = 0; m < 4; m++)
    {   
        if(mark[m] != 0)
        {
            num++;
        }
    }

    cerr << "I've incremented num!" << endl << endl;
}

// Function for error checking
void Student::printStudent()
{
    cout << endl << "Student Name: " << name << endl;
    cout << "Mark 1: " << mark[0] << endl;
    cout << "Mark 2: " << mark[1] << endl;
    cout << "Mark 3: " << mark[2] << endl;
    cout << "Mark 4: " << mark[3] << endl;
    cout << "num marks: " << num << endl << endl; 
}

float Student::getTotal()
{}
float Student::getAverage()
{}

谁能看到我做错了什么?谢谢:)

【问题讨论】:

  • 我不确定,但您的读取功能对于它的作用来说太复杂了。为什么要费心查看相同的数据条目?获取整行并解析它或将字符串传递给解析和填充学生的函数,为什么不呢?
  • 我不确定,这只是我检索数据的原始路径,你认为如果我将它分解成不同的函数会更好,即 readName(), readMark()... 以此类推

标签: c++ loops for-loop crash cin


【解决方案1】:

您永远不会分配内存来存储学生姓名。

在您的 Student 构造函数中,添加以下代码:

name = new char[100]; // allows names up to 100 characters long

并在析构函数中取消注释这一行:

delete[] name;

您还可以通过测量名称长度并分配正确的大小来使代码更加复杂和健壮,或者按照下面的建议使用 std::string。

【讨论】:

  • 或者直接使用std::string来避免这些错误。
  • 非常感谢。 :) 但在我的作业中指定“您需要使用动态内存分配来存储此任务的学生姓名。确保没有内存泄漏。不要忘记在程序文件中包含命名空间。”那还是动态分配内存吗?
  • 还有人能解释为什么它每次都在第 12 个名字之前起作用吗?谢谢:),我只是想更好地理解它为什么会这样做。
  • 当您写入未分配的内存地址时,行为未定义。您可以在不同的机器上编译它并获得不同的行为。但是,您为每个学生分配了一个字符,因此会分配一些内存,而第 12 个名称恰好是您写入未由进程分配的地址的第一个名称。
  • 如果您想使用动态分配并且不想使用 std::string,我认为最好使用局部变量,例如char tempname[100] 在 readData() 函数中,将名称读入其中并分配 name = new char[strlen(tempname)+1],然后将 tempname 复制到其中。那么你只分配你需要的内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多