Loading Data from File to Data Structure in C++ and Interpreting It - c++

Okay so this code is killing me.
My goal is to read data from a file where the data is separated by commas, then load that data into an array of structures that is supposed to be a list of "theater seats". The theater seats have certain characteristics, such as "location", "price", and "status". Price is self-explanatory. Location deals with the row and seat number of the "Seat". And status pertains to whether or not it's sold. After that, I have to interpret the data that I pulled from the data file to make a display THAT CAN be easily manipulated by the user if they input a certain choice. But that's not what I'm getting at in this question.
My question is, what would be the best method to load my data structures from the data file?
Let me show you a bit of the data file that I'm reading from.
1, 1, 50, 0
1, 2, 50, 0
1, 3, 50, 0
1, 4, 50, 0
To explain the data file, the first number is the "row", second number is the seat number in that row, the third number is the price, and the final number ("0") stands for the seat being unsold. Had the seat been purchased, the final number would be 1.
Now, here's my code.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <cstdio>
#include <conio.h>
using namespace std;
enum seatDimensions{ROWS = 10, SEATS_PER = 16};
//Structures
struct Location
{
int row;
int seatNumber;
};
struct Seat
{
Location seat_location[160];
double ticketPrice;
int status;
int patronID;
};
//GLOBALS
const int MAX = 16;
int main()
{
//arrays for our data
Seat seatList[160];
//INDEX
int index = 1;
//filestream
fstream dataIn;
dataIn.open("huntington_data.dat",ios::in);
if(dataIn.fail()) //same as if(dataIn.fail())
{
cout << "Unable to access the data file." << endl;
return 999;
}
string temp;
getline(dataIn,temp,',');
seatList[index].seat_location[index].row = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].seat_location[index].seatNumber = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].ticketPrice = atof(temp.c_str());
getline(dataIn,temp,'\n');
seatList[index].status = atoi(temp.c_str());
while(!dataIn.eof() && index < MAX)
{
index++;
getline(dataIn,temp,',');
seatList[index].seat_location[index].row = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].seat_location[index].seatNumber = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].ticketPrice = atof(temp.c_str());
getline(dataIn,temp,'\n');
seatList[index].status = atoi(temp.c_str());
}
getch ();
return 0;
}
Now from here, I have to display whether or not the seats are TAKEN or not.
The display should look like this, since none of the seats are taken yet.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 // 16 across
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
// 10 deep
I know I'm not inputting my data in correctly, because I cannot seem to get this display no matter how I try to cout it. If you can tell where I'm going wrong, please tell me. Any suggestions would be amazing.
Also, if you have any questions for me, just ask. I tried to be as specific as possible considering the question, but I know that it's still pretty vague.
Please help.
EDIT: Thanks to those who answered my question. I ended up going a very different route with my data structure, but pulled a lot from the answers.

You have the problem that each seat has a position in an array and then has an array of positions:
You need:
Location seat_location[160];
changed to:
int seat_row;
int seal_num;
then:
seatList[index].seat_location[index].row = atoi(temp.c_str());
becomes:
seatList[index].seat_row = index / COLS ;
seatList[index].seat_num = index % COLS ;
You may also like to consider actually arranging your data into a 2D array of the same dimensions as your seating.
BTW From my C background I would suggest reading the whole line and using sscanf, e.g.:
char temp[255]; // Use an appropriate maximum line length +3 for \r\n\0
fgets(dataIn, &temp);
sscanf(temp, "%d, %d, %d, %d", &.....
You could also consider implementing this with a regular expression.

Write a function that gets string of input and splits it into items:
std::vector<std::string> splitLine( const std::string &str );
Implement and debug it with string like "1, 1, 50, 0", make sure it returns vector of string with each number as separate element. Then read input line by line, split and convert each string to number separately. You will simplify the code and it will be much easier to make it work.

is it an assignment?
i guess the way you are organizing your data in structure needs to be changed.
Take a structure maybe like this
struct Seat{
double ticketPrice;
int status;
int patronId;
}
and have a two dimensional array like this
Seat seatList[10][16];
first dimension is (row number-1), second dimension is (seat number-1)
and read your data from file like this
string temp;
getline(dataIn,temp,',');
int row = atoi(temp.c_str());
getline(dataIn,temp,',');
int seatNumber = atoi(temp.c_str());
getline(dataIn,temp,',');
//check row and seatnumber > 0
seatList[row-1][seatNumber-1].ticketPrice = atof(temp.c_str());
getline(dataIn,temp,'\n');
seatList[row-1][seatNumber-1].status = atoi(temp.c_str());
Use two simple for loops to print your output from these structures.

Related

Is there a better way to extract the n-th element of a stringstream than ignore in a loop?

I want to extract the n-th element of an std::istringstream. Right now I'm using a loop with std::istringstream::ignore, something like this:
std::istringstream linestream(line);
for (int i=0; i < n; i++) {
linestream.ignore(50, ' ');
}
linestream >> importantVariable;
The input is a process stat file on linux from /proc/$PID/stat and is comma seperated, but the fields do not have a fixed width (std::seekg won't work reliably here).
Is there a better way to do this? I was expecting something like an overloaded ignore method, that takes an argument which defines how many elements it should skip, instead of having to use a loop.
Edit: I've added information about the input stream.
Here is an example line:
1092 (avahi-daemon) S 1071 1071 1071 0 -1 1077936192 30 0 0 0 0 0 0 0 20 0 1 0 534 48205824 85 18446744073709551615 1 1 0 0 0 0 0 0 0 0 0 0 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0
Basically all said in the comments.
I just one to show an additional solution. The input data is anyway stored in a std::string. So you can directly extract it from there.
You can use iterators and std::next instead of loops.
The same works of course also for streams.
please see
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
#include <sstream>
const std::regex re(" ");
int main() {
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
std::string line{ "1092 (avahi - daemon) S 1071 1071 1071 0 - 1 1077936192 30 0 0 0 0 0 0 0 20 0 1 0 534 48205824 "
"85 18446744073709551615 1 1 0 0 0 0 0 0 0 0 0 0 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 "};
// 1. Extracting direcly from std::string
std::string entry24 = *std::next(std::sregex_token_iterator(line.begin(), line.end(), re, -1), 24);
std::cout << entry24 << "\n";
// 2. Putting in Stream and extracting from stream
// Stream solution
std::istringstream linestream(line);
entry24 = *std::next(std::istream_iterator<std::string>(linestream), 24);
std::cout << entry24 << "\n";
return 0;
}

print cv::Mat element -- OpenCV(C++)

I am trying to loop over a matrix and print its element, which should be a simple operation, but I experience some strange things...
I have a a null matrix :
cv::Mat accum = cv::Mat::zeros(3,5,CV_8U);
Doing this:
for(int i=0;i<accum.rows;i++)
{
for(int j=0;j<accum.cols;j++)
{
cout<<accum.at<int>(i,j) <<endl;
}
}
I get the following elements:
0
0
0
0
0
0
0
0
0
-536870912
0
0
0
2027945984
587217671
Why is there some random number at places where zero should be?
If I initialize the value of matrix at i=1,j=1 with number 1, I get the following
0
0
256
0
0
0
1
0
0
587202560
0
0
0
1931673600
587257437
I just dont understand those random values, I might do something wrong, but cant figure out what. Could you please help?

garbage value in while printing array

I am declaring the array dynamically using new. The array is formed of string length, which I am giving from the user. When I am providing a string of length between 7-11 the array is printing garbage value. Why is it happening?
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<ctime>
#include<map>
using namespace std;
int main(){
string str;
cin>>str;
int i,j;
int** arr = new int*[str.length()];
for(i = 0; i < str.length(); ++i)
arr[i] = new int[str.length()];
for(i=0;i<str.length();i++){
for(j=0;j<str.length();j++){
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
The output for string "BBABCBCAB" is:
36397056 0 8 0 -1 0 1111573058 1094926915 0
0 0 4 0 -1 0 1111573058 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
Why is it happening ? And not for other any string with more than length 12?
You're default-initializing all your ints, which doesn't actually assign them a value. Reading from an indeterminate value is undefined behavior - sometimes you get 0s, sometimes you get some weird values. Undefined behavior is undefined.
If you want all 0s, you need to value-initialize the array:
arr[i] = new int[str.length()]();
// ^^
Or use something like memset or std::fill or std::fill_n.

conway game error with 2d array manipulation

So I'm working on the life game, and so far I have come up with this http://ideone.com/QG4tsS I'm not sure exactly if I am on the right track or not. Basically I have a function putting out random values to try and test my code. But nothing seems to happen. I suspect my problem lies with the following code
int sum = 0;
for (int k = (i - 1); k <= (i + 1); k++) {
for (int l = (j - 1); l <= (j + 1); l++) {
sum += currentGen[k][l];
}
}
return sum;
So my result gives me a 2d array with all 0's but shouldn't I start to see some changes and patterns starting to form? I get one 1 and the rest are 0.
Output
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
I provide this answer based on the code you posted at http://ideone.com/QG4tsS . You really should consider adding that code to your original question, so that future folks who find this on StackOverflow have the full context.
Your RandomCells function only sets cells to 1 if they meet the RANDOM threshold. It doesn't clear them to 0 otherwise. Once you fix that, you'll be all set. ie.
void RandomCells(int currentGen[][CELLY]) {
for (int i = 0; i < CELLX; i++) {
for (int j = 0; j < CELLY; j++) {
if (rand() % 100 + 1 < RANDOM) {
currentGen[i][j] = 1;
} else
{
currentGen[i][j] = 0;
}
}
}
}
Without that else clause, I was seeing initial generations that looked like this:
0 0 4196155 1
1813657216 1 4197653 0
-870503576 1 4197584 1
Clearly, most of those cells were non-zero, and so Conway's Life algorithm would map them to 0 in the next generation because of "crowding".
The reason currentGen was filled with such 'random' values is that it was allocated as an automatic variable to main. Automatic variables do not get initialized to any particular value. You need to initialize them yourself. You can do that by modifying your algorithm (as I did above), or by adding an explicit bit of code to initialize the structure.
This differs from file-scope variables, which C and C++ define as initialized-to-zero on program start if they don't have initializers or default constructors. (Pedants will point out that even that has caveats.)
Once you make the required fixes, to truly see Conway's Life, you'll need to set CELLX and CELLY to larger values...

Copying data file into an array

I have a project for school. They gave me a data file that needs to be in an array of 10*10. This array needs to be an upper triangle, which means that all values of and below the diagonal have to be zero. This data file is the time that a project takes by every stage. It means that every [i][j] represents the time for stage from i to j.
Just to make it more complicated the problem ask you to find the longest time per column and add it to the longest time in the next column.
here is my code so far:
#include <iostream>
#include<iomanip>
#include <fstream>
#include <cmath>
using namespace std;
//Function prototype
int minCompletionTime (int Data[], int numTasks);
int main()
{
//Declaring and initializing variables
int num_Events(0), completion_Time(0);
int startSearch(0), endSearch(0);
const int SIZE(10);
char datch;
//Declaring an array to hold the duration of each composite activity
int rows(0),duration_Data [10];
//Declaring an input filestream and attaching it to the data file
ifstream dataFile;
dataFile.open("duration.dat");
//Reading the data file and inputting it to the array. Reads until eof
//marker is read
while (!dataFile.eof())
{
//Declaring an index variable for the array
//Reading data into elements of the array
dataFile >> duration_Data[rows];
//Incrementing the index variable
rows++;
}
//Taking input for the number of events in the project
cout << "Enter the number of events in the project >>> ";
cin >> num_Events;
//Calling the function to calculate the minimum completion time
completion_Time = minCompletionTime(duration_Data, num_Events);
//Outputting the minimum completion time
cout << "The minimum time to complete this project is " << completion_Time
<< "." << endl;
}
int minCompletionTime (int Data[], int numTasks)
{
int sum=0;
//As long as the index variable is less than the number of tasks to be
//completed, the time to complete the task stored in each cell will be
//added to a sum variable
for (int Idx=0; Idx < numTasks ; Idx++)
{
sum += Data[Idx];
}
return sum;
}
Any help will be appreciated
My data file only has 6 elements that holds this elements: 9 8 0 0 7 5
my data should look like this in order to start doing operations.
0 0 0 0 0 0 0 0 0 0
0 0 9 8 0 0 0 0 0 0
0 0 0 0 7 0 0 0 0 0
0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
It is a little confusing. I am sorry. The first and second column should have values of zero and first row the same way. after fifth row should be all zeros as well since it will be filled with more information from other data file.
There are a few ways of solving this problem. Here are 2 very naive ways:
1. Use a 10x10 array:
Read everything in from the data file (dataFile >> data[row][col]).
Have 2 nested loops:
The outer loop iterates over columns.
The inner loop iterates over the rows of that specific column.
Since you have to find the max and the values under the diagonal is zero, you can just be lazy and find the max of each column (you might have trouble if it's a lot larger than 10x10). However, if you want to only go through the rows that are necessary, I'll let you figure it out (it's very simple, don't over think).
2. Only use a 1x10 array:
Initialize the array with the minimal value (0 or -1 should work for you), let's call it the max_row.
Read item by item on each row, and compare it to the value that's stored in the max_row and replace appropriately.
When you're done, just sum up the elements in max_row.