finding the average of values in an array [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am using a for loop to grab the values in a txt file.
I want to average the numbers together. So I am doing this,
int size = 0;
double sum = 0;
for (int i = 0; i < size; ++i)
{
sum += data[i].getQuantity();
}
double avg = ((double)sum)/size; //or cast sum to double before division
std::cout << avg << '\n';
return 0;
When I cout avg I get 80nan. I assume I need to do atod But I can't seem to implement this correctly.
What am I missing here to find the average of the values stored inside getQuantity
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
struct Input
{
friend std::istream& operator >>(std::istream& inp, Input& item);
friend std::ostream& operator <<(std::ostream& outp, Input const& item);
std::string group;
float total_pay;
unsigned int quantity;
Input() : group(), total_pay(), quantity()
{
}
Input(std::string groupIn, float total_payIn, unsigned int quantityIn) :
group(std::move(groupIn)),
total_pay(total_payIn),
quantity(quantityIn)
{
}
std::string const& getGroup() const { return group; }
float getTotalPay() const { return total_pay; }
unsigned int getQuantity() const { return quantity; }
};
std::istream& operator >>(std::istream& inp, Input& item)
{
return (inp >> item.group >> item.total_pay >> item.quantity);
}
std::ostream& operator <<(std::ostream& outp, Input const& item)
{
outp
<< item.getGroup() << ' '
<< item.getTotalPay() << ' '
<< item.getQuantity();
return outp;
}
int main()
{
std::ifstream infile("input.txt");
if (!infile)
{
std::cerr << "Failed to open input file" << '\n';
exit(EXIT_FAILURE);
}
std::vector<Input> data;
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
Input inp;
if (iss >> inp) // calls our extaction operator >>
data.push_back(inp);
else
std::cerr << "Invalid input line: " << line << '\n';
}
std::copy(data.begin(), data.end(),
std::ostream_iterator<Input>(std::cout,"\n"));
std::cout << data[2].getQuantity();
int size = 0;
double sum = 0;
for (int i = 0; i < size; ++i)
{
sum += data[i].getQuantity();
}
double avg = ((double)sum)/size;
std::cout << avg << '\n';
return 0;
}

Change
int size = 0;
to
size_t size = data.size();
So you set correct value to the size, loop correct number of times and then divide by correct number instead of 0.

You are dividing by 0 in this program, this will always result in an ERROR
in a program because dividing by 0 is simply not possible.

Related

C++: Read text file into 2d array

I'm trying to read the following maze.txt file:
35
35
0
10
++++++++++S++++++++++++++++++++++++
++++++++++OOOOOOOOOOOOOOOOOOOOOOOOO
++++++++++O++++++++++++++++++O+++++
OOOOOOOOOOOOOOOOOOOOOOOOOO+++O++OOE
O+++++++++O++++++++++++++O+++O++O++
OOOOOO++++O++++++++++++++O+++O++O++
O++++O++++OOOOOOOOOOO++++O+OOO++O++
O++++O++++O+++++++++OOOO+O+++O++O++
OOO++OOOO+OOOOOO+++++++++++OOO++OOO
O+O+++++O++++++OOOOOOOOOO++O++++++O
O+OOOO++O++++++O++++++++O+++OOO+++O
O++++O++OOOOOOOO++++++++O+++O+O+++O
OOO++O++++++++++++++++++OOOOO+O+++O
++O++OOOOOOOOOOOOOOOO+++++++++OO++O
OOO+++++++++++++++++OOOOOO++++++++O
O++++++++++++++++++++++++O++OOOOOOO
+++++++++++++++++++++++++O++O++++++
OOOOOOOOOOOOOOOOOOOOOOOOOO++OOOOO++
O++++++++++++++++++++++++O++++++O++
OOOOOOO+++++++++++++++OOOOOOO+++O++
++++++++++++++++++++++O+++++OO++O++
OOOOOOOOOOOOOOOOOOOOOOO++++++O++O++
O++++++++++++++++++++++++++++O+OOOO
OOOO++++++++++++++++++++OOOOOO+O+++
+++OOOOOOOOO+++++++++++++++++++O+++
+++++O+++++OOOOOOOOOO++++++++OOO+++
+O+++OOOOO++++++O++++++++++++O+++++
+OOOOO+++O++++++OOOOOO+++++++O+++++
+++++++++++++++++++++OOOOOOOOO+++++
OOOOOOOOOOOOOOOOOOOOOO+++++++++++++
+++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++
The code works fine with the maze inside the code but I moved it out to a text file, which seems to be read but it is not working. It's giving me the error:
No matching function for call to 'mazeTravel'.
I'm not sure where to go from here. Any help would be appreciated!
#include <iostream>
#include <fstream>
using namespace std;
void printMaze(const char maze[][12], int xCoordinate, int yCoordinate);
int mazeTravel(char maze[][12], int xCoordinate, int yCoordinate, int direction);
int main()
{
char maze[35][35];
ifstream file;
file.open("maze.txt");
if (!file) {
cout << "Error reading file\n";
return -1;
}
else {
for (int row = 0; row < 35; row++) {
for (int column = 0; column < 35; column++) {
file >> maze[row][column];
int success = 0;
success = mazeTravel(maze, 2, 0, 1);
if (success == 1)
cout << "The maze has been solved.\n";
else
cout << "Sorry, the maze cannot be solved\n";
}
}
}
return 0;
}
You could use a std::vector of std::strings to represent your maze:
std::vector<std::string> maze;
To access its cells use
maze[row][column]; // with row being y and column x
To get the number of rows use
maze.size()
and
maze[0].size()
for the number of columns.
You could read such a maze like that (without error checking to not clutter the code):
std::vector<std::string> readMaze(std::istream &is)
{
std::size_t columns;
std::size_t rows;
is >> columns >> rows;
int foo; // sorry, don't know what the 3rd and 4th
is >> foo >> foo; // number is. a starting position, perhaps?
// ignore the rest of the current line:
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string line;
std::vector<std::string> maze;
while (std::getline(is, line))
maze.push_back(line);
return maze;
}
An implementation (with error checking) could look like that:
#include <cstdlib> // EXIT_FAILURE
#include <limits> // std::numeric_limits<>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
// to not have to type std::vector<std::string> all over the place
using maze_type = std::vector<std::string>;
void printMazeCell(maze_type const &maze, std::size_t x, std::size_t y)
{
std::cout.put(maze[y][x]);
}
void printMaze(maze_type const &maze)
{
for (auto const &row : maze)
std::cout << row << '\n';
}
int mazeTravel(maze_type const &maze, std::size_t x, std::size_t y, int dir)
{
// access cells of the maze with maze[y][x]
// maze.size() for the number of columns and
// maze[0].size() for the number of rows
return 42;
}
maze_type readMaze(std::istream &is)
{
std::size_t columns;
if (!(is >> columns)) {
std::cerr << "Couldn't read the number of columns :(\n\n";
return maze_type{}; // return an empty maze on error
}
std::size_t rows;
if (!(is >> rows)) {
std::cerr << "Couldn't read the number of rows :(\n\n";
return maze_type{};
}
int foo;
is >> foo >> foo; // sorry, don't know what the 3rd and 4th number is
// ignore the rest of the current line:
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Trying to read a maze with " << columns << " columns ...\n";
std::string line;
maze_type maze;
while (std::getline(is, line)) {
if (line.length() != columns) {
std::cerr << "Found a row that contains only "
<< line.length() << " columns :(\n\n";
return maze_type{};
}
maze.push_back(line);
}
if (maze.size() != rows) {
std::cerr << "The maze only consists of "
<< maze.size() << " rows :(\n\n";
return maze_type{};
}
return maze;
}
int main()
{
char const *filename = "maze.txt";
std::ifstream is{ filename };
if (!is.is_open()) {
std::cerr << "Couldn't open \"" << filename << "\" for reading :(\n\n";
return EXIT_FAILURE;
}
maze_type maze = readMaze(is);
if (!maze.size()) { // readMaze returned an empty maze :(
std::cerr << "Bye.\n";
return EXIT_FAILURE;
}
printMaze(maze);
}
The problem that you don't have the implementation of
int mazeTravel(char maze[][12], int xCoordinate, int yCoordinate, int direction);
You should create the implementation like this:
int mazeTravel(char maze[][12], int xCoordinate, int yCoordinate, int direction)
{
// The implementation
return 0;
}
Another thing: You have to read the first some numbers at the beginning of the file.
35
35
0
10
After that you can read the matrix from the file

How to add integers and strings in the same vector?

I need help for my university homework. i'm still new to this.
Basically i am doing a run-length encoding and i don't know how to add the letter after the counter:
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
void error(std::string str)
{
throw std::runtime_error(str);
}
int main()
{ int counter = 1;
std::string id;
std::vector<int> v;
std::cout << "Enter the data to be compressed: ";
std::cin >> id;
try
{ for(int i = 0; i < id.size(); i++)
{
if(std::isdigit(id[i]))
error("invalid input");
}
std::cout << "The compressed data is: ";
for(int i = 0; i < id.size(); i++)
{
if(id[i] == id[i+1])
{
counter++;
}
else if(id[i]!= id[i+1])
{
v.push_back(counter);
v.push_back(id[i]);
counter=1;
}
}
for(int j = 0; j < v.size(); j++)
std::cout << v[j];
}
catch(std::runtime_error& str)
{
std::cerr << "error: " << str.what() << std::endl;
return 1;
}
return 0;
}
For example if i input aaabbb, the probram should output 3a3b. The problem is that it outputs 397398 97 and 98 being the ascii code for a and b.
i don't know how to put the letter after the counter and for them to be in the same vector.
If you want to serialize as a string try this :
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <sstream>
void error(std::string str) {
throw std::runtime_error(str);
}
int main() {
std::ostringstream stream;
int counter = 1;
std::string id;
std::cout << "Enter the data to be compressed: ";
std::cin >> id;
try {
for (int i = 0; i < id.size(); i++) {
if (std::isdigit(id[i]))
error("invalid input");
}
std::cout << "The compressed data is: ";
for (int i = 0; i < id.size(); i++) {
if (id[i] == id[i + 1]) {
counter++;
} else if (id[i] != id[i + 1]) {
stream << counter;
stream << (char) id[i];
counter = 1;
}
}
std::cout << stream.str() << std::endl;
} catch (std::runtime_error& str) {
std::cerr << "error: " << str.what() << std::endl;
return 1;
}
}
v[j] from std::cout << v[j] is of type int and that is why std::cout writes a number. To write it as a character, you should cast v[j] to char as follows: std::cout << (char)v[j]. In this way, std::cout will use the char specialization, not the int one.
While the other answers might give you the output you need, I believe the idiomatic way to solve this is using a class to hold both the character and its count. There are two obvious choices.
std::pair
Could also be std::tuple if you prefer it for consistency or whatever reason. Save your results in a std::vector<std::pair<char, int>. This saves the information, but to print it you would need to define an appropriate function. Add elements via
v.emplace_back(character, count);
Wrapper Class
If you want to offer some functionality without outside helper classes, define a custom wrapper class such as the following.
class CharacterCount {
private:
char character;
int count;
public:
CharacterCount(char character, int count):
character(character), count(count) {}
explicit operator std::string() const { return std::to_string(count) + character;
// Other helper functions or constructors you require
}
This simplifies printing
for (auto& character_count : v)
std::cout << static_cast<std::string>(character_count);
I believe because std::ostream::operator<< is templated, you cannot get an implicit conversion to std::string to work. I would advise against implicit conversion anyway.
You can use the same emplace_back syntax as before because we offer an appropriate constructor.
So you take your input in a string and ultimately just need to stream this information out, ultimately meaning there's really no reason to store the information in a vector, just output it! You can use find_if with a lambda to find the non-consecutive character (or find_if_not if you prefer.)
for(string::const_iterator finish, start = cbegin(id); start != cend(id); start = finish) {
finish = find_if(start, cend(id), [value = *start](const auto i) { return i != value; } );
cout << distance(start, finish) << *start;
}
Live Example

Using Structures and Pointers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This code is supposed to read in from a file and store the information. Here's the file:
5
Franks,Tom 2 3 8 3 6 3 5
Gates,Bill 8 8 3 0 8 2 0
Jordan,Michael 9 10 4 7 0 0 0
Bush,George 5 6 5 6 5 6 5
Heinke,Lonnie 7 3 8 7 2 5 7
right now I'm just focused on saving pointers to the names. Here's the code I have so far (Ignore the other functions I haven't gotten to those yet). I have to save the names using employees[row] = new Employee; and fin >> employees[row]->names; and I just don't know how to go about doing that.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
struct Employee {
string names;
vector<int> data;
int totalHrs;
};
int fillAndTotal(vector<Employee *>&employees);
void sort(vector<Employee *>&employees, int amount);
void output(vector<Employee *>&employees, int amount);
int main()
{
vector<Employee *>employees;
//vector<string>names;
int amount = 0;
amount = fillAndTotal(employees);
sort(employees, amount);
output(employees, amount);
system("pause");
return 0;
}
int fillAndTotal(vector<Employee *>&employees) {
int const TTL_HRS = 7;
ifstream fin;
fin.open("empdata.txt");
if (fin.fail()) {
cout << "ERROR";
}
int sum = 0;
int numOfNames;
fin >> numOfNames;
string tmpString;
int tempInt = 0;
vector<int>temp(8);
for (int row = 0; row < numOfNames; row++) {
employees[row] = new Employee;
fin >> employees[row]->names;
Firstly, you don't need pointers for this - your Employee structure is perfectly safe to store as-in in a vector.
Secondly, when reading line-orientated data like this, it's very easy to get off-track and let your reads overflow into the next line, or underflow and you not carry out enough reads for the line - what I do is write a function that reads a whole line at a time and returns a stringstream containing just that line, then I do my individual reads on that stringstream.
Thirdly, and finally, it's always useful to write functions that allows you to dump out your data structures so that you can confirm visually that you've populated the structures correctly. Or you can use a debugger.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
struct Employee
{
std::string names;
std::vector<int> data;
int totalHrs;
};
using EmpList = std::vector<Employee>;
int fillAndTotal(EmpList& employees);
std::stringstream readRowData(std::istream& fin);
#ifndef NDEBUG
// Debug - dump to stream.
std::ostream& operator<<(std::ostream& out, const Employee& employee);
std::ostream& operator<<(std::ostream& out, const EmpList& employees);
#endif
int main(int argc, char* argv[])
{
EmpList employees;
auto grandTotal = fillAndTotal(employees);
std::cout << employees;
std::cout << "\nGrand total hours: " << grandTotal << std::endl;
}
int fillAndTotal(EmpList& employees)
{
auto fin = std::ifstream("empdata.txt");
auto rowCount = 0;
auto rowData = readRowData(fin);
rowData >> rowCount;
auto totalHours = 0;
for (auto i = 0; i < rowCount; ++i)
{
rowData = readRowData(fin);
if (!fin.eof())
{
auto employee = Employee{};
rowData >> employee.names;
int hours;
while (rowData >> hours)
{
if (hours != 0)
{
employee.data.push_back(hours);
employee.totalHrs += hours;
totalHours += hours;
}
}
employees.push_back(employee);
}
}
return totalHours;
}
std::stringstream readRowData(std::istream& fin)
{
std::stringstream rowStream;
std::string rowData;
if (getline(fin, rowData))
{
rowStream.str(rowData);
}
return rowStream;
}
#ifndef NDEBUG
std::ostream& operator<<(std::ostream& out, const Employee& employee)
{
out << "Name: " << employee.names << '\n';
out << "Total hours: " << employee.totalHrs << '\n';
out << "Individual hours:";
for (auto const &hours : employee.data)
{
out << ' ' << hours;
}
out << std::endl;
return out;
}
std::ostream& operator<<(std::ostream& out, const EmpList& employees)
{
auto first = true;
for (auto const &employee : employees)
{
if (first)
{
first = false;
}
else
{
out << '\n';
}
out << employee;
}
return out;
}
#endif
Now your output function is already written for you, and you just need to write your sort.

Using push_back for vector in c++

I am having trouble using push_back for vectors in c++.
My vector is named data.
In my loop I want to add 50 to data[i].getQuantity then push_back to data
These are things that I have tried.
data.push_back(data[i].getQuantity());
and
float myFloat = data[i].getQuantity() + 50;
data.push_back(data[i].getQuantity(myFloat));
data.push_back(myFloat);
The error is saying
No function to call to push_back
Here is my code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
struct Input
{
friend std::istream& operator >>(std::istream& inp, Input& item);
friend std::ostream& operator <<(std::ostream& outp, Input const& item);
std::string group;
std::string total_pay;
float quantity;
// default constructor. sets up zero-elements
Input() : group(), total_pay(), quantity()
{
}
Input(std::string groupIn, std::string total_payIn, float quantityIn) :
group(std::move(groupIn)),
total_pay(total_payIn),
quantity(quantityIn)
{
}
// Accessors
std::string const& getGroup() const { return group; }
std::string getTotalPay() const { return total_pay; }
float getQuantity() const { return quantity; }
};
// global free function for extracting an Input item from an input stream
std::istream& operator >>(std::istream& inp, Input& item)
{
return (inp >> item.group >> item.total_pay >> item.quantity);
}
// global operator for inserting to a stream
std::ostream& operator <<(std::ostream& outp, Input const& item)
{
outp
<< item.getGroup() << ", "
<< item.getTotalPay() << ", "
<< item.getQuantity();
return outp;
}
struct ctype : std::ctype<char>
{
static mask* make_table()
{
static std::vector<mask> table(classic_table(),
classic_table() + table_size);
table[','] |= space;
return &table[0];
}
ctype() : std::ctype<char>(make_table()) { }
};
int main() {
std::fstream infile("employee.dat");
std::vector<Input> data;
std::string line;
try {
while (std::getline(infile, line))
{
std::istringstream iss(line);
Input inp;
iss.imbue(std::locale(iss.getloc(), new ctype));
while (iss >> inp) // calls our extraction operator >>
data.push_back(inp);
if (iss.fail() && !iss.eof())
std::cerr << "Invalid input line: " << line << '\n';
}
// dump all of them to stdout. calls our insertion operator <<
std::copy(data.begin(), data.end(),
std::ostream_iterator<Input>(std::cout,"\n"));
std::ofstream outp("output.dat");
for(int i = 0; i < data[i].getQuantity(); i++)
{
float myFloat = data[i].getQuantity() + 50;
data.push_back(myFloat);
outp << data[i].getGroup() << ',' << data[i].getTotalPay() << ',' << data[i].getQuantity() + 50 << '\n';
}
} catch (std::exception& e) {
std::cout << "There was an error: " << '\n';
return 1;
}
return 0;
}
Your vector is of type std::vector<Input>. That means you can only put objects of type Input into it. You can't push_back a float into such a vector.
If your intention is to create a new Input object and push that back into your vector, you could do something like
data.push_back(Input(data[i].getGroup(), data[i].getTotalPay(), data[i].getQuantity() + 50))
On the other hand, if you are simply trying to modify an element in data without adding a new element to data, you could just do
data[i].quantity += 50;
This works because you use a struct rather than a class. In a struct, variables default privacy level is public. If you wanted to use a class, or you just don't want to directly access the struct members, you would have to create a setter function for quantity.

C++: How to save classes having pointers as member in file?

For example the following class:
class example
{
public:
int *numbers;//int pointer
int size;
example(int s)
{
size=s;
numbers=new int [size];
}
~example()
{
delete []numbers;
}
}
How can this class be stored in a file ?
There is no easy solution to this question - simply put pointers represent a location in memory but when you restore data from the file you expect it to be stored somewhere else (i.e. not in the original location) so storing the value of the pointer in anyway will fail.
Instead you need to set the pointers as you load from the file to relink with the correct memory location. Generally the tactic used to handle this sort of problem is to store a numeric ID for each record - as you load the ID from the file that you need to link to you look up the ID from what is already loaded and set the pointer to that record. This process is surprisingly called pointer swizzling (thanks #keyser).
This problem is generally referred to a serialization of a class this question and this question are good places to start reading about this process on Stack Overflow.
There are widely used tools for this kind of problem; take a look at the boost::serialzation documentation.
Untested, but gives you an idea.
class Example
{
public:
vector<int> numbers;
explicit Example(int s = 0)
: numbers(s)
{
}
friend ostream& operator << (ostream& os, const Example& x)
{
os << x.numbers.size() << " ";
for (auto n : x.numbers)
{
os << n << " ";
}
if (os.bad()) ERROR;
return os;
}
friend istream& operator >> (istream& is, Example& x)
{
vector<int>::size_type size;
is >> size;
numbers.resize(size);
for (auto& n : x.numbers)
{
is >> n;
}
if (is.bad()) ERROR;
return is;
}
};
{
ofstream outfile("myfile.txt");
Example x;
outfile << x;
}
{
ifstream infile("mytext.txt");
Example x;
infile >> x;
}
You need to implement a serialization method. Any class that needs to be serialized should know how to selialize and deserialize itself. You can choose one of the common human readable formats available formats, such as JSON, XML etc. You also have the option of using more compact formats such as Google protocol buffers, Apache thrift, or msgpack. If your serilization needs are very simple, then another option is to roll out your own. Here is a full compilable version of the answer given by Neil Krik which should help your understanding . . .
#include <iostream>
#include <vector>
#include <sstream>
#include <assert.h>
#include <fstream>
using namespace std;
class Example
{
vector<int> nums;
public:
explicit Example(vector<int> s = {}) : nums(s)
{
}
vector<int>& getNums()
{
return nums;
}
vector<int> getNums() const
{
return nums;
}
string stringify() const
{
stringstream s;
for (auto x : nums) {
s << x << ", ";
}
return s.str();
}
friend ostream& operator << (ostream& os, const Example& x)
{
os << x.getNums().size() << " ";
for (auto n : x.getNums())
{
os << n << " ";
}
assert(os.good());
return os;
}
friend istream& operator >> (istream& is, Example& x)
{
vector<int>::size_type size;
is >> size;
x.getNums().resize(size);
for (auto& n : x.getNums())
{
is >> n;
}
assert(is.good());
return is;
}
};
int main()
{
// Example 1
string store;
{
ostringstream outfile;
Example x( {1,2,3,4,5,4,3,2,1} );
outfile << x;
store = outfile.str();
}
{
istringstream infile(store);
Example x;
infile >> x;
std::cout << x.stringify() << std::endl;
}
// Example 2
{
ofstream outfile("myfile.txt");
Example x( {1,2,3,4,1,2,3,4} );
outfile << x;
}
{
ifstream infile("myfile.txt");
Example x;
infile >> x;
std::cout << x.stringify() << std::endl;
}
return 0;
}
This is a very broad topic and there are many ways of solving the problem. One popular way of doing class serialization now is using Google Protocol Buffers.