Reading data from a .csv and into arrays in c++ - c++

I did some searching on this site and on google as well. But i couldnt understand a lot of code i seen and im hoping to find more direct help from here. Im only 2 semesters in for c++ and i have a side project id like to do for my boss.
He generates a csv file for call logs and i want to be able to retrieve certain lines from the log and be able to calculate and display data.
Im not sure of the exact questions i need to ask but heres my code where i tried to start getting data but ran into problems (my programming knowledge is fairly limited due to lack of time and experience :)
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main()
{
//opens the csv file.
ifstream gwfile;
gwfile.open("log.csv");
if(!gwfile) { // file couldn't be opened
cout << "FAILED: file could not be opened" << endl << "Press enter to close.";
cin.get();
return 0;
}else
cout << "SUCCESSFULLY opened file!\n";
cout << "-------------------------------------------------------------------------------\n\n\n";
long int SIZE = 0;
char data[SIZE];
cout << "This is data SIZE:" << data[SIZE] << endl;
//in the csv im trying to only read lines that start with the voice as those are only valid data we need.
//also i would like to display the headings in teh very first line
while( !gwfile.eof() ){
//This is where im trying to only accept the lines starting with "Voice"
//if(data[SIZE] == "Voice"){
for( int i=0; i!=","; i++){
cout << "This is i: " << i << endl; //testing purposes.
}
//}
// getline(gwfile, data, '');
// cout << data[0];
}
return 0;
}

Let’s begin with the obvious
long int SIZE = 0;
char data[SIZE];
cout << "This is data SIZE:" << data[SIZE] << endl;
You are creating an array of size 0, then reaching for its first member: data[0]. This cannot work. Give your array a size that is large enough to handle the data you want to treat, or use a dynamicly resizable container (such as std::vector) to deal with it.

Related

strange thing in sequential file access

Recently, I am trying to write codes to get trained in sequential file access. I learned it well, but the issue is kinda stressing me out. I have a code that work 100%, and its task is "make a code that prints array elements inside a file", the text file name is "numric".
#include <iostream>
#include <fstream>
using namespace std;
int main(){
int a[3]={5000,6000,7000};
ofstream outfile("numric.txt");
if (outfile.is_open()){
outfile << "employee payroll:" << endl;
for (int i=0;i<3;i++)
outfile << a[i] << endl;
outfile.close();
} else
cout << "failed!" << endl;
return 0;
}
I implemented the code in two different program (VS Code, dev++) and it works fine. It found the file, but when I open the text file, there isn't any text inside it. The code should do its work by finding some text inside it if I opened it.
Note:sometimes when the code works, the antivirus pops a message saying it found an item that doesn't look safe in the program and deletes it.

How to I update a pre-existing leaderboard text file, making sure it's sorted?

First of I'd like to thank you all in advance for taking your time reading and helping me with my problem. I'm in no way shape or form an expert at c++, I'm not even good. I started programming in c++ 2 months ago and I find it quite harder than python, for a second experience with programming languages.
So I'm making this game for my programming class and I have to have a leaderboard text file with all the winners of a certain level. I set it up so the file always has the same format for time, name like this.
I've been trying to figure out how to sort the leaderboard entries by time and then by name. I thought of reading the file from line 3 and beyond but that doesn't seem to work. I moved on to what seems a better way of doing it which is to read the whole leaderboard discarding the first 2 lines, store it line by line on a vector, sorting the vector then and wiping the file by opening it in trunc mode but for some reason the file doesn't get wiped, it just keeps on adding more and more entries. I wan't it to add the sorted lines (vector) to the leaderboard one by one up until 10 entries are hit. Can someone help me? Here's a code sniped with the function I'm using to update the leaderboard
// Function to check if MAZE_XX_WINNERS.txt exists, if not creates it
void makeLeaderboard(string maze_name, string formated_time){
string winner_name, filename = maze_name.substr(0,7) +"_WINNERS.txt";
while(true){
// If MAZE_XX_WINNERS.txt file exists
if(ifstream(filename)){
// Open MAZE_XX_WINNERS.txt file in append mode
fstream leaderboard(filename, fstream::app);
// Ask for player name
cout << "Type your name (max 15 characters): ";
getline(cin, winner_name);
// If name is valid
if(isValidName(winner_name) && winner_name.length() <= 15){
string line;
vector<string> lb_entries;
int n_line = 0;
// Append to the end of the file
leaderboard << formated_time << " - " << winner_name << endl;
// Store all leaderboard entries in a vector
while(!leaderboard.eof()){
if(n_line >= 2){
getline(leaderboard, line);
lb_entries.push_back(line);
}
n_line++;
}
leaderboard.close();
//Everything works up until here, past here it doesn't do anything I want it to do
// Sort the leaderboard entries first by time, then by name
sort(lb_entries.begin(), lb_entries.end());
// Check if leaderboard has more than 10 entries to delete those past the limit
if(lb_entries.size() > 10){
// Truncates the vector from the 10th position forward
lb_entries.erase(lb_entries.begin()+9, lb_entries.end());
}
// Reopens the file in truncation mode to delete pre-existing leaderboard
leaderboard.open(filename, fstream::trunc);
// Format the file to have a table like shape
leaderboard << "| TIME - NAME |" << endl;
leaderboard << "------------------------------" << endl;
// Updates leaderboard
for(string entry : lb_entries){
leaderboard << entry << endl;
}
leaderboard.close();
break;
}
// If name not valid
else if(isValidName(winner_name) && winner_name.length() > 15){
cerr << endl << "Name has more than 15 characters! Please retry." << endl << endl;
}
else{
cerr << endl << "Not a valid name input!" << endl << endl;
}
}
// If file doesn't exist
else{
// Attempt to create the file
cout << "Creating leaderboard..." << endl;
ofstream leaderboard(filename);
// Check if file was created
if(!leaderboard){
cerr << "File could not be created" << endl;
}
else{
// Format the file to have a table like shape
leaderboard << "| TIME - NAME |" << endl;
leaderboard << "------------------------------" << endl;
leaderboard.close();
}
}
}
}
You need to break your problem down. What I would do is create a class that represents the LeaderBoards. It would actually consist of two classes. You could do one as an inner class of the others, but let's keep them separate:
class Leader {
public:
std::string time;
std::string name;
};
class LeaderBoard {
public:
std::vector<Leader> leaders;
void readFromFile(std::string fName);
void sort();
void writeToFile(std::string fName);
};
At that point, you need to implement three functions. None of them are very long.
void LeaderBoard::readFromFile(std::string fName) {
std::ifstream file(fName);
std::string line;
// skip the header
file.getline(line);
file.getline(line);
// Read the rest of the file.
while (file.getline(line)) {
// You'll need to parse the line into its parts
Leader leader(from the parts);
leaders.push_back(leader);
}
}
Yeah, I left some magic for you.
The write method would be very simple and just use an ofstream instead of an ifstream.
The sort method -- you can do a google for "c++ sort vector of objects" and get LOTS of examples.
In general, ALL programming can be broken down into smaller steps. If you're getting overwhelmed, break it down. This is one of the reasons you use an object-oriented language. If you don't know how to do something, create a class for it, then put methods in it for the smaller steps.
Then just figure out how to do small parts at a time. First: get data. Then print it out so you're sure you've got what you need.
If your code is more than about a screen or so, you're doing too much in one method. That's not an absolute, but at your level of coding, it's definitely true.
Small, tight methods. Small, tight methods are easier to write. Then string them together.
In this case:
Read the data
Sort the data
Write the data.
Each of these is easy to test individually.

Read a OutputDataStream.writeShort(int v) in C++

I am assigned a task where I have to explain why PrintStream and OutputDataStream produce two different kinds of output files (which I know - the first writes a string representation byte-by-byte, whilst the second writes the raw binary data). In order to elaborate on the background of this, I wanted to write a small C++ file to demonstrate reading the written data off the file back to stdout.
The idea is simple: Write short values from 20.000 to 32.000 to a file using OutputDataStream using it's writeShort(int) method. According to the Java documentation, those values are written in two bytes.
Now... I did try to implement this with std::ifstream on the C++ side, and I believe I ran into some endianess-related issues. According to what I have gathered from various SO questions, Java will write in "network format", which is apparently a different description for "Little Endian". But as far as I think I am aware of, my Mac (MacBook, mid. 2014), uses "Big Endian" - so the bytes are in a wrong order.
This is what I have come up with so far:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv) {
ifstream fh("./out.DataOutputStream.dat", ios::in|ios::binary);
if(!fh.is_open()) {
cerr << "Error while opening file." << endl;
cerr << "Are you in the same directory as <out.DataOutputStream.dat>?" << endl;
return 1;
}
cout << "--- Begin of data ---" << endl;
char num1, num2;
#define SWAP(b) ( (b >> 8) | (b << 8) )
while(!fh.eof()) {
fh.read(&num1, 1); // read one byte
fh.read(&num2, 1); // read the next byte
cout << (unsigned short)SWAP(num2) << (unsigned short)SWAP(num1);
}
cout << flush;
cout << "--- End of data ---" << endl;
return 0;
}
This result does print 32000 at the (very) end...but it prints that twice, and everything else is completely off... Any idea on how I can get this to work with the STL only?

Simple Cipher with std:out_of_range issue (C++)

I'm totally new to programming and heard that C++ or the Assembly Language is a good startning point for someone that want to understand what happens under the hood. I want to follow this follow through even though some of you might have other suggestions. I've been an active student for a week now and for my second challange my teacher asked us to write a cypher. Nothing fancy, but something that scrambled and unscrambled the string written by the user. So far I've tried to scramble them for starters since I deduce that if I'll solve that problem, the unscramling will be achieved through a similar process. I know there's plenty of snippets of code out there already, but I'm really intressted and want to learn through the trial and error method, based on my own assumptions.
I would appriciate it greatly if someone could point out why I get the message: "Terminate called after throwing an instance of 'std::out_of_range'
#include <iostream>
#include <string>
using namespace std;
string latSorted {"abcdefghijklmnopqrstuvwxyz ,."};
string latUnstorted {"-_qazwsxedcrfvtgbyhnujmikolp"};
int main() {
cout << "\n -----------------------------------------------" << endl;
cout << " Enter some text: ";
string usrText;
string* p_usrText; // Pointer Initialization
cin >> usrText; // User enter text
p_usrText = &usrText; // Memory allocation gets assigned to the pointer variable
cout << " You've entered " << *p_usrText << endl << endl;
for (size_t i=0; i < latSorted.length(); i++)
{
char searchChar = latSorted.at(i);
char cryptChar = latUnstorted.at(i);
for(size_t j=0; j < usrText.length(); j++)
{
if(usrText.at(j) == searchChar)
{
*p_usrText = usrText.replace(usrText.begin(), usrText.end(), searchChar, cryptChar); // Memory allocation is still within range due to the pointer. Should not say "out of range".
}
}
}
cout << ' ' << usrText << endl;
cout << endl;
return 0;
}
Thx//Alle
It appears that latSorted and latUnstorted are different lengths.
char cryptChar = latUnstorted.at(i);
Would result in the exception for the last value of i.

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.