0

I have been working on this for a while and can't fix it. I am very new to C++. So far I can get 10 things into my array but the output is not legible, it's just a bunch of numbers. I have read other posts with similar code but for some reason mine isn't working.

The input text file is 10 lines of fake data like this:

56790 "Comedy" 2012 "Simpsons" 18.99 1
56791 "Horror" 2003 "The Ring" 11.99 7

My code is here: (My output is below my code)

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

struct DVD {
    int barcode;
    string type;
    int releaseDate;
    string name;
    float purchaseprice;
    int rentaltime;
    void printsize();
};

int main () {

ifstream in("textfile.exe");

DVD c[10]; 
int i; 

for (int i=0; i < 10; i++){
in >> c[i].barcode >> c[i].type >> c[i].releaseDate >>
c[i].name >> c[i].purchaseprice >> c[i].rentaltime;
}

for (int i=0;i< 10;i++) {
            cout << c[i].barcode<<" ";
            cout << c[i].type<<" ";
            cout << c[i].releaseDate<<" ";
            cout << c[i].name << " ";
      cout << c[i].purchaseprice << " ";
      cout << c[i].rentaltime << "\n";
        }
return 0;
}

My output looks similar to garbage, but there are 10 lines of it like my array: -876919876 -2144609536 -2.45e7 2046

A comment on what to study to modify my code would be appreciated.

6
  • 6
    ifstream in("textfile.exe"); are you sure you want to read in an exe like a text file? Commented Nov 8, 2013 at 22:44
  • *sigh This is why I should be using makefiles instead of typing 100's of times into Cygwin. Commented Nov 8, 2013 at 22:47
  • I get 2 lines of my file now, but this is enough to figure out the rest of the problem. Commented Nov 8, 2013 at 22:48
  • @user2899211 this has nothing do with makefiles though Commented Nov 8, 2013 at 22:48
  • 1
    no but I wrote .exe instead of .txt because I have been typing .exe far more than any other extension. Commented Nov 8, 2013 at 22:49

2 Answers 2

2

As suggested by cmbasnett, ifstream in("textfile.exe") reads in an executable file. If you with for the program to read in a text file, changing it to ifstream in("textfile.txt") should work.

Sign up to request clarification or add additional context in comments.

Comments

1

You always need to check that your input is actually correct. Since it may fail prior to reading 10 lines, you should probably also keep a count of how many entries you could successfully read:

int i(0);
for (; i < 10
       && in >> c[i].barcode >> c[i].type >> c[i].releaseDate
             >> c[i].name >> c[i].purchaseprice >> c[i].rentaltime; ++i) {
    // ???
}

You actual problem reading the second line is that your strings are quoted but the approach used for formatted reading of strings doesn't care about quotes. Instead, strings are terminated by a space character: the formatted input for strings will skip leading whitespace and then read as many characters until another whitespace is found. On your second line, it will read "The and then stop. The attempt to read the purchaseprice will fail because Ring isn't a value numeric value.

To deal with that problem you might want to make the name quotedstring and define an input and output operators for it, e.g.:

struct quoted_string { std::string value; };

std::istream& operator>> (std::istream& in, quoted_string& string) {
    std::istream::sentry cerberos(in); // skips leading whitespace, etc.
    if (in && in.peek() == '"') {
        std::getline(in.ignore(), string.value, '"');
    }
    else {
        in.setstate(std::ios_base::failbit);
    }
    return in;
}
std::ostream& operator<< (std::ostream& out, quoted_string const& string) {
    return out << '"' << string.value << '"';
}

(note that the code isn't test but I'm relatively confident that it might work).

Just to briefly explain how the input operator works:

  1. The sentry is used to prepare the input operation:
    1. It flushes the tie()d std::ostream (if any; normally there is none except for std::cin).
    2. It skips leading whitespace (if any).
    3. It checks if the stream is still not in failure mode (i.e., neither std::ios_base::failbit nor `std::ios_base::badbit are set).
  2. To see if the input starts with a quote, in.peek() is used: this function returns an int indicating either that the operation failed (i.e., it returns std::char_traits<char>::eof()) or the next character in the stream. The code just checks if it returns " as it is a failure if the stream returns an error or any other character is present.
  3. If there is a quote, the quote is skipped using file.ignore() which by default just ignores one character (it can ignore more characters and have a character specified when to stop).
  4. After skipping the leading quote, std::getline() is used to read from file into string.value until another quote is found. The last parameter is defaulted to '\n' but for reading quoted string using a '"' is the correct value to use. The terminating character is, conveniently, not stored.

2 Comments

Yeah I noticed the space was the issue but seeing as I am still super new to this I was bad and changed the textfile to have no spaces. I will research this though. I did noticed the "operator" and "peek" in many other examples I just don't know what they are yet.
operator is for overloading the symbols (+,-,*,/,%,<<,>>,=, etc) to provide different/extended meaning for specific classes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.