Copying a file multiple times using loop; C/C++ - c++

I wanted to copy a file multiple times using different names.
The program is this:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include <sstream>
#include<cstring>
using namespace std;
main()
{
string text;
int i;
char ch;
ostringstream oss;
FILE *fp1,*fp2;
if((fp1=fopen("One Dollar.jpg", "rb"))==NULL)
{
cout<<"Error";
exit(-1);
}
for(i=1; i<=5; i++)
{
oss << "C:\\5241 Dollar\\One Dollar " << i << ".jpg";
text = oss.str();
if((fp2=fopen(text.c_str(), "wb"))==NULL)
{
cout<<"Error "<<i;
exit(-1);
}
while(!feof(fp1))
{
fread(&ch, 1, 1, fp1);
fwrite(&ch, 1, 1, fp2);
}
fclose(fp2);
/* for(int j=0;j<30000;j++)
for(int k=0;k<30000;k++)
if(k==3000)
cout<<k; */
}
fclose(fp1);
}
In this there are two file streams one of which is source and the other is destination.. I loaded the actual file in binary read mode and the destination as binary write mode. I used a for loop to do the work. But as soon as the loop iterates 2nd time, the file opening of fp2 fails. I'm getting the output: Error 2.
How can I make the code work?

You should open and close the first file in each iteration of the loop.
....
for(i=1; i<=5; i++)
{
if((fp1=fopen("One Dollar.jpg", "rb"))==NULL)
{
cout<<"Error";
exit(-1);
}
....
The reason is because at the end of the first iteration, the first file pointer is at the end of the file, so it won't see any data at the second iteration. You have to close and reopen the file (OR you can use seek to jump to the front of the file, but this is the simpler change since its a copy-and-paste)
EDIT: to the new question:
you need to reset the stringstream. In the second iteration you are trying to open
C:\\5241 Dollar\\One Dollar 1.jpgC:\\5241 Dollar\\One Dollar 2.jpg
which is invalid.
One solution is to bring the ostringstream declaration into the loop:
....
for(i=1; i<=5; i++)
{
if((fp1=fopen("One Dollar.jpg", "rb"))==NULL)
{
cout<<"Error";
exit(-1);
}
ostringstream oss;
oss << "C:\\5241 Dollar\\One Dollar " << i << ".jpg";

int main()
{
string text;
int i;
char ch;
ostringstream oss;
FILE *fp1,*fp2;
if((fp1=fopen("/home/maru/fact.cpp", "rb"))==NULL)
{
cout<<"Error";
exit(-1);
}
for(i=1; i<=5; i++)
{
oss << "/home/maru/fact" << i << ".cpp";
text = oss.str();
rewind(fp1);
cout<<text<<"\n";
if((fp2=fopen(text.c_str(), "wb"))==NULL)
{
cout<<"Error "<<i;
exit(-1);
}
while(!feof(fp1))
{
fread(&ch, 1, 1, fp1);
fwrite(&ch, 1, 1, fp2);
}
fclose(fp2);
oss.str("");
}
fclose(fp1);
return 0;
}

Related

c++ nested while loop runs only once

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.

c++ - Manual appending to files in loops

I was writing a -kind of - server that works io thru files.
When I tried to append a string to the file, (I at the time did not know about ios::app, so I used a very unconventional way of doing it) it would not behave as I expected ( I tried the append function without the loop, and it worked every time):
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
ofstream* open(string fileName)
{ // opens a file and returns a pointer to the object ready for writing
vector<string> contents;
ifstream f(fileName.c_str());
if (!f)
{
cout << "No File Found";
exit(-1);
}
while (!f.eof())
{ //read
string temp;
getline(f, temp);
contents.push_back(temp);
}
f.close();
ofstream* out = new ofstream(fileName.c_str());
for (int i = 1; i < contents.size(); i++)
{ // write previous contents
*out << contents[i] << endl << flush;
}
return out;
}
void apend(string text, string fileName)
{
ofstream* file = open(fileName);
*file << text << endl << flush; // insert text
file->close();
}
string stringify(int in)
{ // converts an integer to a string
stringstream x;
x << in;
string out;
x >> out;
return out;
}
int main()
{
cout << "Welcome to the cgs v1.0 ... loading files ... " << endl;
for (int i = 0; i < 10; i++)
apend(stringify(i), "server1.txt");
return 0;
}
Upon running this I got :
server1.txt :
5
6
7
8
9
And if I ran the program again :
server1.txt:
0
1
2
3
4
5
6
7
8
9
My question is, if I used std::flush why did it somehow not write the whole file, and then when it was re-run, write the rest of the first cycle
and none of the second? - This is just curiosity.
I will now move to ios::app.
Thanks for any explanations.

Why isn't a string vector value converted to cstring the equivalent of manually writing the string?

I have an input file that contains a list of .txt files in a folder. I loop through the input file just fine and put the .txt file filepaths in string vectors. However, when I try to open another ifstream using one of the filepaths in the sections vector (string vector value converted to cstring),
std::ifstream secFile(sections[i].c_str());
The line secFile.fail() returns true meaning it fails. If I instead use the currently commented out line that hardcodes a filepath (manually writing the string) rather than getting it from a vector,
//std::ifstream secFile("test2/main0.txt");
it no longer fails. I even tried outputting sections[0].c_str() and "test2/main0.txt" to a text file and the text for each is exactly the same. I even compared the hexadecimal values for the text file and there were no invisible characters that might cause such an issue.
Any idea what the problem might be?
Here is my code:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>
//using namespace std;
int main (int argc, char* argv[]){
if(argc != 2){
return(0);
}
std::vector<std::string> sections;
std::vector<std::string> overlaps;
std::ifstream file(argv[1]);
std::string str;
std::string secLine;
std::string overlapLine;
std::string strLow;
std::string wholePage = "";
//determine if input text file is overlap text or main text
while (getline(file, str))
{
if (str.find("overlap")!=-1){
overlaps.push_back(str);
}
else{
sections.push_back(str);
}
}
file.clear();
for(int i = 0; i < sections.size();i++){
//HERE IS MY QUESTION
std::ifstream secFile(sections[i].c_str());
//std::ifstream secFile("test2/main0.txt");
if(secFile.good()){
std::cout << "\ngood4\n";
}
if(secFile.bad()){
std::cout << "bad4\n";
}
if(secFile.fail()){
std::cout << "fail4\n";
}
if(secFile.eof()){
std::cout << "eof4\n";
}
int secLength = 0;
//determine number of files in test2/
while (getline(secFile,secLine)){
secLength++;
}
secfile.clear();
secfile.seekg(0);
int j = 0;
while (getline(secFile,secLine)){
if (i == 0 && j==0){
wholePage += std::string(secLine) + "\n";
}
else if(j==0){
//do nothing
}
else if(i == (sections.size()-1) && j == secLength){
wholePage += std::string(secLine) + "\n";
}
else if(j == secLength){
//do nothing
}
else{
wholePage += std::string(secLine) + "\n";
}
j++;
}
int k = 0;
if(i < sections.size()-1){
std::ifstream overFile(overlaps[i].c_str());
int overLength = 0;
while (getline(overFile,overlapLine)){
overLength++;
}
while (getline(overFile,overlapLine)){
std::cout << "Hi5";
if(k == 0){
//do nothing
}
else if(k == overLength){
//do nothing
}
else{
if (wholePage.find(overlapLine)){
//do nothing
}
else{
wholePage += std::string(secLine) + "\n";
}
}
}
k++;
}
}
std::ofstream out("output.txt");
out << wholePage;
out.close();
std::cout << "\n";
return 0;
}
You haven't provided enough information to be sure, but the most likely problem is whitespace. getline doesn't strip the trailing whitespace from the lines it produces, so you might be trying to open a file named "test2/main0.txt " (trailing space), which is distinct from "test2/main0.txt". You'll want to trim trailing whitespace in most cases, likely before storing the string to your vector. Since some whitespace can legally be part of a filename, the real solution would be to make sure the garbage whitespace isn't there, but trailing whitespace is filenames is rare enough that you could just hope the file names don't use it.
Here you are passing a filename:
std::ifstream secFile("test2/main0.txt");
Here you are passing a line of text from a file:
std::ifstream secFile(sections[i].c_str());
ifstream expects a filename, not a line of text from a file. It is failing because the text you are inputting doesn't represent a file you are trying to open.

I/O program stuck in loop C++

I'm working on a code that reads in a C++ source file and converts all ‘<’ symbols to “<” and all ‘>’ symbols to “>”. I wrote out the main method and everything compiled nicely but now that I'm actually writing out my convert function at the top of the program, I'm stuck in an infinite loop and I'm hitting a wall on what the culprit is. Could someone help me out?
I included the whole program in case the problem lies in my I/O coding but I surrounded the function with slashes. Hopefully I won't get flamed.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
//FUNCTION GOES THROUGH EACH CHARACTER OF FILE
//AND CONVERTS ALL < & > TO < or > RESPECTIVELY
//////////////THIS IS THE FUNCTION IN QUESTION//////////
void convert (ifstream& inStream, ofstream& outStream){
cout << "start" << endl;
char x;
inStream.get(x);
while (!inStream.eof()){
if (x == '<')
outStream << "<";
else if (x == '>')
outStream << ">";
else
outStream << x;
}
cout << "end" << endl;
};
///////////////////////////////////////////////////////////////////////////
int main(){
//FILE OBJECTS
ifstream inputStream;
ofstream outputStream;
string fileName;
//string outFile;
//USER PROMPT FOR NAME OF FILE
cout << "Please enter the name of the file to be converted: " << endl;
cin >> fileName;
//outFile = fileName + ".html";
//ASSOCIATES FILE OBJECTS WITH FILES
inputStream.open(fileName.c_str());
outputStream.open(fileName + ".html");
//CREATES A CONVERTED OUTPUT WITH <PRE> AT START AND </PRE> AT END
outputStream << " <PRE>" << endl;
convert(inputStream, outputStream);
outputStream << " </PRE>" << endl;
inputStream.close();
outputStream.close();
cout << "Conversion complete." << endl;
return 0;
}
It isn't a good approach to manipulate a file while you're reading it. The right way is, first read the whole file, store the data, manipulate the stored data, and then update the file. Hope this code will help you :)
void convert()
{
int countLines = 0; // To count total lines in file
string *lines; // To store all lines
string temp;
ifstream in;
ofstream out;
// Opening file to count Lines
in.open("filename.txt");
while (!in.eof())
{
getline(in, temp);
countLines++;
}
in.close();
// Allocating Memory
lines = new string[countLines];
// Open it again to stroe data
in.open("filename.txt");
int i = 0;
while (!in.eof())
{
getline(in, lines[i]);
// To check if there is '<' symbol in the following line
for (int j = 0; lines[i][j] != '\0'; j++)
{
// Checking the conditon
if (lines[i][j] == '<')
lines[i][j] = '>';
}
i++;
}
in.close();
// Now mainuplating the file
out.open("filename.txt");
for (int i = 0; i < countLines; i++)
{
out << lines[i];
if (i < countLines - 1)
out << endl;
}
out.close();
}

C++ read from file failing - g++11 - Ubuntu14

sorry for having to ask such a trivial question here, but I have to admit I can't think the reason that's causing my program to behave this way.
Here's the problem;
I'm trying to read from a file which has 32 lines with each line containing a 32-bit long binary number.
I've got a string array of size 32 and I'm trying to store each number from the file in it. It seems straight forward to me but then when I get to the line that tests getline() it jumps to the else bit and ouputs my error message. Initially it was working fine on eclipse but not from the terminal, I thought it had something to do with the permissions so I changed them all to rwx to no avail. I even tried changing the name but that caused the program to not work even in eclipse and now even going back to the original name doesn't work !!
I would appreciate if anyone can shed a light on the problem for me.
Ta!
Edit: Thank you guys for helping me investigate the problem, so far the file seems to be read just fine, I've got a cout statement in my main function to print the second element of the vector in which data is stored (after being read from the file) and it prints fine, in eclipse that is!! .When I compile the same code from the terminal and then run a.out it simply doesn't output anything.
I decided I would include my entire code and hope this will be more helpful.
Here's a quick recap to the questions I was asked:
-The file is just a simple text file that contains lines of 1's and 0's here's what it looks like
00000000000000000000000000000000
11100000000000100000000000000000
00010000000000010000000000000000
10010000000001100000000000000000
10010000000000100000000000000000
10010000000001100000000000000000
00000000000001110000000000000000
10000000001000000000000000000000
10110110010000000000000000000000
00000000000000000000000000000000
I've got a cpp file with it's corresponding header like this:
#ifndef MANCHESTER_H_
#define MANCHESTER_H_
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
using namespace std;
class Manchester {
private:
struct Processor
{
enum operation { JMP,JRP,LDN,STO,SUB,CMP,STP };
char accumulator[32]; // holds results of arithmetic operations.
char controlInstruction[32]; // program counter.holds the address of an instruction.
char presentInstruction[32]; //contains the actual instruction fetched and being executed.
};
Processor processor;
public:
vector<string> store;
int static const size = 32;
Manchester();
~Manchester();
void copyFromFileToStore();
string decToBinary(int );
int binToDecimal(string s);
string getInstruction(int lineNumber);
string getOperand(int lineNumber);
};
#endif /* MANCHESTER_H_ */
Here's the .cpp file
#include "Manchester.h"
Manchester::Manchester()
{
copyFromFileToStore(); // load the program in the store.
}
Manchester::~Manchester() {}
void Manchester::copyFromFileToStore()
{
ifstream myfile;
myfile.open("BabyTest1-MC.txt");
if (!myfile.is_open())
{
cout << "Cannot read file!" << endl;
}
else
{
int i =0;
while( i < 10)
{
string line;
if (getline(myfile,line))
{
store.push_back(line);
i++;
}
else
{
cout << "Error while reading file!" << endl; // always outputs when running the code.
return;
}
}
myfile.close();
}
}
string Manchester::decToBinary(int number)
{
string converted="";
char holder;
do
{
holder = number % 2 + '0';
converted = holder + converted;
number = number /2;
}while (number != 0);
string filler = "";
int stringsize = converted.size();
int diff = (8 - stringsize);
if (diff > 0)
{
for (int i = 0; i < diff; i++)
filler = filler + '0';
}
converted = filler + converted;
return converted;
}
int Manchester::binToDecimal(string s)
{
int converted =0;
int power = 0;
for (int i = s.size()-1; i >= 0; --i)
{
converted += (s[i] - '0') * pow(2, power);
power++;
}
return converted;
}
And finally the file containing the main():
#include "Manchester.h"
int main()
{
Manchester baby;
cout << baby.store.at(1);
return 0;
}
These the original parts that I posted that I didn't want to delete:
string store[32];
ifstream myfile;
myfile.open("BabyTest1-MC.txt");
if (!myfile.is_open())
{
cout << "Cannot read file!" << endl;
}
else
{
int i =0;
while( i < 32)
{
if (getline(myfile,store[i]))
{
i++;
}
else
{
cout << "Error while reading file!" << endl; // always outputs when running the code.
return;
}
}
myfile.close();
}
Sorry I'm editing to show you what works on eclipse but not from the terminal!!!
I simply don't understand the behaviour !!!
string store[32];
ifstream myfile;
myfile.open("BabyTest1-MC.txt");
if (!myfile.is_open())
{
cout << "Cannot read file!" << endl;
}
else
{
int i =0;
while( i < 32)
{
getline(myfile,store[i]);
i++;
}
myfile.close();
}
Why don't you use a std::vector<std::string>, and push_back() to populate it?
std::vector<std::string> store;
// ...
while(i < 32) {
std::string line;
if (getline(myfile,line)) {
store.push_back(line);
i++;
}
// ...
}
What about:
string store[32];
ifstream myfile;
int i;
myfile.open("filename.txt");
if (!myfile.is_open())
{
cout << "Cannot read file!" << endl;
}
else
{
for (i = 0; i < 32; i++)
{
if (!getline(myfile, store[i]))
{
cout << "Error while reading file!" << endl; // always outputs when running the code.
return 0;
}
}
myfile.close();
}
Tested it and it was working for me.
This way the for loop automatically increment you variable and if for some strange reason the program reaches the end of the file, it will display your error message.
I got some help from one of the guys at university and we figured what the problem was !!
It was to do with the endline characters. I'm working on linux which uses \n as the endline character but the file I'm trying to read was built on Windows which of course has \r\n as the endline character! Eclipse seems to be accepting both versions of end of line but not bash!
I edited my code to get rid of those characters altogether before storing them in the vector and it now works fine.
Sorry for the trouble caused in here and hope this will at least remind beginners that there is a difference between files built on windows, mac and linux !! and that attention needs to be made when working with different files !!
void Manchester::copyFromFileToStore()
{
ifstream myfile;
myfile.open("BabyTest1-MC.txt");
if (!myfile.is_open())
{
cout << "Cannot read file!" << endl;
}
else
{
int i =0;
string line;
while(getline(myfile,line))
{
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());
store.push_back(line);
i++;
}
myfile.close();
}
}