Cross referencing data from file - c++

Cant figure this out....I got two txt files, one is encoding1.txt which contains a set of hexadecimals and the ID number that is assigned to them, such as
61 1
C3A4 2
C990 4
C991 5
C991CC83 6
C992 7
CA8C 9
The other file source.txt is the source file which contains a bunch of combined hex and the students' names
CA8CC992 Jack
C991C3A4 Amy
C991CC83 Sam
61C991 Tom
I want to output a txt file for each students with their name as their filenames and inside the file should be the assigned numbers of their hex. e.g. for jack.txt, inside it should be
9
7
Below is the code that I've tried it generates all the test file but inside its jack.txt theres only 9 and other files are empty. Whats the correct way to do this and how do I get the results right?
#include "stdafx.h"
#include <iostream>
#include <string>
//#include<map>
//#include<unordered_map>
#include <fstream>
#include<array>
//#include<vector>
#include <algorithm>
using namespace std;
int main()
{
std::ifstream file;
file.open("encoding1.txt");
if (file.is_open())
{
std::cout << "opened encoding1 file";
}
std::ifstream file2;
file2.open("source.txt");
if (file.is_open())
{
std::cout << "opened source file" << std::endl;
}
std::ofstream outfile;
const int hexencosize = 7;
std::string hexenco[hexencosize] = {};
int id[7] = {};
std::string hexsource;
string * p;
std::string name;
for (int i = 0; i < 6; i++)
while (file >> hexenco[i] >> id[i]) {
std::cout << "hexenco is " << hexenco[i] << std::endl;
std::cout << "id is " << id[i] << std::endl;
};
for (int o = 0; o < 6; o++)
while (file2 >> hexsource >> name) {
outfile.open(name + ".txt");
std::size_t found = hexsource.find(hexenco[o]);
if (found != std::string::npos)
p = std::find(hexenco, hexenco + hexencosize, hexenco[o]);
if (p >= hexenco + hexencosize) std::cout << "Not found" <<
std::endl;
else outfile << id[p - hexenco] << '\n';
outfile.close();
};
system("pause");
return 0;
};

Related

C++ values from struct creating newlines in CSV file

I am very new to C++, and currently am attempting to create a simple user interface which will do the following:
Check if a CSV file already exists with the given name
Create that file if it does not exists, and write the headers
Ask user for information, store in struct
Write data to CSV file when done
The issue I am facing is that when the program ends, and writes the data to the CSV file it creates newlines for each struct variable I am writing. I would like the program to just write all data on one line with comma separated format.
Example code:
struct.h
#ifndef struct_h
#define struct_h
#include "string"
namespace RB
{
struct Values
{
std::string event;
std::string town;
std::string state;
std::string date;
};
}; // namespace
#endif /* struct_h */
create.h
#ifndef create_h
#define create_h
#include <cstdio>
#include <ctime>
#include <iostream>
#include <fstream>
namespace RB
{
int createFile()
{
time_t t = time(nullptr); // the current time
struct tm gmt = *gmtime(&t); // structured time in GMT
const int year = 1900 + gmt.tm_year;
static const char *filename = "results_";
if (std::ifstream((filename + std::to_string(year) + ".csv").c_str()))
{
std::cout << "File Found, appending to file " << (filename + std::to_string(year) + ".csv").c_str() << std::endl;
}
else
{
std::cout << "No file with name " << (filename + std::to_string(year) + ".csv").c_str() << "\ncreating file...\n" << std::endl;
std::ofstream ofile((filename + std::to_string(year) + ".csv").c_str());
ofile << "Event" << ","
<< "Town" << ","
<< "State" << ","
<< "Date" << "\n";
ofile.flush();
ofile.close();
};
return 0;
};
}
#endif /* create_h */
main.cpp
#include <cstdio>
#include <stdlib.h>
#include <iostream>
#include "struct.h"
#include "create.h"
int main()
{
// Run Create before continuing
int c = RB::createFile();
struct RB::Values revent;
// Get Event Name
std::cout << "Starting to enter data for race event...\n" << std::endl;
std::cout << "What was the name of the event: ";
std::cin >> revent.event;
// Get Event Town
std::cout << "What town was the race run in: ";
std::cin >> revent.town;
// Get Event City
std::cout << "What state was the race run in: ";
std::cin >> revent.state;
// Get Event Date
std::cout << "When was the race run: ";
std::cin >> revent.date;
time_t t = time(nullptr); // the current time
struct tm gmt = *gmtime(&t); // structured time in GMT
const int year = 1900 + gmt.tm_year;
static const char *filename = "results_";
if (std::ifstream((filename + std::to_string(year) + ".csv").c_str()))
{
std::ofstream ofile((filename + std::to_string(year) + ".csv").c_str(), std::ofstream::out | std::ofstream::app);
ofile << revent.event << ",";
ofile << revent.town << ",";
ofile << revent.state << ",";
ofile << revent.date;
ofile.close();
};
return 0;
}
Sample Output:
Event,Town,State,Date
CapRock
,Turkey
,Texas
,March 9
I assume this is something simple I am doing wrong, but cannot seem to figure it out on my own.

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.

Writing a C++ Program to Search an Index File From the Linux Command Line

I've written a program that reads in a data file and creates a sorted index file from the data in the original file. However, I"m then supposed to write a second program that allows teh user to search this index file from the Linux command line. For example, they are supposed to be able to type
search 12382 prog5.idx
into the command line and have the information for that record displayed. I have no idea how to accomplish this.
I have written the code to create the index file (works):
#include <iostream>
#include <fstream>
#include <map>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
class Record {
string name;
int code;
double cost;
public:
Record() {
}
Record(string tname,int tcode,double tcost) : name(tname),code(tcode),cost(tcost) {
}
friend ostream& operator<< (ostream &os, const Record& r);
};
//print function
ostream& operator<< (ostream &os, const Record& r) {
os << setw(10) << r.name << " " << setw(5) << r.code << " $" << setw(10) << setprecision(2) << fixed << r.cost ;
return os;
}
int main() {
std::map<int, Record> myMap;
ifstream data;
size_t offset_count = 0;
data.open("prog5.dat");
ofstream outFile("prog5.idx", ios::out);
//if file can't be opened, exit
if(!data) {
cerr << "Open Failure" << endl;
exit(1);
}
std::string line;
while (std::getline(data, line)) {
stringstream ss(line);
int key;
string name;
int code;
double cost;
if(ss >> key >> name >> code >> cost) {
Record r(name,code,cost);
myMap.insert( pair<int,Record>(key,r));
}
else {
cout << "Error";
}
}
// print what's stored in map
for(std::map<int,Record>::iterator x = myMap.begin(); x!=myMap.end(); ++x) {
cout << setw(10) << x->first << ": " << x->second << endl;
}
}
And get the following output when running the above code:
8: blank 0 $ 0.00
12165: Item16 30 $ 7.69
12345: Item06 45 $ 14.20
12382: Item09 62 $ 41.37
12434: Item04 21 $ 17.30
16541: Item12 21 $ 9.99
21212: Itme31 19 $ 8.35
34186: Item25 18 $ 17.75
41742: Item14 55 $ 12.36
Here's what I have so far for the second program:
#include <prog3.idx>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv) {
if(argc < 3) {
std::cerr << "Too few arguments \n";
std::exit(EXIT_FAILURE);
}
int key = atoi(argv[1]);
const char* filename = argv[2];
ifstream input;
input.open("prog5.idx");
}
But I'm not sure where to go from there. Can someone help me out?
Use map or multimap and find in the STL. Make a datatype out of the remaining data with the index as the key. The program will have to read in the entire file first and then find the searched index.

Copy string until '.' And how to copy only numbers when i know the structure

I have a code that i want it to get input file from command line and create output file with XXX at the end - meanning if intput= "blabla.txt" or "/johny/first/blabla.txt" i till get "blablaXXX.txt" or "/johny/first/blablaXXX.txt"
The second question is that when i find a line i was looking for i want to copy only the numbers (keep in date mode) and the len
Line will be "IT IS HERE time 12:04:56.186, len 000120"
And i want to get in the new file line: 12:04:56.186 120
#include <iostream>
#include <fstream>
using namespace std;
int main( int argc, char* args[] )
{
string inputName=args[1];
ifstream inputName(inputFileName);
////// here i will need to get the output string name some thing like
// string outputFileName=EDITED_INPUT_NAME+"XXX"+".txt";
ofstream outpuName(outputFileName);
while( std::getline( inputName, line ) )
{
if(line.find("IT IS HERE") != string::npos)
// how to make it take only the parts i need??????
outpuName << line << endl;
cout << line << endl;
}
inputName.close();
outpuName.close();
return 0;
}
Does this solve your problem:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main(int argc, char* args[]) {
ifstream inputFile(args[1]);
// Your first problem
string outputFileName(args[1]);
outputFileName.insert(outputFileName.find("."), "XXX");
cout << "Writing to " << outputFileName << endl;
// End of first problem
ofstream outputFile(outputFileName.c_str());
string line;
while (getline(inputFile, line)) {
if (line.find("IT IS HERE") != string::npos) {
// Your second problem
string::size_type time_start = line.find("time ") + 5;
string::size_type time_end = line.find(",", time_start);
cout << time_start << " " << time_end << endl;
string time = line.substr(time_start, time_end - time_start);
string::size_type len_start = line.find("len ") + 4;
string::size_type len_end = line.find(" ", len_start);
if (len_end != string::npos)
len_end += 4;
int len = atoi(line.substr(len_start, len_end - len_start).c_str());
// End of second problem
outputFile << time << " " << len << endl;
cout << time << " " << len << endl;
}
}
inputFile.close();
outputFile.close();
return 0;
}
Example input:
sdfghjk sdfghjk fghjkl
IT IS HERE time 12:04:56.186, len 000120
usjvowv weovnwoivjw wvijwvjwv
IT IS HERE time 12:05:42.937, len 000140
Example output:
12:04:56.186 120
12:05:42.937 140
The code could look nicer with std::regex and auto, but as this wasn't tagged with C++11, I held back.

creating files, checking if another one with the same name exists

Code(main.cpp) (C++):
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath);
if(ifs.good()){
finalPath += "dupe.txt";
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath);
}
}
ofs.open(finalPath);
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}
My problem is following.
Whenever I run this and enter, lets say 53 as for the amount, in the end it'll never create the full amount of files. It's always scaled.
Here's an example.
Defined Amont: 300 -> What I Get: 240
Defined Amount: 20 -> What I get: 15
Defined Amount: 600 -> What I get: 450
Thanks in advance.
Based on the logic of your code, you are creating a file if your ifstream object is not 'good()'. If some files aren't being created, then the error lies here.
With some digging, you'll find that the constructor for an ifstream object does not take a string, but instead a char *.
Adding a c_str() to your 'finalPath' variable should take care of this issue.
Some things to note:
You've forgotten to include fstream and iostream.
When digging into problems like this, don't use random numbers as your first test case. It was easier for me to replicate your issue by just trying to create files in numerical order.
Also don't forget 'close()' your ifstreams!
My adaptation of the code:
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <fstream>
#include <iostream>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath.c_str());
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath.c_str());
}
ifs.close();
std::cout << finalPath << std::endl;
ofs.open(finalPath.c_str());
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}