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

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();
}
}

Related

File for loop doesn't open file c++

This file is not opening for a reason which I don't know really, any insight?
#include <iostream>
#include <string>
#include <algorithm>
#include <fstream>
#include <cctype>
using namespace std;
.
.
.
.
.
void MinHeap::TopKFrequentWord(string fileName, int k)
{
MinHeap mh;
Trie T;
string word;
string line;
ifstream inFile(fileName);
for (int i = 0; i < 22; i++)
{
if (i >= 10)
{
fileName = "C:\\Users\\Kareem's Laptop\\Desktop\\Reuters-21578\\reut2-0" + to_string(i) + ".sgm";
}
else if (i <= 9)
{
fileName = "C:\\Users\\Kareem's Laptop\\Desktop\\Reuters-21578\\reut2-00" + to_string(i) + ".sgm";
}
if (!inFile)
{
cout << fileName << " did not open." << endl;
exit(1);
}
bool found = true;
while (inFile >> line)
{
size_t pos = line.find("<BODY>");
if (pos != string::npos)
{
if (found)
{
word = line.substr(pos + 6);
found = true;
TrieNode* TN = T.search(word);
if (!TN)
{
TN = T.insert(word);
}
else
{
TN->frequency++;
}
mh.insert(TN, word);
}
}
}
mh.Display();
cout << '\n';
inFile.close();
}
}
int main()
{
MinHeap foo;
string fileName;
foo.TopKFrequentWord(fileName, 10);
return 0;
}
I have to open 21 files in a loop, read them all and print out the top 10 word count for all of those words.
Unable to use vector due to instructions. I apologize if similarities are obvious.
I tried putting all files in an array but it still didn't work. No errors just not opening (getting exit(1) command).
You are opening the file before the loop. Since you are updating the filename variable inside the loop, I suppose you want to open it each time you pass through the loop.
Move the line :
ifstream inFile(fileName);
to one line before the test:
if (!inFile)
Also, the place where you code ifstream inFile(fileName); you have an empty string in fileName (You didn't initialize the variable passed as argument in main).
Also, you are passing a int k parameter to the function but never uses it there.

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();
}

Line and word counter function not adding up correctly C++

This program is supposed to tell the user how many words and lines are in their program (text file only). The two functions that I have written both work, except the num_of_lines function is counting one more line than is correct every time and the num_of_words function is off by about 300 words every time. Not sure what I am doing wrong here. Any help will be greatly appreciated, thanks. I copy and pasted an output after my code and compared it to wc.
#include <iostream>
#include <fstream>
#include <cctype>
#define die(errmsg) {cerr << errmsg << endl; exit(1);}
using namespace std;
int num_of_words(string name)
{
int cnt2 = 0;
ifstream iwords;
iwords.open(name);
string w;
if(iwords.is_open())
{
while(iwords >> w)
{
cnt2++;
}
}
else cerr <<"can not open" + name << endl;
iwords.close();
return(cnt2);
}
int num_of_lines(string name)
{
int cnt3 = 0;
string line;
ifstream ilines;
ilines.open(name);
if(ilines.is_open())
{
while(getline(ilines, line))
{
cnt3++;
}
}
else cerr <<"can not open" + name << endl;
ilines.close();
return(cnt3);
}
int main(int argc, char **argv)
{
int num_of_lines(string name);
if(argc == 1)die("usage: mywc your_file");
string file;
file = argv[1];
ifstream ifs;
ifs.open(file);
if(ifs.is_open())
{
int b;
b = num_of_words(file);
cout <<"Words: " << b << endl;
}
else
{
cerr <<"Could not open: " << file << endl;
exit(1);
}
ifs.close();
return(0);
}
Zacharys-MBP:c++ Zstow$ my sample.txt
Chars: 59526
Words: 1689
Lines: 762
Zacharys-MBP:c++ Zstow$ wc sample.txt
761 2720 59526 sample.txt
Zacharys-MBP:c++ Zstow$
Most files (especially programs) will end in a new line. You may not see this in your editor but it is probably there. You will have to check the last line to see if it actually contains any content, or if it is empty.
The istream operator (>>) will detect any group of characters between whitespace to be a "word." So if you're parsing programs, you may have:
for(int i=1; i<73; i++)
The istream operator will see 4 words: [for(int, i=1;, i<73;, i++)]

C++ two function program - passing values back and forth between two functions [debug]

I think I am nearing a more elegant solution to a problem. I am trying to create a program that inputs text files of numbers, reads all the first digits, counts the total number of occurences for values 1-9, and then displays the analysis information. the first time I tried to do this, I ran the analyzeData function once with 9 different conditionals. I have since moved to tried to have analyzedata(string filename) pass a basic loop [for (int i; 1 <= 9; i++)] through countLines(string filename, int number) and then display the new counts.
however, i have come to a point where i think it's finished but it will not run. I have three errors on lines 59, 81, and 88. I went back through to check for brackets and semi colons. I have put a considerable bit of time and energy trying to make something efficient rather than a colossal copy and paste mess of doom.
sidenote- I am working in Xcode and the only "output" i can see because it will not run is "sh: PAUSE: command not found".
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
// function to pass digit value to. analyzeData will
// call this function for each digit value 1-9
int countLines(std::string filename, int number)
{
int count=0;
std::ifstream file;
std::string first_digit;
file.open( filename.c_str() );
if ( !file.good() )
{
std::cout << "**ERROR: file not found!" << std::endl;
exit(-1);
}
else
{
file >> first_digit;
if (number == 0)// calling analyzeData with number=0 will compute total # lines / input values
{
while (!file.eof())
{
count++;
}
}
else if (number != 0)
{
if (first_digit[0] == number)
{
count++;
}
}
file.close();
return count;
}
void analyzeData (std::string filename)
{
std::ifstream file;
std::string first_digit;
file.open( filename.c_str() );
if ( !file.good() )
{
std::cout << "**ERROR: file not found!" << std::endl;
exit(-1);
}
else
{
std::cout << filename << std::endl;
std::cout << countLines(filename,0) << std::endl; //total lines
for (int i=1;i <= 9;i++) //sends i through countLines for each digit value
{
std::cout << i << ": " << countLines(filename, i) << std::endl;
}
std::cout << std::endl;
file.close()
}
}
int main(int argc, const char * argv[])
{
analyzeData("***put file path here***");
analyzeData("***put file path here***");
analyzeData("***put file path here***");
system("PAUSE");
return EXIT_SUCCESS;
return 0;
}
Any help or constructive criticism is welcome.
As I was writing this I had a moment of realization! On line 45 I set a conditional for a string index character to be equivalent to a int variable.... this must be a source of error somehow. Can anyone show me how to make the int variable be read as a string? .c_str()??