C++ File I/O and Pointers - c++

I tried to create a program that uses an input file 'cardList.txt' that contains:
Schmidt, Helga
Alvarez, Ruben
Zowkowski, Aaron
Huang, Sun Lee
Einstein, Beverly
and I wanted to sort this alphabetically by last name.
main:
#include <iostream>
#include <fstream>
#include <string>
#include "insertsortFunct.h"
using namespace std;
int main(void){
ifstream inData;
ofstream outData;
const int listSize = 5;
char cardList[listSize][25];
instruct();
openFile(inData, outData);
buildList(cardList, inData);
inData.close();
sortList(cardList, listSize);
cout << endl << "Your list is sorted" << endl;
writeFile(cardList, outData);
outData.close();
return 0;
}
I defined these functions in a separate file:
#include "insertsortFunct.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
void instruct(void){
cout << "The program insertSort.cpp reads the file, cardList.txt " <<
"into an array and" << endl;
cout << "sorts the array using the selection sort algorithm." << endl;
cout << "The sorted array is written to a file named cardList.srt." <<
endl;
}
void openFile(ifstream& inputFile, ofstream& outputFile){
inputFile.open("cardsList.txt");
if(!inputFile.is_open())
exit(1);
outputFile.open("cardsList.srt");
if(!outputFile.is_open())
exit(1);
}
void buildList(char (*array)[25], ifstream& inputFile){
for (int i = 0; i < 5; i++)
inputFile >> array[i];
}
void sortList(char (*list)[25], int length){
int firstOutOfOrder, location;
char temp[25];
for (firstOutOfOrder = 1; firstOutOfOrder < length; firstOutOfOrder++){
location = firstOutOfOrder;
while ( location > 0 && list[location - 1] > list[location]){
temp[25] = list[location][25];
list[location][25] = list[location - 1][25];
list[location - 1][25] = temp[25];
location--;
}
}
}
void writeFile(char (*array)[25], ofstream& outputFile){
for (int i = 0; i < 5; i++)
outputFile << array[i];
}
However my program only prints the instruct(); statements and nothing else appears to happen. This program is supposed to a create a file cardList.srt with the sorted list and that does not appear in my directory after compiling.

Either inputFile.is_open() or outputFile.is_open() return false and hence exit() is called.

Related

OOP can't get value from a class

So I read a file in a function and set values to a class. I would like to read those same values in another function (another .cpp file) and I can't get it to work.
This is the code where I read values from .txt file. This seems to work. I can cout the value that I read.
#include "branjeDatoteke.h"
#include "parametri.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
void branjeDatoteke() {
Parametri pin[101];
string line;
ifstream myfile("pin.txt");
if (myfile.is_open())
{
for (int i = 0; i <= 100 && getline(myfile, line); i++)
{
pin[i].setPin(line);
// cout << pin[i].readPin() << endl;
//cout << line << '\n';
}
myfile.close();
// cout <<"tole more delat: "<< pin[2].readPin() << endl;
}
else cout << "Unable to open file";
}
And this is the code where I want to get the same values again, but cout is not working. I just get blank console where the cout should be.
#include <iostream>
#include "pin.h"
#include "parametri.h"
#include <string>
#include "branjeDatoteke.h"
using namespace std;
void pinPass() {
Parametri pin[101];
string pinKoda;
branjeDatoteke();
cout << pin[0].readPin() << endl;
cout << "Vnesite pin: ";
cin >> pinKoda;
for (int i = 0; i <= 100; i++) {
if (pin[i].readPin() == pinKoda) {
cout << pin[i].readPin() << endl;
cout << "KODA JE PRAVILNA" << endl;
}
else if (i > 100) {
cout << "kode ni v sistemu" << endl;
}
}
}
Assuming your Parametri class is correct, the issue is you are using local variables so they are initialised every time you call the function. They are allocated on the stack, locally for the calling function and can't be used outside of the function that declares them, at least not the way you're doing it. If you call the function twice you also have to assume all local variables must be reinitialised. One way you could solve this would be promoting your pin variable to global, like so:
// your_file_one.cpp
Parametri pin[101];
void PinPass() {
...
}
If you want to use it in another cpp file, then you have to redeclare the variable in the other file as well, like follows:
// your_file_two.cpp
extern Parametri pin[101];
The extern keyword specifies the variable was declared in another compilation unit - for simplicity let's imagine each C++ file which is not a header file as a separate compilation unit.
So your code will look like:
#include "branjeDatoteke.h"
#include "parametri.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
Parametri pin[101];
void branjeDatoteke() {
string line;
ifstream myfile("pin.txt");
if (myfile.is_open())
{
for (int i = 0; i <= 100 && getline(myfile, line); i++)
{
pin[i].setPin(line);
// cout << pin[i].readPin() << endl;
//cout << line << '\n';
}
myfile.close();
// cout <<"tole more delat: "<< pin[2].readPin() << endl;
}
else cout << "Unable to open file";
}
And
#include <iostream>
#include "pin.h"
#include "parametri.h"
#include <string>
#include "branjeDatoteke.h"
using namespace std;
extern Parametri pin[101];
void pinPass() {
string pinKoda;
branjeDatoteke();
cout << pin[0].readPin() << endl;
cout << "Vnesite pin: ";
cin >> pinKoda;
for (int i = 0; i <= 100; i++) {
if (pin[i].readPin() == pinKoda) {
cout << pin[i].readPin() << endl;
cout << "KODA JE PRAVILNA" << endl;
}
else if (i > 100) {
cout << "kode ni v sistemu" << endl;
}
}
}
There are better ways of using global variables than declaring them many times and you may want to research these if you're going to write bigger programs. Also global variables are very useful in certain instances but must not be abused as they can make bigger applications much more difficult to read and maintain.
The Parametri array in your pinPass function is empty(or more precisely , has garbage values).You call the branjeDatoteke function from within pinPass , the
branjeDatoteke function then creates it's own Parametri array (WHICH IS DIFFERENT from the one in your pinPass function),reads the values from the file and displays it via cout.
When branjeDatoteke is done with it's work , all the local variables of that function , inlcuding the Parametri array are destroyed and your program jumps back to the pinPass function.
To do what you're trying to achieve , which is , presumably , have a common array for both the functions, you can either pass the array from pinPass to branjeDatokete , or you can tell branjoDatokete to allocate an array on the heap and then return a pointer to it.I guess the first approach fits better for what you're trying to achieve.

unable to get return data from class in .hpp file

I have 2 files: main.cpp and parser.hpp
I am returning vector<vector> from a member function in class in parser.hpp. However it seems I am not getting anything in my main.cpp from the return value because when I print its size I get 0.
This is my main.cpp:
#include <vector>
#include <cstring>
#include <fstream>
#include <iostream>
#include "parser.hpp"
using namespace std;
int main()
{
ifstream file;
file.open("test.csv");
csv obj;
obj.parse(file);
obj.print_parsed_csv(file);
vector<vector<string>> parsed_csv_data = obj.parse(file);
cout << parsed_csv_data.();
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
This is my parser.hpp
using namespace std;
class csv
{
public:
vector<vector<string>> parse(ifstream &file)
{
string str;
vector<vector<string>> parsed_data;
while (getline(file, str))
{
vector<string> parsed_line;
while (!str.empty())
{
int delimiter_pos = str.find(',');
string word = str.substr(0, delimiter_pos);
// cout << word << " ";
if (delimiter_pos == -1)
{
parsed_line.push_back(word);
break;
}
else
{
str = str.substr(delimiter_pos + 1);
// cout << str << endl;
parsed_line.push_back(word);
}
}
parsed_data.push_back(parsed_line);
}
return parsed_data;
}
void print_parsed_csv(ifstream &file)
{
vector<vector<string>> parsed_csv_data = parse(file);
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
};
I am getting correct cout output in parse() only. print_parsed_csv() in parser.hpp and the cout in main.cpp both are giving 0 as the variable's size.
How do I resolve this?
The first time you call obj.parse the stream object is read from until you get to the end of the file. You need to either reopen the file or reset file to point back to the beginning of the file after reading from it.
You pass the same file variable to each of the three functions below but only the first one works. The first call to obj.parse moves where file is pointing in the input file. When obj.parse exits the first time, file is pointing to the end of the file so when it's used in the subsequent 2 calls, there's nothing to read.
obj.parse(file); // <-- this works fine
obj.print_parsed_csv(file); // <-- this fails
vector<vector<string>> parsed_csv_data = obj.parse(file);fails
// ^^^^^^^^^- this fails
See this question for answers on how to reset the ifstream to the beginning of the file.

Inputting values into an array from a file with C++

The file does open and I get the message "File opened successfully". However I can't input data from the array in file "random.csv" into my inputFile object.
The data in random.csv is:
Boston,94,-15,65
Chicago,92,-21,72
Atlanta,101,10,80
Austin,107,19,81
Phoenix,112,23,88
Washington,88,-10,68
Here is my code:
#include "main.h"
int main() {
string item; //To hold file input
int i = 0;
char array[6];
ifstream inputFile;
inputFile.open ("random.csv",ios::in);
//Check for error
if (inputFile.fail()) {
cout << "There was an error opening your file" << endl;
exit(1);
} else {
cout << "File opened successfully!" << endl;
}
while (i < 6) {
inputFile >> array[i];
i++;
}
for (int y = 0; y < 6; y++) {
cout << array[y] << endl;
}
inputFile.close();
return 0;
}
Hello and welcome to Stack Overflow (SO). You can use std::getline() to read each line from the file, and then use boost::split() to split each line into words. Once you have an array of strings for each line, you can use a container of your liking to store the data.
In the example below I've used an std::map that stores strings and a vector of ints. Using a map will also sort the entrances using the key values, which means that the final container would be in alphabetical order. The implementation is very basic.
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#include <ctype.h>
typedef std::map<std::string,std::vector<int>> ContainerType;
void extract(ContainerType &map_, const std::string &line_)
{
std::vector<std::string> data;
boost::split(data, line_, boost::is_any_of(","));
// This is not the best way - but it works for this demo.
map_[data[0]] = {std::stoi(data[1]),std::stoi(data[2]),std::stoi(data[3])};
}
int main()
{
ContainerType map;
std::ifstream inputFile;
inputFile.open("random.csv");
if(inputFile.is_open())
{
std::string line;
while( std::getline(inputFile,line))
{
if (line.empty())
continue;
else
extract(map,line);
}
inputFile.close();
}
for (auto &&i : map)
{
std::cout<< i.first << " : ";
for (auto &&j : i.second)
std::cout<< j << " ";
std::cout<<std::endl;
}
}
Hope this helps.

How to continue to read a binary file with .read?

I'm trying to read a binary file that contains a 1501-by-1501 matrix of double, and plug it in an Eigen matrix. Here is my code:
#include <fstream>
#include <iostream>
#include <Eigen/Dense>
#include <string>
using namespace std;
using namespace Eigen;
int main()
{
MatrixXd B(1501, 1501);
ifstream inputFile;
double toread;
inputFile.open("/path/to/bathymetry_S1000s2500s_E65d1000s65d2500s.bin",
ios::out | ios::in | ios::binary);
if (!inputFile) {
cout << "The file can't be opened.\n";
exit(10);
} else {
for (int i2 = 0; i2 < 1501; i2++) {
for (int i1 = 0; i1 < 1501; i1++) {
inputFile.read( reinterpret_cast<char*>( &toread ),
sizeof(toread) );
inputFile >> toread;
B(i1, i2) = toread;
}
}
inputFile.close();
}
cout << "Max value:" << B.maxCoeff() << endl; // Just to check the result
cout << "Mean Value:" << B.mean() << endl; // The same
}
My problem is that, when I run the code, my matrix B is actually filled only with the very first value of the inputFile, which is -4502, which will then be given by the two cout. (All the elements of the matrix are -4502). How can I make the compiler understand that I want it to continue reading the inputFile after the previous value, instead of starting from the beginning at each loop-step?

Problems with fstream

I'm writing a vector array to an ofstream file, however certain values aren't getting written, I.E.:
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main (){
char * hold = new char [100];
vector<double> fx(2049);
ifstream inputFile;
ofstream myFile;
inputFile.open("data.txt");
myFile.open("test.txt");
for (int c=0; c<2049; c++){
inputFile.getline(hold, 100);
fx[c] = atof(hold);
}
for (int c=0; c<2049; c++){
myFile << fx[c] << "\n";
}
}
Within fx, the second half is all equal to 0. (fx[1024] through fx[2048]==0). Within test.txt however, none of these 0 values are present, on the carriage return is applied. Any thoughts?
Thanks! (New to the formatting of these questions... any tips to make this more understandable would be appreciated.)
Note: I realize this program is rather redundant. The actual program has a great deal more functionality to it, this is just an area that is working incorrectly.
Try this
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <cstdlib>
#define MAX_FILE_LINES 2048
using namespace std;
//genarate random double number
double fRand()
{
double fMin = 100, fMax = 200;
double f = (double)rand();
return fMin + (f / (fMax - fMin));
}
//init file (if you need to create sample file with list of double numbers, you can use this function)
void fileInit(){
ofstream sourceFile;
sourceFile.open("D:\\source.txt");
if (sourceFile.is_open())
{
for (int i=0; i<MAX_FILE_LINES; i++){
sourceFile << fRand() << endl;
}
}
}
int main (){
string buffer;
vector<double> fx(MAX_FILE_LINES);
ifstream sourceFile;
ofstream destinationFile;
sourceFile.open("D:\\source.txt");
destinationFile.open("D:\\destination.txt");
//reading file lines to vector
int lineCount =0;
if (sourceFile.is_open())
{
while ( sourceFile.good() )
{
getline (sourceFile,buffer);
fx[lineCount] = atof(buffer.c_str());
lineCount++;
if (lineCount == (MAX_FILE_LINES-1)){
break;
}
}
sourceFile.close();
}
//write lines to new file
if (destinationFile.is_open())
{
for (int i=0; i<MAX_FILE_LINES; i++){
destinationFile << fx[i] << endl;
}
}
}
Why screw with handroll buffers for one-offs? You can't save a millionth of what it costs to think about cycles here, there's not enough waste to recoup.
Think about eliminating needless statements and unchecked failures first.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<float> data;
{
ifstream ids("source.txt",ios_base::in);
int linenr = 0;
for ( string line ; getline(ids,line) ; ) {
++linenr;
decltype(data)::value_type x;
istringstream s(line);
if ( s >> x )
data.push_back(x);
else
cerr << "crap line "<<linenr<<" ignored: " << line << '\n';
}
}
ofstream ods("object.txt");
for ( auto x : data )
ods << x << '\n';
}