0

I have a CS project and I am trying to write/read strings into a string variable, say x of size 10. I am new to coding, and I am making some mistake with writing to file. Please help me.

Here is the class I have defined in my project file that includes my string x[10] array. I am pretty sure that I am making a mistake in writing to file, because it adds garbage characters in the file.

void write_announcement() { student st; string line; int num; ofstream file; file.open("announcement.txt"); cout << "Enter number:"; cin >> num; cin.ignore(); getline(cin,line); announce[num] = line; file.write(reinterpret_cast<char *> (&st), sizeof(student)); file.close(); } void read_announcement() { student st; int n; cout << "Enter n: "; cin >> n; ifstream file; file.open("announcement.txt"); while (file >> st.announce[n]); { cout << announce[n]; } file.close(); } 
4
  • 1
    What is announce? st.announce? Commented Nov 23, 2018 at 17:53
  • 3
    Welcome to Stack Overflow. Please take the time to go through the The Tour and refer to the material from the Help Center on what and how you can ask here. It's especially important to post a minimal reproducible example. Commented Nov 23, 2018 at 17:53
  • 1
    This doesn't address the question, but get in the habit of initializing objects with meaningful values instead of creating them and immediately assigning a value. That is, change ifstream file; file.open("announcement.txt"); to ifstream file("announcement.txt");. And you don't need that call to file.close();. The destructor will do that. Commented Nov 23, 2018 at 18:34
  • BTW, you can't write std::string as binary to a file. The std::string contains 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. Commented Nov 23, 2018 at 18:44

1 Answer 1

1

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:

  1. read the file to load previous strings before then assigning and writing new strings.

  2. 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.

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

5 Comments

Remy Lebeau I am still not able to write in the file using the code you wrote for me. Can you please put a little more effort in it, so I can do it. Please! and guys announce is the string array that I am using there, sorry I mentioned x above when I wrote my question.
@MuhammadNoman "I am still not able to write in the file" - why not? Where does it fail for you exactly? I added error checking you are lacking. What is the output? Please be more specific. "Can you please put a little more effort in it" - excuse me? I actually put a lot of effort into what I have posted so far. Why don't you put more effort into learning how to debug your own code? It is an essential skill to have. StackOverflow is not a debugging service, it is not a code writing service, so don't treat it like one.
ah well fine thank you for helping me. I am very new to programming, and my teacher gave us project too earlier. and he has not taught us enough. Sorry for inconvenience. Btw I have fixed one error in code that you gave me up there. It asks me to write text but does not store into file.
actually sorry it asks to enter text but it stores the newly entered text into file and removes the previous one
@MuhammadNoman makes sense, as 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 1) read the file to load previous strings before writing a new string, or 2) make the student be a global variable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.