I can't figure out why this is outputting a different file given that the start of the input file matches the first if statement. Also, if there are multiple finds, the next file name turns out to be the last file name plus the new file name together.
int main()
{
unsigned short n(0);
unsigned char y;
std::ostringstream filename;
std::ifstream input("data.dat", std::ios::binary);
input >> std::noskipws >> std::hex;
std::ofstream output;
output << std::ios::binary;
while (input.good()) {
filename.clear();
filename << n << ".dat";
output.open(filename.str());
while ( input.good() )
{
input >> y;
output << y;
if ( y == 0xFF ) {
input >> y;
output << y;
if ( y == 0xD9 ) {
input >> y;
output << y;
output.close();
break;
}
}
}
if (output.is_open())
output.close();
++n;
}
return 0;
}
#include <iostream> // for input/output
#include <fstream> // for file stream stuff
#include <sstream> // for ostringstream
int main()
{
unsigned short nFile = 0; // used to increment file name
std::ostringstream filename; // output filename
std::ifstream inFile; // input stream
std::ofstream outFile; // output stream
unsigned char buffer; // buffer between input and output
inFile.open("data.dat", std::ios::binary); // open input file
if ( inFile.fail() )
return 1;
while ( inFile.good() )
{
filename.str(""); // empties the stream
filename << nFile << ".dat"; // generate filename
// start the search loop
while ( inFile.good() )
{
// create a file
outFile.open(filename.str(), std::ios::binary);
if ( outFile.fail() )
return 1;
while ( inFile.good() )
{
inFile.read(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // read a byte
if ( inFile.eof() )
break;
outFile.write(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // write a byte
if ( buffer == 0xFF )
{
inFile.read(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // read a byte
if ( inFile.eof() )
break;
outFile.write(reinterpret_cast<char*>(&buffer), sizeof(buffer)); // write a byte
if ( buffer == 0xD9 ) // full match; break loop
{
break;
}
}
}
// if search is done and file is still open, close it
if (outFile.is_open())
outFile.close();
++nFile;
}
return 0;
}
}
Related
Please can you advise, why the inner loop runs only once?
I'd like to add suffix to each line of input file and then store the result in output file.
thanks
For example:
Input file contains:
AA
AB
AC
Suffix file contains:
_1
_2
Output file should contain:
AA_1
AB_1
AC_1
AA_2
AB_2
AC_2
My result is :
AA_1
AB_1
AC_1
Code:
int main()
{
string line_in{};
string line_suf{};
string line_out{};
ifstream inFile{};
ofstream outFile{"outfile.txt"};
ifstream suffix{};
inFile.open("combined_test.txt");
suffix.open("suffixes.txt");
if (!inFile.is_open() && !suffix.is_open()) {
perror("Error open");
exit(EXIT_FAILURE);
}
while (getline(suffix, line_suf)) {
while (getline(inFile, line_in))
{
line_out = line_in + line_suf;
outFile << line_out << endl;
}
inFile.close();
outFile.close();
}
}
IMHO, a better method is to read the files into vectors, then iterate through the vectors:
std::ifstream word_base_file("combined_test.txt");
std::ifstream suffix_file("suffixes.txt");
//...
std::vector<string> words;
std::vector<string> suffixes;
std::string text;
while (std::getline(word_base_file, text))
{
words.push_back(text);
}
while (std::getline(suffix_file, text))
{
suffixes.push_back(text);
}
//...
const unsigned int quantity_words(words.size());
const unsigned int quantity_suffixes(suffixes.size());
for (unsigned int i = 0u; i < quantity_words; ++i)
{
for (unsigned int j = 0; j < quantity_suffixes; ++j)
{
std::cout << words[i] << suffix[j] << "\n";
}
}
Edit 1: no vectors
If you haven't learned about vectors or like to thrash your storage device you could try this:
std::string word_base;
while (std::getline(inFile, word_base))
{
std::string suffix_text;
while (std::getline(suffixes, suffix_text))
{
std::cout << word_base << suffix_text << "\n";
}
suffixes.clear(); // Clear the EOF condition
suffixes.seekg(0); // Seek to the start of the file (rewind).
}
Remember, after the inner while loop, the suffixes file is at the end; no more reads can occur. Thus the file needs to be positioned at the start before reading. Also, the EOF state needs to be cleared before reading.
I have been trying to read following data table and create an object for the HUBs(rows) and another object for continent (columns). Since I am not a C++ experienced user I have been facing some difficulties. The data is in following. The number after HUB and the dash shows the order from the hub. The other numbers under each continent are the corresponding cost and tariffs between a HUB and continent. I would like to be able to cout for instance following and get the result which would be 73.
cout << hub(1)->cont(USA)->transport() << endl;
,USA,EUROPE,ASIA
HUB1-12000,,,
Transportation Cost,73,129,141
Tariffs,5,5,1
ShippingType,a,b,c
OtherFees,0.6,0.3,0.8
HUB2-11000,,,
Transportation Cost,57,101,57
Tariffs,7,7,5
ShippingType,b,b,d
OtherFees,0.7,0.3,0.6
Really appreciate your help. Here is what I have tried so far:
void Hub()
{
string file = "/hubs.csv";
// 1-First read the first line and save the continent name
string str, field;
getline( fin, str );
vector<string> contList;
stringstream linestr( str );
while ( linestr.good() )
{
getline( linestr, field, ',' );
string contname;
contList.push_back(contname);
}
// 2-Then read the rest
getline( fin, str );
while ( !fin.eof() ) // Read the whole file
{
stringstream linestr( str );
string contname, order;
if ( qstr[0] == 'HUB1' || qstr[0] == 'HUB2')
{
// Read the name of the hub
getline( linestr, hubname, ',' ); // Read the hub name
getline( linestr, order, ',' ); // Read the order quantityity
int quantity;
istringstream orderstream( order);
orderstream >> quantity;
// Find the hub and add the order to the hub
Hub* hub = glob->FindHubName( hubname ); // this returns a pointer
if ( glob->FindHubName( hubname ) == nullptr )
{
hubNotFound.push_back( hubname );
getline( fin, qstr );
continue;
}
hub->TotalOrder( quantity );
}
else if ( qstr[0] != 'HUB1' || qstr[0] != 'HUB2')
{
// Read costs and tariffs
cout << hub(1)->cont(ASIA)->transport()
}
getline( fin, qstr );
}
fin.close();
}
Something like this:
#include <iostream>
#include <fstream>
#include <boost/tokenizer.hpp>
#include <string>
int main() {
using namespace std;
using namespace boost;
string line, file_contents;
fstream file("test.csv");
if (!file.is_open()) {
cerr << "Unable to open file" << endl;
return 1;
}
getline(file, line);
tokenizer<> tok_head(line);
int n_columns = 0;
for (tokenizer<>::iterator beg=tok_head.begin(); beg!=tok_head.end(); ++beg) {
cout << *beg << '\t';
n_columns++;
}
cout << endl;
while (getline(file, line)) {
file_contents += line;
}
file.close();
tokenizer<> tok(file_contents);
int i = 0;
for (tokenizer<>::iterator beg=tok.begin(); beg!=tok.end(); ++beg, ++i) {
cout << *beg;
if (i % n_columns) {
cout << '\t';
} else {
cout << endl;
}
}
return 0;
}
Makefile
all: t
t: csv.cpp
g++ -I /usr/include/boost csv.cpp -o t
It looks like you must parse each line using different logic, so you should check first column first and using it apply appropriate logic, below is some pseudocode for that:
std::fstream fs("test.txt");
std::string line;
//
// Read line by line
while (std::getline(fs, line)) {
std::istringstream str(line);
std::string rec_type;
// Read record type (your first two lines looks like are of no type?)
if ( !std::getline(str, rec_type, ',') )
continue;
// Decide type of record, and parse it accordingly
if ( rec_type == "Transportation Cost") {
std::string val;
// Read comma delimited values
if ( !std::getline(str, val, ',') )
continue;
int ival1 = std::stoi(val);
if ( !std::getline(str, val, ',') )
continue;
int ival2 = std::stoi(val);
// ...
}
if ( rec_type == "Tariffs") {
std::string val;
if ( !std::getline(str, val, ',') )
continue;
int ival = std::stoi(val);
// ...
}
}
One method is to consider each line as a separate record and object.
Let the objects read their data.
For example:
class Tariff
{
int values[3];
public:
friend std::istream& operator>>(std::istream& input, Tariff& t);
};
std::istream& operator>>(std::istream& input, Tariff& t)
{
// Read and ignore the label "Tariff"
std::string name;
std::getline(input, name, ','); // Read until ',' delimiter.
input >> t.value[0];
// Note: the ',' is not a digit, so it causes an error state,
// which must be cleared.
input.clear();
input >> t.value[1];
input.clear();
input >> t.value[2];
input.clear();
}
Another method is to read the label first, then delegate to a function that reads in the row.
std::string row_text;
std::getline(text_file, row_text); // Read in first line and ignore.
while (std::getline(text_file, row_text))
{
std::istringstream text_stream(row_text);
std::string label;
std::getline(text_stream, label, ','); // Parse the label.
// Delegate based on label.
// Note: can't use switch for strings.
if (label == "Tariffs")
{
Input_Tariff_Data(text_stream);
}
else if (label == "ShippingType")
{
Input_Shipping_Type_Data(text_stream);
}
//...
} // End-while
The if-else ladder can be replaced by a lookup table that uses function pointers. Sometimes the table is easier to read.
typedef void (*P_Input_Processor)(std::istringstream& text_stream);
struct Table_Entry
{
char const * label;
*P_Input_Processor input_processor;
};
//...
const Table_Entry delegation_table[] =
{
{"Tariffs", Input_Tariff_Data},
{"ShippingType", Input_Shipping_Type_Data},
};
const unsigned int entry_quantity =
sizeof(delegation_table) / sizeof(delegation_table[0]);
// ...
std::string row_text;
std::getline(input_file, row_text); // Read and ignore first line.
while (std::getline(input_file, row_text))
{
// Create a stream for parsing.
std::istringstream text_stream(row_text);
// Extract label text
std::string label;
std::getline(text_stream, label, ',');
// Lookup label in table and execute associated function.
for (unsigned int index = 0; index < entry_quantity; ++index)
{
if (label == delegation_table[index].name)
{
// Execute the associated input function
// by derferencing the function pointer.
delegation_table[index](text_stream);
break;
}
}
}
An alternative to the lookup table is to use:
std::map<std::string, P_Input_Processor>
or
std::map<std::string, void (*P_Input_Processor)(std::istringstream&)>
I have a text file that contains over 5000 lines with data (lottery draw results for Lotto). Each line has the form: number. day.month.year number1,number2,number3,number4,number5,number6
Five sample lines:
27.01.1957 8,12,31,39,43,45
03.02.1957 5,10,11,22,25,27
10.02.1957 18,19,20,26,45,49
17.02.1957 2,11,14,37,40,45
24.02.1957 8,10,15,35,39,49
I have also:
struct Lotto
{
short number_drawing;
char day;
char month;
short year;
char tab[6];
};
I have to write data from this text file into a binary file as struct Lotto.
I have already run out of ideas.
I have beeng trying since few days but my program still doesn't work properly :(
I try to load although one line :)
int main()
{
ifstream text("lotto.txt", ios::in);
ofstream bin("lottoBin.txt", ios::binary | ios::out);
Lotto zm;
short number_drawing;
char day;
char month;
short year;
char tab[6];
char ch;
int records = 0;
while (!text.eof())
{
text >> zm.number_drawing >> ch >> zm.day >> ch >> zm.month >>
ch >> zm.year >> zm.tab[0] >> ch >> zm.tab[1] >> ch >> zm.tab[2] >>
ch >> zm.tab[3] >> ch >> zm.tab[4] >> ch >> zm.tab[5];
records++;
}
cout << "All records: " << records << endl;
Here are some observations that might help you:
You will not be able to directly read a number into a char. Use an intermediate integer.
Define a function to read a record: bool read( std::istream&, Lotto& )
Your while should call the above function: while ( read( is, lotto ) )
A starting point:
bool read( std::istream& is, Lotto& lotto )
{
short t;
char c;
// read data
//
is >> t;
lotto.number_drawing = t;
is >> c;
if ( c != '.' )
return false;
//
is >> t;
lotto.day = char( t );
is >> c;
if ( c != '.' )
return false;
// read rest of fields...
// end of line
while ( is.get( c ) && isspace( c ) && c != '\n' )
;
if ( ! is.eof() && c != '\n' )
return false;
// check data
if ( lotto.month > 12 )
return false;
// check rest of data...
return is.good();
}
int main()
{
ifstream is( "yourfile.txt" );
if ( ! is )
return -1;
Lotto lotto;
while ( read( is, lotto ) )
{
// ...
}
if ( !is.eof() )
return -1;
return 0;
}
I'm using this code to extract certain part of each line of a text file:
std::ifstream file( "infile.txt" );
std::string in1, out1;
int blockNumber = 0;
while( getline( file, in1 ) )
{
int n = 0;
int i = 0;
while( i <= blockNumber )
{
n = in1.find_first_of("(", n + 1);
i++;
}
out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );
ofstream fmatch ("solo_matches.txt",ios::out);
fmatch.close();
fmatch.open("solo_matches.txt");
fmatch << out1;
fmatch.close();
}
But when I run the code, the result is not as I expect it to be. Only the last string is being written to the file. If I use this instead:
std::cout << out1 << std::endl;
I get the exact output I need. I do not understand what is the difference.
Well, ofstream probably overwrites existing contents every time you open it. I mean, every time you open file, write pointer will be placed at the begninning, so even without ios::trunc flag new data written into that file will overwrite existing contents.
To solve the problem, stop reopening ofstream twice for every line of text. File open operation can be slow.
Either that, or try using ios::app flag.
Move file open and file close operations outside while loop:
#include<iostream>
#include<fstream>
int main()
{
std::ifstream file( "infile.txt" );
std::string in1, out1;
int blockNumber = 0;
std::ofstream fmatch ("solo_matches.txt",std::ios::out);
while( getline( file, in1 ) )
{
int n = 0;
int i = 0;
while( i <= blockNumber )
{
n = in1.find_first_of("(", n + 1);
i++;
}
out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );
//fmatch.close(); //you don't need this
//fmatch.open("solo_matches.txt"); //you don't need this
std::cout << out1 << std::endl;
fmatch << out1 << std::endl;
}
fmatch.close();
}
And replace
fmatch << out1;
with
fmatch << out1 << endl;
if you need cout and fmatch agreement.
std::ofstream fmatch("solo_matches.txt", ios::out);
fmatch << ...;
fmatch.close();
opens the file, rewrites its content and saves it upon closing the stream. To append the content at the end of the file, you can use ios::app flag:
std::ofstream fmatch("solo_matches.txt", ios::out | ios::app);
or yet even better, instead of reopening the file in every iteration:
while (...) {
construct ofstream
write to file
close ofstream
}
you could do:
construct ofstream
while (...) {
write to file
}
close ofstream
Also note that this line:
out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );
relies on the correct format of the input, it would be safer to check the return value of find_first_of:
std::size_t pos = in1.find_first_of(")", n);
if (pos != std::string::npos)
{
out1 = in1.substr( n + 1, pos - n - 1 );
...
}
I am trying to read all the characters in a file into an array. Assuming all variables are declared, why are all the characters not being read into my array. When I output some of the characters in the "storeCharacters[]" array, garbage is being returned. Please help.
This is my function:
void countChars(ifstream& input, char storeCharacters[])
{
int i = 0;
while( !input.eof() )
{
input.get(storeCharacters[i]);
i++;
}
}
After the while loop try adding storeCharacters[i] = '\0' to null terminate the string.
The easy fix to your problem if you know the maximum size of your file, then just set your array to have that size and initialize it with \0.
let's say the maximum characters count in your file is 10000.
#define DEFAULT_SIZE 10000
char storeCharacters[DEFAULT_SIZE];
memset (storeCharacters,'\0',DEFAULT_SIZE) ;
The below post should be the correct way to read a file using a buffer it has memory allocation and all what you need to know :
Correct way to read a text file into a buffer in C?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;
void getFileName(ifstream& input, ofstream& output) //gets filename
{
string fileName;
cout << "Enter the file name: ";
cin >> fileName;
input.open(fileName.c_str());
if( !input )
{
cout << "Incorrect File Path" << endl;
exit (0);
}
output.open("c:\\users\\jacob\\desktop\\thomannProj3Results.txt");
}
void countWords(ifstream& input) //counts words
{
bool notTrue = false;
string words;
int i = 0;
while( notTrue == false )
{
if( input >> words )
{
i++;
}
else if( !(input >> words) )
notTrue = true;
}
cout << "There are " << i << " words in the file." << endl;
}
void countChars(ifstream& input, char storeCharacters[], ofstream& output) // counts characters
{
int i = 0;
while( input.good() && !input.eof() )
{
input.get(storeCharacters[i]);
i++;
}
output << storeCharacters[0];
}
void sortChars() //sorts characters
{
}
void printCount() //prints characters
{
}
int main()
{
ifstream input;
ofstream output;
char storeCharacters[1000] = {0};
getFileName(input, output);
countWords(input);
countChars(input, storeCharacters, output);
return 0;
}