Reading from a file into an object? - c++

I have a file of the format:
3 // num of tasks in taskset1
1 2 3 //priority for each task
10 20 30 //exec time, deadline , period
23 34.5 45
23 56 98
4 // num of tasks in taskset2
1 2 4 3//priority for each task
10 20 30 //exec time, deadline , period
23 34.5 45
23 56 98
34 54 100
......
I need to read the text file directly into a structure object taskset.
struct tasks
{
double wcet;
double deadline;
double period;
int priority;
};
struct tasksets
{
tasks task[100];
double num_tasks;
} taskset[100];
I am storing the contents in an array and then into objects which works fine. But since my file size is too huge, my program gets killed. I need to do without using the huge array. And instead of 100 different objects just use one object for the taskset. Any suggestions on how to do it?
int main(int argc, char* argv[])
{
double aa[1000][1000];
int u = 0;
int v = 0;
int i = 0;
int j = 0;
int k = 0;
string temp; // a temporary variable used to store string data
vector<vector<string>> tokens;
while (getline(cin, temp))
{
v = 0;
istringstream iss(temp);
vector<string> tokens_in_line;
while (iss >> temp)
{
double temp1 = atof(temp.c_str());
aa[u][v] = temp1;
v++;
tokens_in_line.push_back(temp);
}
u++;
if (!tokens_in_line.empty())
{
tokens.push_back(tokens_in_line);
}
}
cout << "Execution started" << endl;
for (i = 0; i < u; i = i + j)
{
cout << "Task set #" << setnum << endl;
taskset[setnum].num_tasks = aa[i][0];
cout << "Number of tasks: " << taskset[setnum].num_tasks << endl;
for (k = 0; k < taskset[setnum].num_tasks; k++)
{
taskset[setnum].task[k].priority = aa[i + 1][k];
taskset[setnum].task[k].wcet = aa[i + 2 + k][0];
taskset[setnum].task[k].deadline = aa[i + 2 + k][1];
taskset[setnum].task[k].period = aa[i + 2 + k][2];
cout << "Task " << k + 1 << ":";
cout << " Priority : " << taskset[setnum].task[k].priority;
cout << " WCET : " << taskset[setnum].task[k].wcet;
cout << " Deadline : " << taskset[setnum].task[k].deadline;
cout << " Period : " << taskset[setnum].task[k].period << endl;
}
j = k + 2;
setnum++;
}
return 0;
}

Yeah you can read directly into the variables of the class with the operator >>. use getline to read into each variable. The code I used before is below for you to see ho its done. Basically you want to create a class with those variable needing to be read into and then you want to instanciate it in the class or main whichever you doing and read the file then add each variable that way. see below where p is the instanciated class with variables.
string STRING;
string floor;
string toFloor;
ifstream infile;
infile.open("passenger requests.txt");
if (!infile)
{
cout << "no good file failed! \n" << endl;
}
while (infile.good())
{
for (int i = 0; i < 49; ++i)
{
getline(infile, STRING);
//Saves the line in STRING.
infile >> p[i].time;
getline(infile, floor, ',');
infile >> p[i].fromFloor;
getline(infile, toFloor, ',');
infile >> p[i].toFloor;
}
}
infile.close();
}

As Josh already pointed out, you can read your tokens into the variable directly instead of storing them in aa. By the way, aa being a double array of arrays is not a good choice for your integer tokens anyway.
Concerning the use of fixed-size arrays and crashing your program for too large input sets, I would instead go for either a std::list or std::vector for the tasksets and append new objects as needed.
Finally, your code doesn't compile as provided, I had to add a declaration for setnum and the necessary headers.

The main problem I see in your format - you have to read all priorities for all tasks in taskset before you can actually read tasks, if you can change format to store priority for each task at the same line where other details are - it would be better, anyway here is version which use less memory than your original one:
struct task {
double wcet;
double deadline;
double period;
int priority;
};
int main(int, char**) {
task currentTask;
std::string temp; // a temporary variable used to store string data
while (std::getline(std::cin, temp)) {
const int taskCount = atoi(temp.c_str()); // read number of tasks
// parse task priorities
int* priorities = new int[taskCount];
for (int i=0; i<taskCount; i++)
std::cin >> priorities[i];
// read actual tasks
for (int i=0; i<taskCount; i++) {
std::cin >> currentTask.wcet;
std::cin >> currentTask.deadline;
std::cin >> currentTask.period;
currentTask.priority = priorities[i];
std::cout << "Task " << (i + 1) << ":";
std::cout << " Priority : " << currentTask.priority;
std::cout << " WCET : " << currentTask.wcet;
std::cout << " Deadline : " << currentTask.deadline;
std::cout << " Period : " << currentTask.period << std::endl;
}
delete[] priorities;
}
return 0;
}

Related

reading csv using atof() with c++

I was stuck in this problem, I tried to read the datas from my csv file.
I will put my output and source code below.
As you can see,I'm printing the value of tmp[i] first and then I use another array to store the value in column tmp[i].
But the outputs are wrong. It's value should be the same as tmp[i].
Hoping someone can help me deal with this.
output:
69
26
54
3
69
54.1442
54.6054
54.1772
double stockp1[1000];
double stockp2[1000];
double stockp3[1000];
double stockp4[1000];
int c=0,d=0,e=0,f=0;
while (getline(inFile, line))
{
vector<string> a = _csv(line);
stockp1[c++] = atof(a[tmp[0]].c_str());
stockp2[d++] = atof(a[tmp[1]].c_str());
stockp3[f++] = atof(a[tmp[2]].c_str());
stockp4[e++] = atof(a[tmp[3]].c_str());
}
for (int i = 0; i < 4; i++)
{
cout << tmp[i] << endl;
}
cout << stockp1[0] << endl;
cout << stockp2[0] << endl;
cout << stockp3[0] << endl;
cout << stockp4[0] << endl;
}
vector<string> _csv(string s)
{
vector<string> arr;
istringstream delim(s);
string token;
int c = 0;
while (getline(delim, token, ','))
{
arr.push_back(token);
c++;
}
return arr;
}

How to add up a die roll using user inputted number of die and sides of die in C++?

I'm having trouble with my die roller program not staying within its user-set parameters when it rolls a die. The program is to:
be able to take an input in for form nDx or ndx where the d is the letter d or D.
n may or not be present. If it is, it represents the number of dice. If not, assume it is a 1.
x may or may not be present. If it is, it represents the number of sides on the die. If it is absent, assume it is a 6.
If n is absent, x must be present. If x is absent, n must be present.
Remember, you need to roll each die individually and then add up the values. Also show the individual dice if n > 1.
For example: 2d means roll 2 six-sided dice (2d6). d20 means roll one 20-sided die (1d20)
An example of my output I receive is:
Enter number of die being used:
4
Enter the number of sides:
5
results are:
4d5 = 3
7
11
13
13
----jGRASP: operation complete.
What I need is the output to be like this:
input dice code: 3d6
3d6 = 4 + 2 + 5 = 11
I'm terribly bad at coding this, so please go easy on me. This is what I currently have:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int dice (int nrDice, int nrSides)
{
int result = 0;
for (int i = 0; i < nrDice; i++)
{
result += ((rand()% nrSides) + 1);
cout << result << endl;
}
return result;
}
int main ()
{
int nrDice = 1, nrSides;
srand(time(0));
cout << "Enter number of die being used: " << endl;
cin >> nrDice;
cout << "Enter the number of sides: " << endl;
cin >> nrSides;
cout << nrDice << "d" << nrSides << " = " << dice (nrDice, nrSides) << endl;
return 0;
}
You just need to output your roll, not cumulative sum:
int dice (int nrDice, int nrSides)
{
const char* sep = "";
int result = 0;
for (int i = 0; i < nrDice; i++)
{
int roll = ((rand()% nrSides) + 1);
result += roll;
std::cout << sep << roll;
sep = " + "
}
std::cout << result << endl;
return result;
}
Demo
You already create function :) which is good.
Now, try that function has one purpose, print or roll die.
std::vector<int> dice (int nrDice, int nrSides)
{
std::vector<int> result;
for (int i = 0; i < nrDice; i++)
{
result.push_back((rand() % nrSides) + 1);
}
return result;
}
void print(std::vector<int>& v, const char* separator)
{
const char* sep = "";
for (auto e : v) {
std::cout << sep << e;
sep = separator;
}
}
int accumulate(std::vector<int>& v)
{
return std::accumulate(v.begin(), v.end(), 0);
}
Demo

Need help on getting the smallest three numbers on an array

For this program a user must enter 10 contestants and the amount of second it took for them to complete a swimming race. My problem is that I must output the 1st, 2nd and 3rd placers, so I need to get the three smallest arrays (as they would be the quickest times) but I'm unsure on how to do it. Here is my code so far.
string names[10] = {};
int times[10] = { 0 };
int num[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int min1 = 0, min2 = 0, min3 = 0;
cout << "\n\n\tCrawl";
for (int i = 0; i < 10; i++)
{
cout << "\n\n\tPlease enter the name of contestant number " << num[i] << ": ";
cin >> names[i];
cout << "\n\tPlease enter the time it took for them to complete the Crawl style: ";
cin >> times[i];
while (!cin)
{
cout << "\n\tError! Please enter a valid time: ";
cin.clear();
cin.ignore();
cin >> times[i];
}
if (times[i] < times[min1])
min1 = i;
cout << "\n\n\t----------------------------------------------------------------------";
}
system("cls");
cout << "\n\n\tThe top three winners of the Crawl style race are as follows";
cout << "\n\n\t1st Place - " << names[min1];
cout << "\n\n\t2nd Place - " << names[min2];
cout << "\n\n\t3rd Place - " << names[min3];
}
_getch();
return 0;
}
As you can see, it is incomplete. I know how to get the smallest number, but its the second and third smallest that is giving me trouble.
your code is full of errors:
what do you do with min2 and min3 as long as you don't assign them?? they are always 0
try checking: cout << min2 << " " << min3;
also you don't initialize an array of strings like that.
why you use an array of integers for just printing number of input:
num? instead you can use i inside loop adding to it 1 each time
to solve your problem use a good way so consider using structs/clusses:
struct Athlete
{
std::string name;
int time;
};
int main()
{
Athlete theAthletes[10];
for(int i(0); i < 10; i++)
{
std::cout << "name: ";
std::getline(std::cin, theAthletes[i].name);
std::cin.sync(); // flushing the input buffer
std::cout << "time: ";
std::cin >> theAthletes[i].time;
std::cin.sync(); // flushing the input buffer
}
// sorting athletes by smaller time
for(i = 0; i < 10; i++)
for(int j(i + 1); j < 10; j++)
if(theAthletes[i].time > theAthletes[j].time)
{
Athlete tmp = theAthletes[i];
theAthletes[i] = theAthletes[j];
theAthletes[j] = tmp;
}
// printing the first three athletes
std::cout << "the first three athelets:\n\n";
std::cout << theAthletes[0].name << " : " << theAthletes[0].time << std::endl;
std::cout << theAthletes[1].name << " : " << theAthletes[1].time << std::endl;
std::cout << theAthletes[2].name << " : " << theAthletes[2].time << std::endl;
return 0;
}
I hope this will give u the expected output. But i suggest u to use some sorting alogirthms like bubble sort,quick sort etc.
#include <iostream>
#include<string>
using namespace std;
int main() {
int times[10] = { 0 };
int num[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int min1 = 0, min2 = 0, min3 = 0,m;
string names[10] ;
cout << "\n\n\tCrawl";
for (int i = 0; i < 10; i++)
{
cout << "\n\n\tPlease enter the name of contestant number " << num[i] << ": ";
cin >> names[i];
cout << names[i];
cout << "\n\tPlease enter the time it took for them to complete the Crawl style: ";
cin >> times[i];
cout<<times[i];
while (!cin)
{
cout << "\n\tError! Please enter a valid time: ";
cin.clear();
cin.ignore();
cin >> times[i];
}
if(times[i]==times[min1]){
if(times[min1]==times[min2]){
min3=i;
}else{min2 =i;}
}else if(times[i]==times[min2]){
min3=i;
}
if (times[i] < times[min1]){
min1 = i;
cout <<i;
}
int j=0;
while(j<i){
if((times[j]>times[min1])&&(times[j]<times[min2])){
min2 =j;
j++;
}
j++;
}
m=0;
while(m<i){
if((times[m]>times[min2])&&(times[m]<times[min3])){
min3 =m;
m++;
}
m++;
}
cout << "\n\n\t----------------------------------------------------------------------";
}
cout << "\n\n\tThe top three winners of the Crawl style race are as follows";
cout << "\n\n\t1st Place - " << names[min1];
cout << "\n\n\t2nd Place - " << names[min2];
cout << "\n\n\t3rd Place - " << names[min3];
return 0;
}
There is actually an algorithm in the standard library that does exactly what you need: std::partial_sort. Like others have pointed out before, to use it you need to put all the participant data into a single struct, though.
So start by defining a struct that contains all relevant data. Since it seems to me that you only use the number of the contestants in order to be able to later find the name to the swimmer with the fastest time, I'd get rid of it. Of course you could also add it back in if you like.
struct Swimmer {
int time;
std::string name;
};
Since you know that there always will be exactly 10 participants in a race, you can also go ahead and replace the C-style array by a std::array.
The code to read in the users then could look like this:
std::array<Swimmer, 10> participants;
for (auto& participant : participants) {
std::cout << "\n\n\tPlease enter the name of the next contestant: ";
std::cin >> participant.name;
std::cout << "\n\tPlease enter the time it took for them to complete the Crawl style: ";
while(true) {
if (std::cin >> participant.time) {
break;
}
std::cout << "\n\tError! Please enter a valid time: ";
std::cin.clear();
std::cin.ignore();
}
std::cout << "\n\n\t----------------------------------------------------------------------";
}
Partial sorting is now essentially a one-liner:
std::partial_sort(std::begin(participants),
std::begin(participants) + 3,
std::end(participants),
[] (auto const& p1, auto const& p2) { return p1.time < p2.time; });
Finally you can simply output the names of the first three participants in the array:
std::cout << "\n\n\tThe top three winners of the Crawl style race are as follows";
std::cout << "\n\n\t1st Place - " << participants[0].name;
std::cout << "\n\n\t2nd Place - " << participants[1].name;
std::cout << "\n\n\t3rd Place - " << participants[2].name << std::endl;
The full working code can be found on coliru.
This is not a full solution to your problem, but just meant to point you into the right direction...
#include <iostream>
#include <limits>
#include <algorithm>
using namespace std;
template <int N>
struct RememberNsmallest {
int a[N];
RememberNsmallest() { std::fill_n(a,N,std::numeric_limits<int>::max()); }
void operator()(int x){
int smallerThan = -1;
for (int i=0;i<N;i++){
if (x < a[i]) { smallerThan = i; break;}
}
if (smallerThan == -1) return;
for (int i=N-1;i>smallerThan;i--){ a[i] = a[i-1]; }
a[smallerThan] = x;
}
};
int main() {
int a[] = { 3, 5, 123, 0 ,-123, 1000};
RememberNsmallest<3> rns;
rns = std::for_each(a,a+6,rns);
std::cout << rns.a[0] << " " << rns.a[1] << " " << rns.a[2] << std::endl;
// your code goes here
return 0;
}
This will print
-123 0 3
As you need to know also the names for the best times, you should use a
struct TimeAndName {
int time;
std::string name;
}
And change the above functor to take a TimeAndName instead of the int and make it also remember the names... or come up with a different solution ;), but in any case you should use a struct similar to TimeAndName.
As your array is rather small, you could even consider to use a std::vector<TimeAndName> and sort it via std::sort by using your custom TimeAndName::operator<.

Moving elements in an array by certain amount

So I have a program that reads in a certain number of keys. An example would be
5 1 10 21 9 6 21 11 13 16 20
The text file example would be
Java 2 linux 3 fear 0 pool 2 do 0 red 1 lock. 1 I 0 random 2
I want my program to start at Java and depending on first key, which in this case is 5, would move over 5 elements leading to "red". And so on and so on. However, I have managed to read in all the data and put them into arrays, I am just having trouble figuring out how to move the pointer in the array.
Code:
#include <iostream>
#include <fstream>
using namespace std;
struct pieces {
char word[5];
int jump;
} ;
// Main Function
int main ()
{
// declare variables
int wordCount[2];
int keyCount[2];
int numKeys, numKeys2;
int numWords;
int keyAmount = 1;
int wordAmount = 23;
int keyarr[11];
pieces cypher[wordAmount];
char filename[10];
ifstream inData;
int temp[10];
//prompt user for input file
cout << " Enter file name: ";
cin >> filename;
inData.open(filename);
if(inData.is_open());
{
// read in data
for ( numKeys = numWords = 0; numKeys < keyAmount; numKeys++){
// read in num of words and keys
inData >> wordCount[numKeys] >> keyCount[numKeys];
//read in words followed by jump key
for( numWords = 0; numWords < wordAmount; numWords++){
inData >> cypher[numWords].word >> cypher[numWords].jump;
}
// read in the actual keys
for( numKeys2 = 0; numKeys2 < wordCount[numKeys]; numKeys2++){
inData >> keyarr[numKeys2];
}
}
//print out data
for( int j = 0; j < numKeys; j++){
cout << wordCount[j] << "\n";
cout << keyCount[j] << "\n";
}
cout << "\n";
for ( int i = 0; i < wordAmount; ++i){
cout << cypher[i].word << " ";
cout << cypher[i].jump << " ";
}
cout << "\nKeys: " << "\n";
for(int k = 0; k < 11; k++){
cout << keyarr[k] << " ";
}
cout << "\n";
}
inData.close();
return 0;
}

Entering data from .txt into struct array

For my c++ homework, I have an .txt document containing building information ordered like:
Building name
year built
lat coordinate
lon coordinate
ex.
Parking Deck
1993
34.2252
37.5563
Admin Building
1985
34.2356
37.5734
I have to read this into an array of my created struct:
struct list
{
char name[50];
int yearBuilt;
double latCoord;
double lonCoord;
} building;
now I've created a for loop to read in the data to my created array of type list:
list buildingnumber[SIZE]; //array for buildings
But when I try to print out the "k" earliest buildings made, it shows no data in the array
Here's my current code:
#include <iostream>
#include <fstream>
#include <istream>
#include <cstdlib>
#include <string>
using namespace std;
const int SIZE = 5000;
//struct for building type
struct list
{
char name[50];
int yearBuilt;
double latCoord;
double lonCoord;
}building;
list buildingnumber[SIZE]; //array for buildings
void InsertionSort(list buildingnumber[], int buildingsloaded)
{
int key = 0, i = 0;
for(int j = 1; j < buildingsloaded; j++)
{
key=buildingnumber[j].yearBuilt;
i=j-1;
while(buildingnumber[i].yearBuilt > key && i >= 0)
{
buildingnumber[i+1] = buildingnumber[i];
i--;
}
buildingnumber[i+1].yearBuilt = key;
}
}
int main()
{
char filePath[50];
ifstream openFile;
cout << "Enter the path of the building file: ";
cin.getline(filePath, 50);
openFile.open(filePath);
//verify if file is opened + report buildings loaded
int buildingsloaded = 0;
if(!openFile.fail())
{
while(openFile >> building.name >> building.yearBuilt >> building.latCoord >> building.lonCoord)
{
buildingsloaded++;
}
cout << buildingsloaded << " buildings have been loaded." << endl;
}
// get how many buildings user wants
int k = 0;
cout << "How many buildings are you interested in?: ";
cin >> k;
//create array
// loadKbuildings(building, buildingsloaded);
for(int i = 0; i < k; i++)
{
openFile >> buildingnumber[i].name >> buildingnumber[i].yearBuilt >> buildingnumber[i].latCoord >> buildingnumber[i].lonCoord;
}
// insertion sort
InsertionSort(buildingnumber, buildingsloaded);
// display earliest k buildings
cout << "The " << k << " oldest buildings are: " << endl;
int i = 0;
while ( i < k )
{
cout << buildingnumber[i].name << endl;
cout << "Year Built: " << buildingnumber[i].yearBuilt << endl;
cout << "Coordinates: (" << buildingnumber[i].latCoord << "," << buildingnumber[i].lonCoord << ")" << endl;
cout << endl;
i++;
}
}
The problem is here:
if(!openFile.fail())
{
while(openFile >> building.name >> building.yearBuilt >> building.latCoord >> building.lonCoord)
{
buildingsloaded++;
}
cout << buildingsloaded << " buildings have been loaded." << endl;
}
You've read all of the data already (to count the number of buildings); the next time you try to grab the data, it's gone.
You can resolve this issue by storing the buildings in an array the first scan through.
int c = 0;
if(!openFile.fail())
{
// *
while(openFile >> buildingnumber[c].name >> buildingnumber[c].yearBuilt >> buildingnumber[c].latCoord >> buildingnumber[c].lonCoord)
{
buildingsloaded++;
c++;
}
cout << buildingsloaded << " buildings have been loaded." << endl;
}
As per WhozCraig's comment, the line under the star only reads in one word for the building's name; you should use cin.getline() instead and change around the loop condition.
You should obviously also take out the data reading section below:
//create array
// loadKbuildings(building, buildingsloaded);
for(int i = 0; i < k; i++)
{
openFile >> buildingnumber[i].name >> buildingnumber[i].yearBuilt >> buildingnumber[i].latCoord >> buildingnumber[i].lonCoord;
}