0

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();
}
Ouanixi
  • 116
  • 1
  • 9
  • Try using while(!myfile.eof()). – user2970916 Nov 18 '14 at 19:55
  • `while(!myfile.eof() && i <= 31)` – bialpio Nov 18 '14 at 19:56
  • 3
    Please **never** use `myfile.eof()`: http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – Galik Nov 18 '14 at 19:57
  • You do realize that `getline()` is bound to fail eventually when it reaches the end don't you? Also your loop should probably be `while(i < 32)` (0-31 = 32 values). – Galik Nov 18 '14 at 19:58
  • @Galik _"Please never use myfile.eof() ..."_ While you're right with that recommendation, I can't spot where it's used in the sample code actually?!? – πάντα ῥεῖ Nov 18 '14 at 20:01
  • @πάνταῥεῖ I was responding to those who are advising to use `eof()`. – Galik Nov 18 '14 at 20:02
  • Thanks for the reply guys! I appreciate it needs to be (i < 32 or <=31) I must have forgotten it when I was trying different options. This still didn't make any difference as to whether getline works or not :( – Ouanixi Nov 18 '14 at 20:03
  • @Galik Ah, I see. You should have directed your comment to _@bialpio_. – πάντα ῥεῖ Nov 18 '14 at 20:03
  • @Galik Yes getline() will fail eventually but for some reason it's not even passing the test at the start !!! – Ouanixi Nov 18 '14 at 20:08
  • Try to see what the error is by reading the return value of `getline`. It might give you a clue. You can do this by calling one of the `iostate` methods (see http://www.cplusplus.com/reference/ios/ios_base/iostate/) on `myfile` after the failed `getline` call. – Hanna H Nov 18 '14 at 20:19
  • Is it possible that you have two files called `"BabyTest1-MC.txt"` and one of them is empty? In *eclipse* it may be working from a different base directory than in the shell and therefore opening a different file. – Galik Nov 18 '14 at 20:29
  • You are saying that you are reading binary values of 32bits in a text file. Is every line like this: `01010110101101010100101010101010` or is it true binary data in 4 bytes of files separated by a \n character? – Darien Pardinas Nov 18 '14 at 20:32
  • @DarienPardinas `.txt` extension counts against that assumption. But I've been stumbling about this mentioning of _32 bit binary number_ as well. The OP is simply unclear about the actual input processed from `BabyTest1-MC.txt`. – πάντα ῥεῖ Nov 18 '14 at 20:53
  • I'm going to edit my question as there are a couple of more clues that are worth looking into. I managed to get the file to be read now. I'm going to post the entire code for you to have a look! – Ouanixi Nov 18 '14 at 21:27

3 Answers3

1

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++;
    }
    // ...
 }
πάντα ῥεῖ
  • 83,259
  • 13
  • 96
  • 175
  • Because the code doesn't get passed if (getline(myfile,line)) even if I just put a simple cout statement after the condition it won't get to it, it just jumps to the else section as for some reason getline isn't working at all !!! – Ouanixi Nov 18 '14 at 20:05
  • @Ouanixi Problems with `myfile.open("BabyTest1-MC.txt");` actually? Are you sure that file exists in the same directory where your executable is actually running? Check the Eclipse Debug options used. – πάντα ῥεῖ Nov 18 '14 at 20:08
  • Yes I am sure! I've edited my original code to show that the code works when I don't test the getline(). However, it only when I run it from Eclipse, not when compiled manually on the terminal. And I know I'm using the same g++ on both! Strange !! – Ouanixi Nov 18 '14 at 20:11
  • your code works fine but still not working from the command line. I need to investigate this further. I'm now starting to believe that there is nothing wrong with the code !!!! – Ouanixi Nov 18 '14 at 21:25
  • @Ouanixi _" I'm now starting to believe that there is nothing wrong with the code !!!!"_ besides you actually have problems with `myfile.open("BabyTest1-MC.txt");`, or what's really given in the input stream. Your statement _"... each line containing a 32-bit long binary number ..."_ is what makes me really suspecting, what your input actually is, and what you think it is. – πάντα ῥεῖ Nov 18 '14 at 21:30
  • I've just edited my question to include the data that's in the file. At the moment Eclipse compiles and prints the second element on the console. But the terminal compiles and then shows nothing :( – Ouanixi Nov 18 '14 at 21:42
  • @Ouanixi That edit doesn't really improve improve your question. Do you actually have problems to convert the 32-bit binary digit bit fields to numbers? Have a look at the [`std::bitset<>`](http://en.cppreference.com/w/cpp/utility/bitset) class, and it's [features to convert from string](http://en.cppreference.com/w/cpp/utility/bitset/bitset). – πάντα ῥεῖ Nov 18 '14 at 21:47
  • No don't worry about the binary part. The program is to simulate the fetch execute cycle on a Manchester baby machine. Part of it is to read the file line by line and store each line in a simple data Structure, array or vector etc.. And that seems to work fine on eclipse but not when I compile manually from the terminal!! – Ouanixi Nov 18 '14 at 21:51
  • @Ouanixi Well, build settings for eclipse and just a call of the makefile from a terminal might differ. It's hard to tell what's your problem actually. – πάντα ῥεῖ Nov 18 '14 at 21:54
  • I found what the problem was. Will post the answer now! – Ouanixi Nov 19 '14 at 12:37
1

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 just tried this, still the same problem! On Eclipse: - It seems that reading the file works and it does output the error message at the end. From Bash: - It just outputs "Error while reading file!" No idea what's going on ! – Ouanixi Nov 18 '14 at 20:17
  • That's really weird. I tested this code myself. And it worked. OH wait! I think I might know what's wrong. Does your file contain 32 lines? If it contains less lines it will raise the error because then the loop would execute and try to read past the end of the file? – user4155352 Nov 18 '14 at 21:17
  • Hmm you might have put a finger on something there. My file contains only 10 or 11 lines ! I tried it again though by limiting the loop to 10. Let me rewrite a few things and use a vector instead like @πάντα ῥεῖ suggested. – Ouanixi Nov 18 '14 at 21:18
0

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();
    }
}
Ouanixi
  • 116
  • 1
  • 9