Почему «info []» из структурных записей дает ошибки? - PullRequest
0 голосов
/ 11 февраля 2019

Эта программа использует класс и берет информацию о сотрудниках из файла.Я упоминал файл ниже тоже.Я также упомянул вывод, который я получил, хотя есть ошибки.В выводе тоже что-то не так, но я думаю, что это из-за информационной ошибки, которую он получает.

Во время работы этой программы я получил это сообщение об ошибке:

Error: Run-Time Check Failure #2 - Stack around the variable 'info' was corrupted.

Также есть это сообщение:

Unhandled exception at 0x00950A89 in employee.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.

// Используемый файл для этой программы:

A.Smith                       20001 25 40
T.Philip                      20002 20 35
S.LOng                        20003 15 50
G.Santos                      20004 30 30
F.Farkas                      20005 22 55

// Вывод после запуска даже с ошибками:

 This week's employee history

 Name           Id            Rate          Hours
*  A.Smith     20001         $25/h        40h
* T.Philip     20002         $20/h        35h
*   S.LOng     20003         $15/h        50h
* G.Santos     20004         $30/h        30h
* F.Farkas     20005         $22/h        55h


This week's payment

 Name               Payment
* ╠╠╠╠╠╠╠╠         $0        <----------There is this error too
*  T.Philip         $700
*    S.LOng         $825
*  G.Santos         $900
*   A.Smith         $1000


* The average wages of the employees: $685.00

// Код:

/*
#include "pch.h"
#include <iostream> 
#include <fstream> 
#include <stdlib.h> 
#include <string> 
#include<iomanip> 
*/
using namespace std;

struct records {
    char name[50] = {};
    char id[5] = {};
    int rate = 0;
    int hours = 0;
    int pay = 0;
};

void take(records array[], const int a);
int calculator(records array[], const int a);
void swap(records array[], const int a);   
double Average(records array[], int a);

ifstream infile;

int main()

{
    const int n = 5;

Это первый разобъявлена ​​информация:

    struct records info[n];
    double averageWages;
    int overTime = 0, i;
    infile.open("Project 3.dat");

    cout << "\n This week's employee history \n" << endl;

    if (infile.is_open()) {
        cout << " Name           Id            Rate          Hours  " << endl;

Здесь функция take использует информацию о структуре:

        take(info, n);

        cout << endl << endl;
        cout << "This week's payment\n" << endl;
        cout << " Name               Payment" << endl;

Также здесь другие функции используют информацию:

        calculator(info, n);
        swap(info, n);

        for (i = 0; i < n; i++) {
            cout << "*" << setw(10) << info[i].name << setw(10) << "$" << info[i].pay << endl;
        }
        averageWages = Average(info, n);

        cout << "\n\n" << "* The average wages of the employees: $" << averageWages << endl << endl;
    }

    else {
        cerr << "Error! file cannot open." << endl;
        exit(1);
    }
    return 0;
}

// Принимаязаписи:

void take(records array[], const int a) {
    for (int i = 0; i < a; i++) {

        while (infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours) {
            cout << "*" << setw(9) << array[i].name << setw(10) << array[i].id << setw(10) << "$" << array[i].rate << "/h" << setw(10) << array[i].hours << "h      " << endl;
        }
    } infile.close();
}

// поменять записи, чтобы упорядочить их в соответствии с общей полученной выплатой

void swap(records array[], const int a) {
    bool tf; //true or false

    do {
        tf = false;

        for (int i = 0; i < a; i++) {

            if (array[i].pay > array[i + 1].pay) {
                swap(array[i], array[i + 1]);
                tf = true;
            }
        }
    } while (tf);

    records temp;

    for (int i = 0; i < a - 1; ++i)
    {
        for (int j = i + 1; j < a; ++j)
        {
            if (array[i].pay > array[j].pay)
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}

To calculate average:

double Average(records array[], const int a) {

    double total = 0;
    double average;

    for (int i = 0; i < a; i++) {
        total = total + (array[i].pay);
        average = total / a;
    }

    cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);
    return (total / a);
}

// Для расчета зарплаты:

int calculator(records array[], const int a) {



    infile.open("Project 3.dat");

    if (infile.is_open()) {

        for (int i = 0; i < a; i++) {
            infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours;

            if (array[i].hours > 40) {
                int   overTime = (array[i].hours - 40)*1.5;
                array[i].pay = ((array[i].rate) * 40) + (overTime*(array[i].rate));
            }
            else {
                array[i].pay = (array[i].rate)*(array[i].hours);
            }
        }

        for (int i = 0; i < a; i++) {
            return (array[i].pay);
        }
    }
}

1 Ответ

0 голосов
/ 12 февраля 2019

Трудно найти все потенциальные проблемы с этим фрагментированным кодом, но вам лучше использовать std::string s вместо char[].Они безопаснее, а также имеют множество встроенных функций.Они также хорошо работают с разным.функций в STL.

Ваш struct records info[n]; будет содержать только n (5) элементов.Вместо этого используйте стандартный контейнер, например std::vector на тот случай, если вы захотите добавить больше записей в файл.

Чтение и запись в файлы обычно можно выполнять с помощью пользовательских потоковых операторов и всех бесплатных функций, которые выприходится иметь дело с рядом записей, которые могут быть собраны в своем собственном классе.Я создал одну record структуру и один Records класс, чтобы продемонстрировать, как они могут использоваться вместе.

#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>

struct record {
    std::string name{};
    std::string id{};
    int rate = 0;
    int hours = 0;
    int pay = 0;

    // stream operators for reading/writing a record
    friend std::istream& operator>>(std::istream&, record&);
    friend std::ofstream& operator<<(std::ofstream&, const record&);
    friend std::ostream& operator<<(std::ostream&, const record&);
};

// populate a record from an istream
std::istream& operator>>(std::istream& is, record& r) {
    std::string line;
    // get a line and check that it's > 30 chars long
    if(std::getline(is, line) && line.size()>30) {
        // extract the name and remove trailing spaces
        r.name = line.substr(0, 30);
        auto pos = r.name.find_last_not_of(' ');
        if(pos != std::string::npos)
            r.name = r.name.substr(0, pos+1);

        // put the rest of the line in a stringstream
        std::stringstream ss(line.substr(30));
        // and extract the rest of the fields
        if(ss >> r.id >> r.rate >> r.hours) {
            // calculate pay
            r.pay = r.rate * r.hours;
        } else { // if extraction fails, set the stream in fail mode
            is.setstate(std::ios_base::failbit);
        }
    } else is.setstate(std::ios_base::failbit);

    return is;
}

// streaming a record to an ofstream (like a file)
std::ofstream& operator<<(std::ofstream& os, const record& r) {
    os << std::setw(30) << std::left << r.name.substr(0, 30) << r.id << " " << r.rate << " " << r.hours << "\n";
    return os;
}

// streaming a record to a generic ostream (like std::cout)
std::ostream& operator<<(std::ostream& os, const record& r) {
    os << "* " << std::setw(30) << std::left << r.name << std::right << r.id
       << " $" << r.rate << "/h " << r.hours << "h $" << std::setw(4) << r.pay;
    return os;
}

class Records { // a class to maintain a number of "record"s
    std::vector<record> m_records{}; // stores all "record"s
public:
    Records(const std::string& filename) {
        record tmp;
        std::ifstream e(filename); // open file
        // and extract one record at a time and put it in m_records.
        while(e>>tmp) m_records.emplace_back(std::move(tmp));
    }

    // sum on any member in "record"
    template <typename field>
    auto Sum(field f) const {
        return std::accumulate(m_records.begin(), m_records.end(), 0,
                    [&](int a, const record& b) { return a + (b.*f); });
    }

    // average of any member in "record"
    template <typename field>
    auto Average(field f) const {
        return static_cast<double>(Sum(f)) / m_records.size();
    }

    // sorting on any member in "record"
    template <typename field, typename T>
    void Sort(field f, const T& cmp) {
        std::sort(m_records.begin(), m_records.end(),
                [&](const record& a, const record& b){ return cmp(a.*f, b.*f); });
    }

    // return the number of "record" elements
    std::vector<record>::size_type size() const { return m_records.size(); }

    // access an element via subscript
    record& operator[](std::vector<record>::size_type idx) { return m_records[idx]; }
    const record& operator[](std::vector<record>::size_type idx) const { return m_records[idx]; }

    // iterators to use in for-loops
    std::vector<record>::const_iterator cbegin() const noexcept { return m_records.cbegin(); }
    std::vector<record>::const_iterator cend() const noexcept { return m_records.cend(); }
    std::vector<record>::const_iterator begin() const noexcept { return cbegin(); }
    std::vector<record>::const_iterator end() const noexcept { return cend(); }
    std::vector<record>::iterator begin() noexcept { return m_records.begin(); }
    std::vector<record>::iterator end() noexcept { return m_records.end(); }

    // stream operator to show all records
    friend std::ostream& operator<<(std::ostream&, const Records&);
};

std::ostream& operator<<(std::ostream& os, const Records& R) {
    os << "  Name                            Id  Rate  Hrs  Pay\n";
    for(const auto& r : R) std::cout << r << "\n";

    os << std::setprecision(2) << std::fixed;
    os << "Average pay         : $" << std::setw(7) << R.Average(&record::pay) << "\n";
    os << "        rate        : $" << std::setw(7) << R.Average(&record::rate) << "\n";
    os << "        hours worked:  " << std::setw(7) << R.Average(&record::hours) << "h\n";
    return os;
}

int main() {
    // create a "Records" entity called "info" by reading a file
    Records info("Project 3.dat");

    // misc sorting and showing the result
    std::cout << "Sorted as read from the file:\n";
    std::cout << info;

    std::cout << "\nSorted according to name:\n";
    info.Sort(&record::name, std::less<std::string>());
    std::cout << info;

    std::cout << "\nSorted according to id:\n";
    info.Sort(&record::id, std::less<std::string>());
    std::cout << info;

    std::cout << "\nSorted according to pay:\n";
    info.Sort(&record::pay, std::greater<int>());
    // output example using iterators:
    for(auto& rec : info) {
        std::cout << rec << "\n";
    }

    std::cout << "\nSorted according to rate:\n";
    info.Sort(&record::rate, std::greater<int>());
    std::cout << info;

    std::cout << "\nSorted according to hours:\n";
    info.Sort(&record::hours, std::greater<int>());
    std::cout << info;

    // example using subscript, operator[]
    if(info.size()>2) {
        std::cout << "\ninfo[2] = " << info[2] << "\n";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...