Cannot find the end of an array when opening a file - c++

So I want to open a file and display the contents. Thing is, I don't know how many elements are used and how many elements are empty. So, when I try to display the elements the first few are shown but the rest are random numbers. How do I find and display the exact number of elements?
file:
10011 Ali Doha 12355555 11-5-14 3434 7890
10015 Ahmed Al-Khor 51244444 13-6-14 3425 4455
10014 Mohammed Al-Wakra 53344333 17-7-14 5566 1234
10012 Omar Doha 56666666 10-8-14 1234 5678
10013 Youssef Al-Khor 7555512 5-5-14 88000 4532
10019 Hamad Al-Wakra 81234567 8-6-14 3125 1265
10018 Jassim Doha 86753541 9-7-14 9875 5566
code:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
const int isize=10;
ifstream datafile;
datafile.open("D:\customers.txt");
int customer_number[isize];
string customer_name[isize];
string customer_address[isize];
long contact[isize];
string Due_date[isize];
int water_consumption[isize];
int electricity_consumption[isize];
double total_bill[isize];
if (!datafile)//to know if the file is exist or not
cout << "error" << endl;
else
{
for(int i=0; i<1000; i++)
{
datafile >> customer_number[i];
datafile>> customer_name[i];
datafile>> customer_address[i];
datafile>> contact[i];
datafile>> Due_date[i];
datafile>> water_consumption[i];
datafile>> electricity_consumption[i];}
}
for(int i=0; i<isize; i++)
{
if(customer_number[i] == '\0')
break;
else
cout << customer_number[i] << "\t" << customer_name[i] << "\t" << customer_address[i] << "\t" << contact[i] << "\t"
<< Due_date[i] << "\t" << water_consumption[i] << "\t" << electricity_consumption[i] << "\t" << endl;
}
datafile.close();
return 0;
}

Looks like each text line is a record, thus use std::getline with std::string to read a record.
When the number of records is unknown, you need a dynamic container, such as std::vector, std::list or std::map, not a fixed size array.
You will need to research the std::string methods and also std::istringstream for parsing the text line into native format fields. There are lots of examples on StackOverflow on how to do this.
So stop using fixed size arrays and use std::vector instead.

Related

Stringing together multiples of the same string (an asterisk) determined by an input file. C++

Essentially, the objective is to read an input file (hence inFile and inFileName) and output a population growth with asterisks representing each 1000 people using an ID (ex. 1375892), going from the year 1900 to 2020 in 20-year increments.
So, 1 asterisk for 1000 people, 3 asterisks for 3000 people, etc. The input file has numbers like 5000 and 7000 that I need to use to calculate the number of asterisks I need (by dividing by 1000). Even with that, I'm trying to figure out the final step in converting asteriskNum (the number of asterisks I need to use) and have it output the string of asterisks, not an integer of how many asterisks I need.
I definitely know I'm missing SOMETHING, but even after asking my teacher and scouring through my textbook and notes, I can't figure out how to solve this specific issue.
#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
using namespace std;
int main(){
string asterisk = "*";
string firstName;
int PopNum{0};
int year{1900};
int asteriskNum{};
const string INTROLINE{"POPULATION GROWTH \n(each * represents 1000 people)"};
cout << INTROLINE << "\n";
string inFileName="DL8_L5_Morrison.txt";
ifstream inFile{inFileName};
if (inFile){
cout << inFileName << " opened for reading. \n";
inFile >> firstName;
while (not inFile.eof()){
inFile >> PopNum;
asteriskNum = PopNum/1000;
cout << year << " " << asteriskNum << " " << << "\n";
year+=20;
inFile.close();
}
else {
cout << inFileName << " did not open for reading. \n";}
cout<<"Goodbye!\n";
return EXIT_SUCCESS;
}
}
You can use a std::string object and use the constructor that takes a count and character as arguments (constructor version #2 here). This will work with an int for the count argument, but it is better to cast it to a size_t type (or just have the calculated value as a size_t in the first place):
//...
asteriskNum = PopNum/1000;
cout << year << " " << std::string(static_cast<size_t>(asteriskNum), '*') << std::endl;
//...

How to Read Numerical, Minute and Second Values from File, While Writing Values *Exactly As Given* To Other File

First off, is it possible?
To extrapolate the question: I'd like to read some integers from a file, which is relatively simple for me.
However, when I read these values, which are formatted: "123 17 24 55 04 30 09" for example, my written output shows "123 17 24 55 4 30 9", where the "0" is absent before the 4, and the 9. This bothers me from a formatting aspect. How do I retain the 0 which is infront of the 4, and 9, in my output?
My current code is attached
int main() {
ifstream inf;
ofstream of;
float timeSmin, timeSsec, timeBmin, timeBsec=01.00, timeRmin=01, timeRsec=01.00;
int ID, totaltime;
inf.open ("triath.txt");
of.open ("output.txt");
if (!inf.is_open()){
cout << "Triath.txt cannot be opened, error..." << endl;
}
inf >> ID >> timeSmin >> timeSsec >> timeBmin >> timeBsec >> timeRmin >> timeRsec; //writing values to input object.
of << ID << " " << timeSmin << " " << timeSsec << " " << timeBmin << " " << timeBsec << " " << timeRmin << " " << timeRsec;
inf.close();
of.close();
return 0;
} ```
I would read the file in as a string and parse the string. That gives you the original string to use for output.
You'll need a way of splitting your input string into tokens. If you can't figure that out, you can do a google for "c++ split string by spaces" and get a bunch of good hits.
You'll need to then convert substrings into integers. Again, a google for "c++ convert string to integer" will provide some clues.
Then you just output the original string as is, and it's identical to what you originally read.

Connexion between points (type) and an integer (without struct )

I read points frome a file, I use the library Lemon (because i want to use graph later) therefore each point is represented by the type : dim2 :: Point .
so I used the library lemon/dim2.h
My problem is that each point there have a number of the frame of the video, so i used this code to put variables from file in a vectors:
std::ifstream file("file1.txt");
std::vector<dim2::Point<int>> pointTable;
std::vector<int> frame;
int temp, temp2,temp3;
while (file >> temp >> temp2 >> temp3)
{
pointTable.push_back(dim2::Point<int>(temp, temp2));
frame.push_back(temp3);
}
//int tailleFmax = frame.max_size;
for (int i = 0; i < (36) ;i++)
//cout << frame[i] <<endl;
// cout << trajectoire[i].x << endl;
cout << trajectoire[i].y << endl;
My question : i dont know how to represent in c++ the connection betwen each point and his frame number and name this variable Trajectory.
Example of file :
155 // that is x
168 // that is y
0 // that is the frame number
364
245
20
546
156
I suspect that a map<int, dim2::Point<int>> is what you're looking for.
You could also simplify your code by reading in the point directly using dim2::Point's extraction operator: http://lemon.cs.elte.hu/pub/doc/latest-svn/a00862.html#g2dd3eccf5dece76c03bc6d1c2f348643
Your final code should look something like this:
ifstream file("file1.txt");
map<int, dim2::Point<int>> frame2PointTable;
pair<int, dim2::Point<int>> temp;
while(file >> temp.second >> temp.first) frame2PointTable.insert(temp);
To output this you could do something like:
for(const auto& i : frame2PointTable) cout << i.first << ": (" << i.second.x << ", " << i.second.y << ")\n";
Important notes:
Your example file contains 3 points but only 2 frame numbers, in this case only the 2 frame number-point combinations would be inserted
If you ever have multiple identical frame numbers in a file, only the first instance will be accepted by frame2PointTable
I've written you a live example using pair<int, int> instead of dim2::Point here: http://ideone.com/qtCZ8L

C++ output formatting using setw and setfill

In this code, I want to have numbers printed in special format starting from 0 to 1000 preceding a fixed text, like this:
Test 001
Test 002
Test 003
...
Test 999
But, I don't like to display it as
Test 1
Test 2
...
Test 10
...
Test 999
What is wrong with the following C++ program making it fail to do the aforementioned job?
#include<iostream>
#include<string>
#include<fstream>
#include<iomanip>
using namespace std;
const string TEXT = "Test: ";
int main()
{
const int MAX = 1000;
ofstream oFile;
oFile.open("output.txt");
for (int i = 0; i < MAX; i++) {
oFile << std::setfill('0')<< std::setw(3) ;
oFile << TEXT << i << endl;
}
return 0;
}
The setfill and setw manipulators is for the next output operation only. So in your case you set it for the output of TEXT.
Instead do e.g.
oFile << TEXT << std::setfill('0') << std::setw(3) << i << endl;

C++ text file into multi-dimensional array problems

As part of a school project, I would like to get an inventory *.txt file into an array in C++ and eventually back to a *.txt file at a later part in the program.
The text file will start out with 10 rows that will represent grocery story items and will include three columns that represent the name, price, and quantity of the items. I have been able to read from the file, even add numbers in front of each row that is displayed. Now, I would like to get the text file into a string array so that the "employee" user can make changes to items one at a time and then I can dump that array back into a *.txt file.
The code below is what I have been trying so far. I can get the count of rows in the file, but can't seem to get the columns counted or the data in the rows displayed. When I run the program, I get what appear to be 10 empty lines after it displays the rows (10) and Cols(0).
The columns in the *.txt file are normally separated by a space. I tried a tab, and tried: while(getline(invFile, lines, '\t'); which just caused the console to display what I am guessing was a memory address and then crashed.
Unfortunately, we have not gotten very far into debugging programs, and from the look of the syllabus, I don't think that will be covered very thoroughly, so I don't know how to troubleshoot any further. I have spent the last couple of hours Google-ing, and have gotten to the point that I actually need to ask for help.
The project involves a lot more than this component, but I really am stuck on this part. I am not asking for someone to do this for me, but if anyone has any idea what I am doing wrong and can point me in the best direction to get a text file into a multi-dimensional array, I would really appreciate it.
Thank you.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
int row = 0;
int col = 0;
using namespace std;
int main()
{
string lines;
int x;
string textArray[2][2];
ifstream invFile;
invFile.open("inventory.txt");
if(invFile.fail()){
cerr << "The file cannot be opened!";
exit(1);
}
cout << "\n" << endl;
while(invFile.good()) {
while(getline(invFile, lines)) {
istringstream streamA(lines);
col = 0;
while(streamA >> x) {
cout << x;
textArray[row][col] = x;
col++;
}
row++;
}
}
invFile.close();
cout << "Rows: " << row << endl;
cout << "Cols: " << col << endl;
cout << "\n" << endl;
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
cout << "Line: " << i << textArray[i][j] << ".";
}
cout << "\n";
}
return(0);
}
=============================
inventory.txt:
Apples 1.25 20
Oranges 1.75 20
Kiwi 2.50 15
Pineapples 5.50 20
Tomatoes 1.50 20
Onions 2.00 20
Corn 1.80 20
Carrots 2.30 20
Milk 4.50 20
Cheese 2.25 20
I would suggest that you create a struct or class to hold the data. From each line of text, extract the fields appropriately and them to your struct. Then, keep a list of those structs using std::vector.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
#include <vector>
#include <cstdlib>
using namespace std;
struct Row
{
vector<string> columns;
};
int main()
{
string line;
vector<Row> rows;
ifstream invFile;
invFile.open("inventory.txt");
if(invFile.fail()){
cerr << "The file cannot be opened!";
exit(1);
}
cout << "\n" << endl;
while(invFile.good()) {
while(getline(invFile, line))
{
Row row;
istringstream streamA(line);
string col;
while ( streamA >> col )
{
row.columns.push_back(col);
}
rows.push_back(row);
}
}
invFile.close();
cout << "Rows: " << rows.size() << endl;
cout << "Cols: " << rows[0].columns.size() << endl;
cout << "\n" << endl;
for(int i=0; i<rows.size(); i++){
for(int j=0; j<rows[i].columns.size(); j++){
cout << "Line: " << i << " " << rows[i].columns[j] << "\n";
}
cout << "\n";
}
return(0);
}
I'd like to suggest you add some print lines in the important step -- which I think also is a fast&good "debug" method. So that you can find where you wrong easily.
For example in your code, seems textArray wasn't assigned, so add some print nearby:
while(getline(invFile, lines)) {
cout <<"lines: " << lines << endl; //test enter here
istringstream streamA(lines);
col = 0;
while(streamA >> x) {
cout << "x is" << x; //test if enter here
textArray[row][col] = x;
col++;
}
row++;
}
Through the output, the lines is ok but cout << "x is" << x; wasn't printed, which means the while(streamA >>x) condition is false, why?
Go to find the library function called, std::istringstream x is int type but col 1 value is Apples, operator << will return NULL, it's unreasonable assing Apples to an int, till now, found point 1. If have to use int or float to store the numbers, use some convert API like atoi, atof.
After change x from int to string, got segmentation falut, it's obviously that textArray[2][2] is not enough to store all the information. "Out of range" is the reason of segmentation fault, so make a large array to test continue until passed.
There's a couple ways you could do this. The easiest would be to just put something like 3,10 at the top of the file, and then you know three columns and 10 rows. Since your writing this after modification, you would just need to make sure that those numbers get written correctly.
If you want to learn some more advanced methods, then your life will be easier AFTER you learn a bunch more.
If you used a vector, using something like vector< vector<string> > you could just read to a stringstream and then split the line read and put it into the vector
fstream file(...);
string tempString;
vector< vector<string> > list;
// Get a full line
while(getline(file, tempString, '\n'){
// Create a StringStream and store tempString in it for further manipulation
stringstream ss;
ss << tempString;
vector<string> tempVec;
// Get each column from this row
while(getline(ss, tempString, '\t'){
// Put each column into a vector
tempVec.push_back(tempString);
}
// Put the entire vector into our list vector
list.push_back(tempVec);
}
The benefit of this second method is twofold. First, it's very easy. I'm guessing you don't know how it works, but some easy Google searches on keywords you don't know, and you'll find out fast enough. The second is it allows (theoretically) unlimited rows, and unconstrained columns. By that, I mean one row could have 20 columns, one could have 2, and there would be no wasted space.
Note that you should NOT use the skeleton code I showed before researching it. If you don't have at least a general idea of what is happening here, then you'll just cause problems for yourself later on. I'm not going to explain everything here, because other people have done that already. Also, since you're learning this in school, you'll get to these things eventually, so you'll just be getting ahead. The one main constraint would be if your project requires arrays, in which case, my first solution would be the best option.