Passing array values using pointer - c++

I have two functions one is for file reading and another one for little sorting of numbers. With function read() I am reading file's each line and put each line into array. File looks like:
1
2
3
With function sort() I want to print only numbers with value greater than 1.
What is wrong: I got printed two arrays, but my sort array still printing all values, not only greater than 1.
My code:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
class UZD
{
private:
int numLines;
int *value;
public:
UZD();
int * read();
int sort();
};
// =========================================================
UZD::UZD()
{
}
// =========================================================
int * UZD::read(){
ifstream myfile("stu.txt");
int value[20];
string line[20];
int i=0;
while(!myfile.eof() && i < 20) {
getline(myfile,line[i]);
++i;
}
numLines = i;
for (i=0; i < numLines; ++i) {
value[i] = atoi(line[i].c_str());
cout << i << ". " << value[i]<<'\n';
}
return value;
}
// =========================================================
int UZD::sort(){
int *p;
p = read();
int i;
if(p[i] > 1) {
cout << p <<'\n';
}
}
// =========================================================
int main() {
UZD wow;
wow.read();
wow.sort();
}

There are many issues in your code, the most obvious one is "return value" in the read() method. Value is a local array and will be gone once out of scope of read(). Also the design seems faulty. You are calling read() twice, once from the main() and again internally from sort().
I have written a working code, using vectors. Probably this is what you are expecting:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
class UZD
{
private:
int numLines;
vector<int> value;
public:
UZD();
vector<int> & read();
void sort();
};
// =========================================================
UZD::UZD()
{
}
// =========================================================
vector<int> & UZD::read(){
ifstream myfile("stu.txt");
vector<string> line(20);
int i=0;
while(!myfile.eof() && i < 20) {
getline(myfile,line[i]);
++i;
}
numLines = i;
cout << "After reading file: " << endl;
for (i=0; i < numLines; ++i) {
value.push_back(atoi(line[i].c_str()));
cout << i << ". " << value[i]<<'\n';
}
return value;
}
// =========================================================
void UZD::sort(){
cout << "Inside sort()" << endl;
for(int i=0; i<value.size(); ++i){
if(value[i] > 1)
cout << value[i] << endl;
}
}
// =========================================================
int main() {
UZD wow;
wow.read();
wow.sort();
return 0;
}
I have kept the variable names same for clarity. Let me know if you don't get anything.

There are a lot of issues in your program; just to mention some of them:
In sort, you use variable i uninitialized, which is undefined behaviour (probably crashes); You write while(!myfile.eof()..., which is usually considered wrong (see this SO answer; The use of atoi is not recommended, as it is not safe if the parameter does not represent a number; You return a pointer to a local variable, which is destroyed one going out of scope; You declare member variables, but pass through local ones (e.g. value)...
See the following code which demonstrates the usage of int* and a vector<int>; hope it helps.
class UZD
{
private:
int numLines;
int *value = nullptr;
public:
~UZD() {
if (value)
delete value;
};
void read();
void print();
};
// =========================================================
void UZD::read(){
ifstream myfile("stu.txt");
value = new int[20];
int val;
numLines = 0;
while(numLines < 20 && myfile >> val) {
value[numLines] = val;
numLines++;
}
}
// =========================================================
void UZD::print(){
for (int i=0; i<numLines; i++)
cout << value[i] << endl;
}
class UZD_vector
{
private:
vector<int> values;
public:
void read();
void print();
};
// =========================================================
void UZD_vector::read(){
ifstream myfile("stu.txt");
int val;
while(myfile >> val) {
values.push_back(val);
}
}
// =========================================================
void UZD_vector::print(){
for (auto val : values)
cout << val << endl;
}
// =========================================================
int main() {
cout << "with int[]:" << endl;
UZD wow;
wow.read();
wow.print();
cout << "with vector:" << endl;
UZD wow_vector;
wow_vector.read();
wow_vector.print();
}

Here is your own code rectified, just in case you find vectors too difficult to learn (which should not be true, though)
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
class UZD
{
private:
int numLines;
int *value;
int num;
public:
UZD();
void read();
void sort();
};
// =========================================================
UZD::UZD():num(20)
{}
// =========================================================
void UZD::read(){
ifstream myfile("stu.txt");
value = new int[num];
string line[num];
int i=0;
while(!myfile.eof() && i < num) {
getline(myfile,line[i]);
++i;
}
numLines = i;
for (i=0; i < numLines; ++i) {
value[i] = atoi(line[i].c_str());
cout << i << ". " << value[i]<<'\n';
}
}
// =========================================================
void UZD::sort(){
cout << "After sorting: " << endl;
for (int i = 0; i < num; ++i) {
if(value[i] > 1)
cout << value[i] << endl;
}
}
// =========================================================
int main() {
UZD wow;
wow.read();
wow.sort();
return 0;
}

Related

Struct doesn't print with cout

I'm trying to print the structure in an array whose int prejetih member is highest.
#include <iostream>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(Tekma tekme[]) {
int maksi = 0, index = 0;
for (int i = 0;i < 2;i++) {
if (maksi < tekme[i].prejetih) {
index = i;
maksi = tekme[i].prejetih;
}
}
return tekme[index];
}
void vpis(Tekma tekme[]) {
for (int i = 0;i < 2;i++)
cin >> tekme[i].prejetih;
}
int main() {
Tekma tekme[2];
vpis(tekme);
cout << najvec_kosev(tekme);
}
The compiler reports
C++ no operator matches these operands
operand types are: std::ostream << Tekma
over cout << najvec_kosev(tekme);
Here using a solution with std::vector and fixing your cout problem:
#include <iostream>
#include <vector>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(vector<Tekma>& tekme) {
Tekma lowest = tekme[0]
for(auto& t : tekme) {
if(lowest.prejetih < t.prejetih) {
lowest = t;
}
}
return lowest ;
}
void vpis(vector<Tekma>& tekme) {
int input;
while(true) {
cin >> input;
// Check if the input is valid else quit the loop.
if(input == valid) {
Tekma newStruct = {input};
tekme.push(newStruct);
}
else {
// Stop the loop
break;
}
}
}
int main() {
vector<Tekma> tekme;
vpis(tekme);
cout << najvec_kosev(tekme).prejetih; // This fixes your error.
}

C++ Creating Lottery Guessing Program

Okay so the project is to create a lottery number composed of 10 random positive integers and the user is suppose to guess it until the user guesses the correct number. All of my code looks good but when I run the program and enter in a number it gives me this MSVS Runtime Library error? I dont even know what it means as I am fairly new to programming. Help would be very appreciated!
Main.cpp
#include <iostream>
#include <cmath>
#include <ctime>
#include "Lottery.h"
using namespace std;
int main() {
const int size = 9; //declare variables
int win[size];
int g;
srand(time(NULL));
assign(win, size);
draw(win, size);
g = entry();
if (check(win,size,g) == true) {
cout << "Congradulations! You have won the lottery!" << endl;
}
else {
cout << "Try again!" << endl;
}
printOut(g);
}
Lottery.cpp
#include <iostream>
#include <cmath>
#include "Lottery.h"
using namespace std;
int entry() {
int guess;
cout << "Enter a number from 0 to 99." << endl;
cin >> guess;
return guess;
}
void assign(int w[], int s) {
for (int i = 0; i < s; i++) {
w[s] = -1;
}
}
bool check(int w[], int s, int g) {
for (int i = 0; i < s; i++) {
if (g == w[i]) {
return true;
}
}
return false;
}
void draw(int w[], int s) {
for (int i = 0; i < s; i++) {
int tmp = rand() % 100;
if (check(w, s, tmp)) {
i--;
}
else
w[i] = tmp;
}
}
void printOut(int g) {
cout << "Numbers you have chosen:" << " " << g << endl;
}
Lottery.h
#ifndef LOTTERY_INCLUDED
#define LOTTERY_INCLUDED
void assign(int[], int);
bool check(int[], int, int);
void draw(int[], int);
int entry();
void printOut(int);
#endif //LOTTERY
Debugging tutorials are available elsewhere. But if something bad happens, don't panic and look for instructions.
First, your runtime error:
This has a link "Break and open exception settings" link or a "Break" button. Break which will take you to the end of main if you click it.
The details say we did something bad near win.
Look at this:
void assign(int w[], int s) {
for (int i = 0; i < s; i++) {
w[s] = -1; //<------Oh oops!
}
}
We know the length of the array is s i.e. 9, and are using w[s] where we clearly meant w[i].
The extra details in the error are telling you a possible place to look.

Reference array from class in an other class

I'm writing a program that converts decimal numbers into binary, octal and hexadecimal. I'm doing each conversion in different class, but i want to use the binary form of the number which is stored in an array(bin[31]) inside the 1st class. Is there a way to use that array in my other classes? My teacher said i should use references, but i don't know how to do it. My files are:
Binary.h
#ifndef BINARY_H
#define BINARY_H
class Binary{
public:
int num_;
static int bin[31];
int i;
int x;
Binary();
void Set(int temp);
int Get();
void ChangeToBinary();
void ChangeToBinaryComplement();
void TwoComplement();
void PrintBinary();
~Binary();
};
# endif
Binary.cpp
#include <stdio.h>
#include <iostream>
#include "Binary.h"
#include "Octal.h"
using namespace std;
Binary::Binary(){
}
void Binary::Set(int temp){
num_ = temp;
}
int Binary::Get(){
return num_;
}
void Binary::ChangeToBinary(){
x = 1;
for (i=0;i<30;i++){
x*=2;
}
for (i = 0; i<31;i++){
if (num_ -x >= 0){
bin[i] = 1;
num_ = num_ -x;
}
else{
kettes[i] = 0;
} x=x/2;
}
}
void Binary::ChangeToBinaryComplement(){
for (i=0;i<31;i++){
if (bin[i] ==0){
bin[i] = 1;
}
else {
bin[i] = 0;
}
}
}
void Binary::TwoComplement(){
for(i=30;i>0;i--){
if(bin[i] == 0){
bin[i] = 1;
break;
} else{
bin[i] = 0;
}
}
}
void Binary::PrintBinary(){
for (i=0;i<31;i++){
cout << bin[i];
}
cout << " " << endl;
}
Binary::~Binary()
{
}
Octal.h
#ifndef OCTAL_H
#define OCTAL_H
class Octal{
private:
int* oct_ = new int[10];
int i;
public:
Octal();
void ConvertToOctal();
void PrintOctal();
~Octal();
};
#endif
Octal.cpp
#include <stdio.h>
#include <iostream>
#include "Binary.h"
#include "Octal.h"
using namespace std;
Octal::Octal()
{
}
void Octal::ConvertToOctal(){
int k = 0;
int z = 0;
int o = 0;
for(i=0;i<31;i++){
if((help[i] ==1) && (k==0)){
z = z + 4;
k = k + 1;
}
else if((help[i] ==1) && (k==1)){
z = z + 2;
k = k + 1;
}
else if((help[i] ==1) && (k==2)){
z = z + 1;
k = k + 1;
}
else{
k = k + 1;
}
if(k==3){
oct_[o]=z;
z=0;
k=0;
o = o + 1;
}
}
}
void Octal::PrintOctal(){
for(i=0;i<10;i++){
cout << oct_[i];
}
}
Octal::~Octal()
{
}
If you have to use your own classes
You can add a method inside the Binary class that lets you get access to the pointer to the array containing the data. The method would probably look like this:
int getData(){
return bin;
}
You can also access the array directly using Binary::bin, which will also give you a pointer to the first element of the array.
It would be much better tho if you changed the array type from int to bool or char. If you want to do it even better - use the vector< bool > template class. It's basically an array of bools. You can read about it in the C++ Reference
If you just need the funcionality
You should really just use the standard manipulators. There is no real reason to reinvent the wheel. The easiest way to do this is by inputting a number into a stream, and outputing it into a string. Like this:
#include<string> // string
#include<sstream> // stringstream
#include<iostream> // cin, cout
#include<iomanip> // setbase
using namespace std;
int main(){
int number;
cin >> number;
stringstream parser;
parser << setbase(16) << number;
string convertedNumber;
parser >> convertedNumber;
cout << endl << convertedNumber << endl;
return 0;
}
Of course you can change the base inside the setbase manipulator.

Crashing when objects are deleted

It's crashing at the very end of the main() function where it needs to delete the starters objects. The error message that pops up when I run the program says: Debug assertion failed! Expression: _BLOCK_IS_VALID(pHead->nBlockUse). How do i fix it from crashing when deleting the starters objects?
#include <iostream>
#include <fstream>
#include "olympic.h"
using namespace std;
ofstream csis;
int main() {
const int lanes = 4;
Ranker rank(lanes);
csis.open("csis.txt");
// First make a list of names and lane assignments.
Competitor* starters[lanes];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
// The race is run; now assign a time to each person.
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
// Put everyone into the ranker.
for (int i = 0; i < lanes; i++)
rank.addList(starters[i]);
// Now print out the list to make sure its right.
cout << "Competitors by lane are:" << endl;
csis << "Competitors by lane are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
// Finally, show how they finished.
cout << "Rankings by finish are:" << endl;
csis << "Rankings by finish are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for (int i = 0; i < lanes; i++)
delete starters[i];
csis.close();
}
ranker.cpp:
#include "ranker.h"
#include "competitor.h"
#include <stdlib.h>
Ranker::Ranker(int lanes) {
athlete = new Competitor*[lanes];
numAthletes = 0;
maxAthletes = lanes;
}
int Ranker::addList(Competitor* starter) {
if (numAthletes < maxAthletes && starter != NULL) {
athlete[numAthletes] = starter;
numAthletes++;
return numAthletes;
}
else
return 0;
}
Competitor* Ranker::getLane(int lane) {
for (int i = 0; i < numAthletes; i++) {
if (athlete[i]->getLane() == lane) {
return athlete[i];
}
}
return NULL;
}
Competitor* Ranker::getFinish(int position) {
switch(position) {
case 1:
return athlete[3];
break;
case 2:
return athlete[2];
break;
case 3:
return athlete[1];
break;
case 4:
return athlete[0];
break;
}
return NULL;
}
int Ranker::getFilled() {
return numAthletes;
}
Ranker::~Ranker() {
delete [] athlete;
}
competitor.h:
#ifndef _COMPETITOR_H
#define _COMPETITOR_H
class Competitor {
private:
char* name;
int lane;
double time;
public:
Competitor(char* inputName, int inputLane);
Competitor();
void setTime(double inputTime);
char* getName();
int Competitor::getLane();
double getTime();
void print();
~Competitor();
};
#endif
competitor.cpp:
#include "competitor.h"
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
Competitor::Competitor(char* inputName, int inputLane) {
name = inputName;
lane = inputLane;
}
Competitor::Competitor() {
name = 0;
lane = 0;
time = 0;
}
void Competitor::setTime(double inputTime) {
time = inputTime;
}
char* Competitor::getName() {
return name;
}
int Competitor::getLane() {
return lane;
}
double Competitor::getTime() {
return time;
}
void Competitor::print() {
cout << setw(20) << name << setw(20) << lane << setw(20) << setprecision(4) << time << endl;
}
Competitor::~Competitor() {
delete [] name;
}
Call stack:
before crash: http://i.imgur.com/d4sKbKV.png
after crash: http://i.imgur.com/C5cXth9.png
After you've added Competitor class, it seems the problem is that you delete its name in Competitor's destructor. But you assign it from string literal which can't really be deleted. I'm sure the stack trace leading to assertion will prove that.
One way of solving the problem would be using std::string to store the name.
Problem is when deleting the char* value on destructor, which is assigned with const char instead new char. So i have slightly changed the constructor to copy the const char to new char.
Competitor::Competitor(char* inputName, int charlen, int inputLane)
{
name = new char[charlen + 1];
memcpy(name , inputName, charlen );
name [charlen] = '\0';
lane = inputLane;
}

Queue Simulation problem

My program is to print the queue of information from a file but i have problem with my following code. When i run the program it keep loop. I cant figure out the problem. Any help?
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <queue>
#include <list>
using namespace std;
void simulation(ifstream &infile);
void processArrival(int *newEvent, ifstream &inFile, list<int> eventList,queue<int> printQueue);
void processDeparture(int *newEvent, list<int> eventList,queue<int> printQueue);
string name[100];
int timeAccepted[100];
int fileSize[100];
int i = 1;
int j = 1;
int currentTime;
bool checker = true;
int main(void)
{
ifstream inFile;
string fileName;
int i = 0;
inFile.open("123.txt", ios::in);
simulation(inFile);
/*while(inFile.peek() != EOF )
{
inFile>>name[i]>>timeAccepted[i]>>fileSize[i];
i++;
}
for(int s = 0; s < i; s++)
{
cout << name[s] << timeAccepted[s] << fileSize[s] <<endl;
}*/
return 0;
}
void simulation(ifstream &inFile)
{
queue<int> printQueue;
list<int> eventList;
int *newEvent;
while(inFile.peek() != '\n')
{
inFile>>name[0]>>timeAccepted[0]>>fileSize[0];
}
eventList.push_front(timeAccepted[0]);
int checkEmpty = eventList.empty();
newEvent = &eventList.front();
while(checkEmpty ==0)
{
newEvent = &eventList.front();
if(checker)
{
processArrival(newEvent, inFile, eventList, printQueue);
}
else
{
processDeparture(newEvent, eventList, printQueue);
}
checkEmpty = eventList.empty();
}
}
void processArrival(int *newEvent, ifstream &inFile, list<int> eventList,queue<int> printQueue)
{
int atFront=0;
atFront = printQueue.empty();
cout << atFront <<endl;
printQueue.push(*newEvent);
cout << printQueue.front() <<endl;
eventList.remove(*newEvent);
int temp;
if(atFront==1)
{
currentTime = *newEvent + fileSize[0];
cout << name[0] << " ## " << *newEvent << " ## " << currentTime << endl;
eventList.push_back(currentTime);
}
checker = false;
if(inFile.peek() != EOF )
{
inFile>>name[i]>>timeAccepted[i]>>fileSize[i];
eventList.push_back( timeAccepted[i] );
i++;
checker = false;
if(eventList.back() <= eventList.front())
{
temp = eventList.back();
eventList.back() = eventList.front();
eventList.front() = temp;
checker = true;
}
}
}
void processDeparture(int *newEvent, list<int> eventList,queue<int> printQueue)
{
printQueue.pop();
eventList.pop_front();
int checkEmpty = 1;
checkEmpty = printQueue.empty();
int temp;
if(checkEmpty ==0)
{
currentTime = *newEvent + fileSize[j];
cout << name[j] << " " << *newEvent << " " << currentTime << endl;
eventList.push_back(currentTime);
checker = true;
if(eventList.back() < eventList.front())
{
temp = eventList.back();
eventList.back() = eventList.front();
eventList.front() = temp;
checker = false;
}
j++;
}
}
Your processArrival and processDeparture functions are taking their eventList and printQueue arguments by value. This means that when you call them, for example in this line:
processArrival(newEvent, inFile, eventList, printQueue);
Copies of eventList and printQueue are made and passed into the processArrival function. The processArrival function then operates on those copies, and the original data is never modified. In particular, this means that the original eventList will never have any items removed from it, so it will never be empty -- it will just keep trying to process the first event over and over again.
The solution is to pass these parameters by reference. i.e. change the definition of processArrival to
void processArrival(int *newEvent, ifstream &inFile, list<int>& eventList, queue<int>& printQueue)
Note the & characters that I have inserted before eventList and printQueue. These cause references to the original data, rather than copies of the original data, to be passed into the processArival function. This means that processArrival will operate directly on the original data as you intend it to. Don't forget to make the corresponding change to processDeparture as well.