Unreadable output file, is this a fault? - c++

Here is my code:
#include <stdio.h>
#include <iostream>
#include <conio.h>
char filename[100];
FILE *stream, *stream2;
char s[20];
struct date
{
int day, month, year;
};
struct employee
{
int ID;
char name[100];
date birthdate;
char address[20];
char rank[20];
int money;
};
void main()
{
errno_t err;
// Open for read (will fail if file "crt_fopen_s.c" does not exist)
// Open for write
err = fopen_s(&stream2, "C:/Users/Van/Desktop/LAALAL/fool.txt", "w+");
if (err == 0)
{
employee nv;
std::cout << "\nInput information of an employee:\n";
std::cout << "\tInput ID : ";
std::cin >> nv.ID;
std::cin.sync();
std::cout << "\tInput name : ";
std::cin.clear();
gets_s(s);
gets_s(nv.name);
std::cout << "\tInput birthdate (Day Month Year ) : ";
std::cin >> nv.birthdate.day >> nv.birthdate.month >> nv.birthdate.year;
std::cout << "\tInput address: ";
std::cin.clear();
gets_s(s);
gets_s(nv.address);
std::cout << "\tInput rank : ";
std::cin.clear();
gets_s(s);
gets_s(nv.rank);
std::cout << "\tMoney : ";
std::cin >> nv.money;
std::cin.sync();
std::fwrite(&nv, sizeof(nv), 1, stream2);
std::fclose(stream2);
}
}
Well I don't have any problem with the code, but when I input my information, I cant read the output in the file. Here is the picture of my output:
What is my problem?
Thanks in advance for your time!

You are using fwrite() function, which writes data to files as binary, not as text (ASCII). You should be using std::ofstream class from <fstream> (instead of FILE), together with << operator.
More info here:
http://www.cplusplus.com/doc/tutorial/files/
Example code:
#include <iostream>
#include <fstream>
using namespace std;
struct some_struct{
int some_int;
char some_char;
};
int main () {
struct some_struct x;
x.some_int = 123123;
x.some_char = 'x';
//This is how you open the file.
ofstream myfile;
myfile.open ("example.txt");
//This is is how you write to it.
myfile << "Integer: " << x.some_int << " Char: " << x.some_char;
//This is how you close it.
myfile.close();
return 0;
}
Output inside the file example.txt:
Integer: 123123 Char: x

You can use fstream library to programming by operators like << or >>
#include <iostream>
#include <fstream>
using namespace std;
struct date
{
int day, month, year;
};
struct employee
{
int ID;
char name[100];
date birthdate;
char address[20];
char rank[20];
int money;
};
int main()
{
char ch;
ofstream file("fool.txt");
if (!file)
{
cout << ""Cannot open file, press any key to continue ...";
cin.get();
exit(0);
}
employee nv;
cout << "\nInput information of an employee:\n";
cout << "\tInput ID : ";
cin >> nv.ID;
cin.ignore();
cout << "\tInput name : ";
gets_s(nv.name);
cout << "\tInput birthdate (Day Month Year) : ";
cin >> nv.birthdate.day >> nv.birthdate.month >> nv.birthdate.year;
cin.ignore();
cout << "\tInput address: ";
gets_s(nv.address);
cout << "\tInput rank: ";
gets_s(nv.rank);
cout << "\tMoney: ";
cin >> nv.money;
cin.ignore();
file << nv.ID << ' ' << nv.name << ' ' << nv.birthdate.day
<< ' ' << nv.birthdate.month << ' ' << nv.birthdate.year
<< ' ' << nv.address << ' ' << nv.rank << ' ' << nv.money << ' ';
file.close();
cout << "\nOutput From File : \n";
ifstream file2("fool.txt");
file2.get(ch);
while (!file2.eof())
{
cout.put(ch);
file2.get(ch);
}
file2.close();
cout << "\nOutput Completed";
cin.get();
}
and pay attention to these hints :
Declare the usage of std namespace in your code first, so you can remove the std:: clauses.
using namespace std;
cin.clear() and cin.sync() are not necessary, just use cin.ignore() after input a integer type and before input a char type
cin >> nv.ID;
cin.ignore();
gets_s(nv.name);
see this post to understand it better
you are collecting char s[20]; from input in some lines. Why?? remove it
in this example and using operators for file programming ( << ) you should add a space character after writing each data to file for separate data
file << nv.ID << ' ' << nv.name
standard functions for input or print char type are gets() and puts(), but you use gets_s() that I think it's because of secure warning, you can disable this error, In this case, if you want your code to use another compiler it will not be a problem. You can only comment one line instead of change many lines
#pragma warning(disable: 4996)

Related

read /write file in c++, choose option

I'm trying to write a code for signup / login while being able to write and read from the file. So far I am able to write in the file and asked for the users input and displayed in the file (signup).
My problem is now,
How do I do the login part, in which when the user chooses login, they are able to choose what username they want based on a selection of usernames and the input they have made while choosing the first option?
How can this information be read and displayed in the file?
Expected output for user login
Choose you username:
0:mike
1:Linda
2:Martha
Expected input from the user
your choice: "Key in choice"
So far the code displayed works, but I am not sure what to do for my next step.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
int option;
int age,height;
string name;
string database;
ofstream file_out;
ifstream file_in;
cout << " For sign up type 1" <<endl;
cout << " For log in type 2" <<endl;
cin >> option;
if ( option == 1 ) {
file_out.open("database.txt");
cout << "Input name: \n";
cin >> name;
cout << "Input age: \n";
cin >> age;
cout << " Input height: \n";
cin >> height;
//write file
file_out << name << endl;
file_out << age << endl;
file_out << height << endl;
file_out.close();
} else if (option == 2) {
//read file
file_in.open("database.txt");
cout << "choose your username: " << endl;
// input line of code
while ( getline(file_in, database));
//input line of code
cout << database << endl;
You can do something like this. Print all the usernames, but before printing out check if they are numbers with help of the stof function, if they are numbers we don't have to do anything, but if it is a string it will throw an exception, so in the catch block we print it and store it into dictionary/map for easy retrieval.
#include <fstream>
#include <iostream>
#include <map>
int main(void) {
std::fstream file;
file.open("secret.txt", std::ios::in);
std::map<int, std::string> map;
std::string username;
int count = 1;
while (!file.eof()) {
file >> username;
try {
std::stof(username);
} catch (...) {
std::cout << count << ". " << username << "\n";
map.insert(std::make_pair(count, username));
count++;
}
}
int choice;
std::cout << "Choose your username: ";
std::cin >> choice;
username = map.at(choice);
std::cout << "Your username is set to " << username;
return 0;
}

ifstream usage and user input not outputting content to read

I'm practicing ifstream usage. I want the user to enter the file they want to read, in this example num1.txt specifically. I want the console to read one letter from num1.txt and output it on its own line.
I've ran the code below, and after entering "num1.txt" into the console, I get nothing back. I've tried moving around cout << num << endl; to the inner do statement, but it ends up repeating the number 10 an infinite amount.
What am I doing wrong here?
Contents in num1.txt:
2 4 6 8 10
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
string fileName, cont;
ifstream inputFile;
do {
int num = 0;
int total = 0;
cout << "Please enter the file name: ";
cin >> fileName;
inputFile.open(fileName);
if (inputFile.is_open()) {
do {
inputFile >> num;
total += num;
}
while(num > 0);
if (total != 0) {
cout << num << endl;
cout << "Total is: " << total << endl;
}
}
else {
cout << "Failed to open file." << endl;
}
inputFile.close();
cout << "Do you want to continue processing files? (yes or no): " << endl;
cin >> cont;
}
while (cont == "yes");
}
Your inner do loop is not correctly validating that operator>> is actually successful before using num. It should be looking at the stream's error state after each read. The easiest way to do that is to change your do loop into a while loop that uses the result of the read as its loop condition, eg:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
string fileName, cont;
ifstream inputFile;
do {
cout << "Please enter the file name: ";
cin >> fileName;
inputFile.open(fileName);
if (inputFile.is_open()) {
int num = 0;
int total = 0;
while (inputFile >> num) {
total += num;
}
inputFile.close();
cout << "Total is: " << total << endl;
}
else {
cout << "Failed to open file." << endl;
}
cout << "Do you want to continue processing files? (yes or no): " << endl;
}
while ((cin >> cont) && (cont == "yes"));
return 0;
}

How to create multiple file in fstream with loop [duplicate]

This question already has answers here:
How to concatenate a std::string and an int
(25 answers)
Closed 2 years ago.
I am new in coding and in this community I want to save multiple student info in multiple file in ".txt" file like "student1.txt", "student2.txt", "student3.txt" etc. See my code then I hope you will understand my problem.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main() {
for(int i = 1; i < 30; i++) {
string name, roll, gpa;
cout << "Enter student info";
cout << "name :";
cin >> name;
cout << "\nEnter Roll :";
cin >> roll;
cout << "\nEnter gpa :";
cin >> gpa;
ofstream file;
/* Problem part :I know this part of code will never work */
file.open("Student <<i<<".txt");
/* what should I do */
file << name << endl << roll << endl << gpa;
file.close();
}
}
Here is what I think you need: std::to_string and operator+ (string)
Check out the answers on this thread. There they have shown numerous methods to do this.
Code:
#include <fstream>
#include <iostream>
#include <string>
int main() {
for (int i = 1; i < 30; i++) {
std::string name, roll, gpa;
std::cout << "Enter student info : " << std::endl;
std::cout << "Name : ";
std::cin >> name;
std::cout << "Enter roll number : ";
std::cin >> roll;
std::cout << "Enter GPA : ";
std::cin >> gpa;
std::ofstream file("Student" + std::to_string(i) + ".txt");
file << name << std::endl
<< roll << std::endl
<< gpa << std::endl;
}
}

error: request for member which is of non-class type 'MULTIMEDIA_FILME [500]'| [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
So the main objective of the program was to build a file and save on it the data I would input.
I did this with char and worked perfectly but I wanted to do with string too, so I tried the way I did with char and it gives me some errors
error: request for member 'nome' in 'filmes', which is of non-class type 'MULTIMEDIA_FILME [500]'|
and the same for every string.
I tried deleting the [500] and the [1] in each string and it works, but I wanted to add and save various datas for the same strucure like:
Nome: "some name"
Tipo: "some type of movie"
Ano: "some year"
Descricao: "some description"
....
and repeat it once I do other input.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct MULTIMEDIA_FILME
{
string nome;
string tipo;
int ano;
string descricao;
};
int main()
{
using namespace std;
struct MULTIMEDIA_FILME filmes [500] ;
fstream myFile("filme.txt", ios::in | ios::out | ios::app);
ofstream filme_txt;
filme_txt.open("filme.txt");
cout << "Nome do filme:" << endl;
cin >> filmes.nome[1];
filme_txt << filmes.nome[1] << endl;
cout << "Tipo do filme:" << endl;
cin >> filmes.tipo[1];
filme_txt << filmes.tipo[1] << endl;
cout << "Ano do filme:" << endl;
cin >> filmes.ano[1];
filme_txt << filmes.ano[1] << endl;
cout << "Descricao do filme:" << endl;
cin >> filmes.descricao[1];
filme_txt << filmes.descricao[1] << endl;
filme_txt.close();
}
EDIT1:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct MULTIMEDIA_FILME
{
string nome;
string tipo;
int ano;
string descricao;
};
int main()
{
int n_filmes=0,contador,i=0;
struct MULTIMEDIA_FILME filmes [500] ;
FILE *ficheiro_num_filmes;
ficheiro_num_filmes=fopen("num_filmes.txt","rb");
if(ficheiro_num_filmes==NULL)
{
ficheiro_num_filmes=fopen("num_filmes.txt","wb");
fwrite(&n_filmes,sizeof(int),1,ficheiro_num_filmes);
fclose(ficheiro_num_filmes);
}
else
{
fread(&n_filmes,sizeof(int),1,ficheiro_num_filmes);
fclose(ficheiro_num_filmes);
}
fstream myFile("filme.txt", ios::in | ios::out | ios::ate | ios::app);
ofstream filme_txt;
filme_txt.open("filme.txt");
cout << "Quanto filmes deseja gravar:" << endl;
cin >> contador;
cout << "Nome do filme:" << filmes[1].nome << endl;
do{
cout << "Nome do filme:" << n_filmes+1 << endl;
cin >> filmes[1+n_filmes].nome;
filme_txt << filmes[1+n_filmes].nome << endl;
cout << "Tipo do filme:" << endl;
cin >> filmes[1+n_filmes].tipo;
filme_txt << filmes[1+n_filmes].tipo << endl;
cout << "Ano do filme:" << endl;
cin >> filmes[1+n_filmes].ano;
filme_txt << filmes[1+n_filmes].ano << endl;
cout << "Descricao do filme:" << endl;
cin >> filmes[1+n_filmes].descricao;
filme_txt << filmes[1+n_filmes].descricao << endl;
n_filmes ++;
i++;
}while(i<contador);
filme_txt.close();
ficheiro_num_filmes=fopen("num_filmes.txt","w+b");
fwrite(&n_filmes,sizeof(int),1,ficheiro_num_filmes);
fclose(ficheiro_num_filmes);
}
The program has two problems:
The program declares 500 filmes objects. This means that when you want to access the objects, the subscript should be provided prior to the member, e.g.
filmes.nome[1]
should be
filmes[1].nome
There is no need to declare 500 objects. Unless there is a requirement to create 500 different files, or to be able to store 500 different film objects, only one film object need be created. So, a simplified version of the program would be:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct MULTIMEDIA_FILME {
string nome;
string tipo;
int ano;
string descricao;
};
int main() {
struct MULTIMEDIA_FILME filmes;
fstream myFile("filme.txt", ios::in | ios::out | ios::app);
ofstream filme_txt;
filme_txt.open("filme.txt");
cout << "Nome do filme:" << endl;
cin >> filmes.nome;
filme_txt << filmes.nome << endl;
cout << "Tipo do filme:" << endl;
cin >> filmes.tipo;
filme_txt << filmes.tipo << endl;
cout << "Ano do filme:" << endl;
cin >> filmes.ano;
filme_txt << filmes.ano << endl;
cout << "Descricao do filme:" << endl;
cin >> filmes.descricao;
filme_txt << filmes.descricao << endl;
filme_txt.close();
}
If you truly wish to see 500 films stored in a single file, then you need to add some sort of while() loop to query up to 500 times for the film objects. As your requirement did not request this, and as there is no loop in your program, I have not tried to debug this fork of the problem.
Here is updated code with a for loop in response to your comment. Much more can be done. The requirements are not clear as to when you want to overwrite the file(s) and when you want to append, and when you want to read back the contents of the file. I suspect those are additional requirements that will come later.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Multimedia_Filme {
string nome;
string tipo;
int ano;
string descricao;
};
int GetFilmCountFromFile(const string &fileName) {
ifstream myFile;
myFile.open(fileName);
if (myFile.is_open()) {
string line;
getline(myFile, line);
return stoi(line); // convert string to int
} else {
return 0;
}
}
void WriteFileCountToFile(const string &fileName, int fileCount) {
ofstream myFile;
myFile.open(fileName);
if(myFile.is_open()) {
myFile << fileCount << endl;
myFile.close();
}
}
int GetIntFromUser(string prompt) {
int count;
cout << prompt << endl;
cin.clear();
cin >> count;
return count;
}
string GetStringFromUser(string prompt) {
string returnString;
cout << prompt << endl;
cin.clear();
cin.ignore(1);
cin >> returnString;
return returnString;
}
int main(int argc, char **argv) {
int n_filmes = 0, contador, i = 0;
Multimedia_Filme filmes[500];
n_filmes = GetFilmCountFromFile("filmCountFile.txt");
contador = GetIntFromUser("Quanto filmes deseja gravar: ");
ofstream filmeFile;
filmeFile.open("filme.txt");
if(filmeFile.is_open()) {
for (int i = 0; i < contador; i++) {
filmes[i].nome = GetStringFromUser("Nome do filme: ");
filmes[i].tipo = GetStringFromUser("Tipo do filme: ");
filmes[i].ano = GetIntFromUser("Ano do filme: ");
filmes[i].descricao = GetStringFromUser("Descricao do filme: ");
filmeFile << filmes[i].nome << endl
<< filmes[i].tipo << endl
<< filmes[i].ano << endl
<< filmes[i].descricao << endl;
}
filmeFile.close();
}
WriteFileCountToFile("num_filmes.txt", contador);
}

Over looping (Cout) in C++

#include <iostream>
#include <string>
#include <cctype>
using namespace std;
char hold;
string name;
char num1;
char num2;
int main() {
cout << "Hello!\n";
cout << "Tell me your name?: ";
cin >> name;
cout << "Well well well, if it isn't "<< name << "!\n";
cout << "Enter a NUMBER " << name << ": ";
cin >> num1;
while(!isdigit(num1)) {
cout << "Enter a NUMBER " << name << ": ";
cin >> num1;
}
cin >> hold;
system("pause");
return 0;
}
The problem is, it is overlooping the cout. How do I fix it?
Thanks.
A better way is to use std::stringstream (note: include sstream)
int getNumber()
{
std::string line;
int i;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> i)
{
if (ss.eof())
{
break;
}
}
std::cout << "Please re-enter your input as a number" << std::endl;
}
return i;
}
This replaces your while loop, and you make the call after asking for a number as you already figured out how to do.
The following is a shortened version of the original attempt. However, as with the original, it only checks a single character.
If I changed num1 to be an int then i'd need to check whether the input was valid as #Dieter Lucking mentioned.
#include <iostream>
using namespace std;
int main() {
char num1;
do {
cout << "\nEnter a number: ";
cin >> num1
} while(!isdigit(num1));
}
A bit of a variation on staticx's solution, which will pass Dieter Lücking's echo "" | test line.
I use an istringstream and get input until no more standard input or I get valid input. I pushed it all into a templated Get function that can be used for any type; you just need to give it a prompt for the user:
Get() function
template<typename T>
void Get(T& toSet, std::string prompt) // read from cin
{
std::string nextIn;
cout << prompt;
getline(cin >> std::ws, nextIn);
istringstream inStream(nextIn);
while(cin && !(inStream >> toSet))
{
inStream.clear();
cout << "Invalid Input. Try again.\n" << prompt;
getline(cin >> std::ws, nextIn);
inStream.str(nextIn);
}
if (!cin)
{
cerr << "Failed to get proper input. Exiting";
exit(1);
}
}
And you'd use it like so:
int myNumber = 0;
Get(myNumber, "Please input a number:");
Full code:
Live Demo
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template<typename T>
void Get(T& toSet, std::string prompt) // read from cin
{
std::string nextIn;
cout << prompt;
getline(cin >> std::ws, nextIn);
istringstream inStream(nextIn);
while(cin && !(inStream >> toSet))
{
inStream.clear();
cout << "Invalid Input. Try again.\n" << prompt;
getline(cin >> std::ws, nextIn);
inStream.str(nextIn);
}
if (!cin)
{
cerr << "\nFailed to get proper input. Exiting\n";
exit(1);
}
}
int main()
{
string name;
int num1 = -1;
cout << "\nHello!\n";
Get(name, "\nTell me your name?:");
cout << "\nWell well well, if it isn't "<< name << "!\n";
Get(num1, std::string("\nEnter a NUMBER, ") + name + ": ");
cout << "\nYou entered number: " << num1 << std::endl;
return 0;
}