You can't write/read a std::string object as-is to/from a stream, let alone an array of strings, the way you are doing so. You are writing/reading each string's internal data, which amongst other things consists of a pointer to character data that is stored elsewhere in memory, possibly a small buffer for short-string optimizations, etc. You are writing/reading that internal data, not the actual character data. That is why you are getting "garbage" in your file.
When writing, you need to serialize the string character data in a format that you can then deserialize when reading back, eg:
struct student { string announce[10]; }; ostream& operator<<(ostream &os, const student &st) { for(int x = 0; x < 10; ++x) os << st.announce[x] << '\n'; return os; } istream& operator>>(istream &is, student &st) { for(int x = 0; x < 10; ++x) getline(is, st.announce[x]); return is; } void write_announcement() { student st; string line; int num; cout << "Enter number: "; cin >> num; cin.ignore(numeric_limits<streamsize>::max(), '\n'); if ((num < 0) || (num >= 10)) { cout << "Invalid number!" << endl; return; } cout << "Enter text: "; getline(cin, line); st.announce[num] = line; ofstream file("announcement.txt"); if (!file.is_open()) { cout << "Cannot create file!" << endl; return; } if (!(file << st)) { cout << "Cannot write to file!" << endl; } } void read_announcement() { student st; int num; cout << "Enter number: "; cin >> num; cin.ignore(numeric_limits<streamsize>::max(), '\n'); if ((num < 0) || (num >= 10)) { cout << "Invalid number!" << endl; return; } ifstream file("announcement.txt"); if (!file.is_open()) { cout << "Cannot open file!" << endl; return; } if (!(file >> st)) { cout << "Cannot read from file!" << endl; return; } cout << "Text: " << st.announce[num] << endl; }
Alternatively:
struct student { string announce[10]; }; ostream& operator<<(ostream &os, const student &st) { for(int x = 0; x < 10; ++x) { uint32_t len = st.announce[x].size(); os.write(reinterpret_cast<char*>(&len), sizeof(len)); os.write(st.announce[x].c_str(), len); } return os; } istream& operator>>(istream &is, student &st) { for(int x = 0; x < 10; ++x) st.announce[x].clear(); for(int x = 0; x < 10; ++x) { uint32_t len; if (!is.read(reinterpret_cast<char*>(&len), sizeof(len))) break; string s; if (len > 0) { s.resize(len); if (!is.read(&s[0], len)) break; } st.announce[x] = s; } return is; } void write_announcement() { student st; string line; int num; cout << "Enter number: "; cin >> num; cin.ignore(numeric_limits<streamsize>::max(), '\n'); if ((num < 0) || (num >= 10)) { cout << "Invalid number!" << endl; return; } cout << "Enter text: "; getline(cin, line); st.announce[num] = line; ofstream file("announcement.txt", ofstream::binary); if (!file.is_open()) { cout << "Cannot create file!" << endl; return; } if (!(file << st)) { cout << "Cannot write to file!" << endl; } } void read_announcement() { student st; int num; cout << "Enter number: "; cin >> num; cin.ignore(numeric_limits<streamsize>::max(), '\n'); if ((num < 0) || (num >= 10)) { cout << "Invalid number!" << endl; return; } ifstream file("announcement.txt", ifstream::binary); if (!file.is_open()) { cout << "Cannot open file!" << endl; return; } if (!(file >> st)) { cout << "Cannot read from file!" << endl; return; } cout << "Text: " << st.announce[num] << endl; }
That being said, you are creating a new local student every time you write/read the file, but you populate only 1 string on each write, and are not preserving previous strings across multiple writes. So, either:
read the file to load previous strings before then assigning and writing new strings.
make the student be a global variable so it exists longer than any single write/read operation, and thus can cache string assignments over time.
ifstream file; file.open("announcement.txt");toifstream file("announcement.txt");. And you don't need that call tofile.close();. The destructor will do that.std::stringas binary to a file. Thestd::stringcontains pointers and pointers will change upon each instantiation of your program. You'll have to either write the length first, followed by text or write the text followed by a nul,'\0'character.