Way to handle the objects in C++ - c++

Every time when I run the code Compiler give the error of object already define and I don't know where I am making mistakes in the whole code.
Even if I do this all in one file it is working but I don't know why its not working in this style can anyone help me that where I am doing mistake in this code.
Any help would be appreciated.
Thank you
student.h
ifndef STUDENT
define STUDENT
class Student
{
public:
char student_no[10];
char student_name[20];
char student_address[20];
char student_score[20];
Student();
};
Student::Student()
{//constructor
student_no[0] = 0; student_name[0] = 0; student_address[0] = 0;
student_score[0] = 0;
}
#endif
student.cpp
using namespace std;
#include "writestr.cpp"
#include <fstream>
#include <string.h>
#include <iostream>
int main(){
char filename[20];
Student s;
cout << "Enter the file name:" << flush;
cin.getline(filename, 19);
ofstream stream(filename, ios::out);
if (stream.fail()) {
cout << "File open failed!" << endl;
return 0;
}
while (1) {
cin >> s; // read fields of person
if (strlen(s.student_name) == 0) break;
// write person to output stream
stream << s; // write fields of person
}
return 1;
}
Problems occured
This is the portion where I write the streaming code.
writestr.cpp
using namespace std;
#include "readper.cpp"
#include <fstream>
#include <string.h>
#include <iostream>
ostream & operator << (ostream & stream, Student & s)
{ // insert fields into file
stream << s.student_name << s.student_no << s.student_address
<< s.student_score;
return stream;
}
readper.cpp
using namespace std;
#include "student.h"
#include <fstream>
#include <string.h>
#include <iostream>
istream & operator >> (istream & stream, Student & s)
{ // read fields from input
cout << "Enter Student Name, or <cr> to end: " << flush;
stream.getline(s.student_name, 30);
if (strlen(s.student_name) == 0) return stream;
cout << "Enter Student Name: " << flush; stream.getline(s.student_name, 30);
cout << "Enter Student Id Number: " << flush; stream.getline(s.student_no, 30);
cout << "Enter Address: " << flush; stream.getline(s.student_address, 30);
cout << "Enter Score: " << flush; stream.getline(s.student_score, 15);
return stream;
}

You are defining (not just declaring) the constructor in the header file:
Student::Student()
{//constructor
student_no[0] = 0; student_name[0] = 0; student_address[0] = 0;
student_score[0] = 0;
}
This defines the constructor (generates the code) again and again in every cpp that includes the header file. Since this definition has no inline keyword, it may exist exactly once in the program, not multiple times. Defining the non-inline constructor in multiple translation units (cpp files) causes the error.
Possible solutions:
Move the constructor definition into the class, or
Prefix it by an inline keyword, or
Move it to one of the cpp files
Another issue: you include cpp files, which cause a lot more issues by declaring the same thing again and again. Simply add them to the project/makefile/etc, instead of including:
#include "writestr.cpp"

Related

OOP can't get value from a class

So I read a file in a function and set values to a class. I would like to read those same values in another function (another .cpp file) and I can't get it to work.
This is the code where I read values from .txt file. This seems to work. I can cout the value that I read.
#include "branjeDatoteke.h"
#include "parametri.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
void branjeDatoteke() {
Parametri pin[101];
string line;
ifstream myfile("pin.txt");
if (myfile.is_open())
{
for (int i = 0; i <= 100 && getline(myfile, line); i++)
{
pin[i].setPin(line);
// cout << pin[i].readPin() << endl;
//cout << line << '\n';
}
myfile.close();
// cout <<"tole more delat: "<< pin[2].readPin() << endl;
}
else cout << "Unable to open file";
}
And this is the code where I want to get the same values again, but cout is not working. I just get blank console where the cout should be.
#include <iostream>
#include "pin.h"
#include "parametri.h"
#include <string>
#include "branjeDatoteke.h"
using namespace std;
void pinPass() {
Parametri pin[101];
string pinKoda;
branjeDatoteke();
cout << pin[0].readPin() << endl;
cout << "Vnesite pin: ";
cin >> pinKoda;
for (int i = 0; i <= 100; i++) {
if (pin[i].readPin() == pinKoda) {
cout << pin[i].readPin() << endl;
cout << "KODA JE PRAVILNA" << endl;
}
else if (i > 100) {
cout << "kode ni v sistemu" << endl;
}
}
}
Assuming your Parametri class is correct, the issue is you are using local variables so they are initialised every time you call the function. They are allocated on the stack, locally for the calling function and can't be used outside of the function that declares them, at least not the way you're doing it. If you call the function twice you also have to assume all local variables must be reinitialised. One way you could solve this would be promoting your pin variable to global, like so:
// your_file_one.cpp
Parametri pin[101];
void PinPass() {
...
}
If you want to use it in another cpp file, then you have to redeclare the variable in the other file as well, like follows:
// your_file_two.cpp
extern Parametri pin[101];
The extern keyword specifies the variable was declared in another compilation unit - for simplicity let's imagine each C++ file which is not a header file as a separate compilation unit.
So your code will look like:
#include "branjeDatoteke.h"
#include "parametri.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
Parametri pin[101];
void branjeDatoteke() {
string line;
ifstream myfile("pin.txt");
if (myfile.is_open())
{
for (int i = 0; i <= 100 && getline(myfile, line); i++)
{
pin[i].setPin(line);
// cout << pin[i].readPin() << endl;
//cout << line << '\n';
}
myfile.close();
// cout <<"tole more delat: "<< pin[2].readPin() << endl;
}
else cout << "Unable to open file";
}
And
#include <iostream>
#include "pin.h"
#include "parametri.h"
#include <string>
#include "branjeDatoteke.h"
using namespace std;
extern Parametri pin[101];
void pinPass() {
string pinKoda;
branjeDatoteke();
cout << pin[0].readPin() << endl;
cout << "Vnesite pin: ";
cin >> pinKoda;
for (int i = 0; i <= 100; i++) {
if (pin[i].readPin() == pinKoda) {
cout << pin[i].readPin() << endl;
cout << "KODA JE PRAVILNA" << endl;
}
else if (i > 100) {
cout << "kode ni v sistemu" << endl;
}
}
}
There are better ways of using global variables than declaring them many times and you may want to research these if you're going to write bigger programs. Also global variables are very useful in certain instances but must not be abused as they can make bigger applications much more difficult to read and maintain.
The Parametri array in your pinPass function is empty(or more precisely , has garbage values).You call the branjeDatoteke function from within pinPass , the
branjeDatoteke function then creates it's own Parametri array (WHICH IS DIFFERENT from the one in your pinPass function),reads the values from the file and displays it via cout.
When branjeDatoteke is done with it's work , all the local variables of that function , inlcuding the Parametri array are destroyed and your program jumps back to the pinPass function.
To do what you're trying to achieve , which is , presumably , have a common array for both the functions, you can either pass the array from pinPass to branjeDatokete , or you can tell branjoDatokete to allocate an array on the heap and then return a pointer to it.I guess the first approach fits better for what you're trying to achieve.

Calling a string getter function from a header file

I'm learning C++, and I'm just messing around with putting classes in separate files for practice. I have a getter function, which returns a string (because the variable is saved as a string). However, from my main() function, I am not sure how to call it. I know the problem is probably that I need to include string somewhere when I call the object, but I have no idea how to format it.
I know this is a pretty newbie questions, but I couldn't find the answer anywhere. Could someone help me out?
(p.s. I'm not trying to get this specific code to work, since it's useless. I'm just trying to learn how to apply it for future reference).
I've tried throwing in string in a couple of places when calling or creating the object, but I always get an error. I know I could get around it by not encapsulating the variable or not having a separate class file, but that's not what I want.
main.cpp
#include <iostream>
#include "usernameclass.h"
#include <string>
using namespace std;
int main()
{
usernameclass usernameobject;
usernameobject.getUsername();
return 0;
}
usernameclass.h
#ifndef USERNAMECLASS_H
#define USERNAMECLASS_H
#include <string>
class usernameclass
{
public:
usernameclass();
std::string getUsername();
void setUsername(std::string name);
askUsername();
private:
std::string usernameVar = "test";
};
#endif
usernameclass.cpp
#include "usernameclass.h"
#include <iostream>
#include "username.h"
#include <string>
using namespace std;
string usernameclass::getUsername(){
return usernameVar;
cout << "test cout" << endl;
}
usernameclass::askUsername(){
string name;
cout << "What is your name?" << endl;
cin >> name;
setUsername(name);
cout << "Ah, so your name is "+usernameVar+", great name I guess!" << endl;
cin.get();
cin.get();
cout << "You're about to do some stuff, so get ready!" << endl;
}
usernameclass::usernameclass(){}
void usernameclass::setUsername(string name){
string* nameptr = &usernameVar;
*nameptr = name;
}
Expected result: runs getUsername() function and returns usernameVar
Actual result: doesn't run the getUsername() function
The current code would not compile, because you have not specified return type of 'askUsername()' routine, which is 'void', I believe.
Other things are good, apart from an output in 'getUsername()', which happens after returning from the function and about which you should have received a warning, I guess.
To the question: you can call that 'get' method in 'main()' as:
cout << usernameobject.getUsername();
Your code should be structured more like this instead:
main.cpp
#include <iostream>
#include "usernameclass.h"
int main()
{
usernameclass usernameobject;
// optional:
// usernameobject.askUsername();
// do something with usernameobject.getUsername() as needed...
return 0;
}
usernameclass.h
#ifndef USERNAMECLASS_H
#define USERNAMECLASS_H
#include <string>
class usernameclass
{
public:
std::string getUsername() const;
void setUsername(std::string name);
void askUsername();
private:
std::string usernameVar = "test";
};
#endif
usernameclass.cpp
#include <iostream>
#include "usernameclass.h"
std::string usernameclass::getUsername() const {
return usernameVar;
}
void usernameclass::setUsername(std::string name) {
usernameVar = name;
}
void usernameclass::askUsername() {
std::string name;
std::cout << "What is your name?" << std::endl;
std::getline(std::cin, std::name);
setUsername(name);
std::cout << "Ah, so your name is " << getUsername() << ", great name I guess!" << std::endl;
std::cout << "You're about to do some stuff, so get ready!" << std::endl;
}

create multiple text files inside a loop

I want to create some text file in C++. For example: I will run a loop from 1 to 5 and create the following files:
1.txt
2.txt
3.txt
4.txt
5.txt
is it possible? I have made a sample code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
main()
{
FILE *fp;
int i;
for(i=1;i<=5;i++)
{
//fp=fopen("%d.txt","r",i); //what will go here??
}
}
I am confused about what I will write inside the loop. how can I create those files?
char i;
char fileName[] = "0.txt";
for(i='1';i<='5';i++)
{
fileName[0]=i;
fp=fopen(fileName,"r"); //what will go here??
//...
}
You can use sprintf if this is too simple for your case;
Since you tag c++, I think fstream string is the thing to use.
A simple c++ example
#include <fstream>
#include <string>
using namespace std;
int main(){
string base(".txt");
for(int i=1;i<=5;++i){
ofstream(to_string(i)+base);// to_string() need c++11
}
}
If you still don't have to_string (you don't have c++11 or your compiler just don't have this) you can use this simple version for now. (better put this in your own namespace)
#include <string>
#include <sstream>
std::string to_string(int i){
std::stringstream s;
s << i;
return s.str();
}
You can use a std::stringstream to compose the file name before passing it to the std::ofstream constructor as a std::string.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
int main()
{
std::cout << "How many files do you want to create? ";
int n;
std::cin >> n;
std::cout << "How many digits do you want to display? ";
int n_digits;
std::cin >> n_digits; // i.e. zeroes == 3 -> 001.txt
std::cout << "Enter a common prefix for all the files: ";
std::string prefix;
std::cin.ignore();
std::getline(std::cin, prefix); // i.e. prefix == "file" -> file001.txt
std::string ext(".txt");
for ( int i = 1; i <= n; ++i )
{ // use a stringstream to create a file names like: prefix001.txt
std::stringstream ss;
ss << prefix << std::setfill('0') << std::setw(n_digits) << i << ext;
// open the file. If not c++11 use ss.str().c_str() instead
std::ofstream file( ss.str() );
if ( !file )
{
std::cerr << "Error: failed to create file " << ss.str() << '\n';
break;
}
// write something to the newly created file
file << "This is file: " << ss.str() << "\n\nHello!\n";
if ( !file )
{
std::cerr << "Error: failed to write to file " << ss.str() << '\n';
break;
}
}
}
#include <iostream>
#include <fstream>
int main(void)
{
std::ofstream out; // you must call out.close() inside loop to be able to open another file for writting otherwise you'll get only the first one "a.txt"
std::string sFileName;
for(char c('a'); c < 'f'; c++)
{
sFileName = c;
sFileName += ".txt";
out.open(sFileName.c_str(), std::ios::out);
// std::ofstream out(sFileName.c_str(), std::ios::out); // here you are not obliged to call out.close() because the first out is not the very second and so on...
out.close(); // very important if you use the same ofstream to open another file
}
std::cout << std::endl;
return 0;
}
*** to be able to use one ostream object in opening many files you must close the precedent file to be able to open the next otherwise it fails trying creating the next one.

Cannot use ifstream in Xcode

I am new to C++ and have researched this everywhere and cannot seem to figure out how to compile this and have not idea why. It works in visual C++ but not Xcode. The error seems to be on the input stream. Any suggestions?
Error reads - "Implicit instantiation of undefined template 'std::_basic_ifstream >'
#include <iostream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "The file is providing the data.";
ifstream myFile("/Users/me/Desktop/somewords.txt"); // * error
int i;
string s;
double d;
myFile >> i >> s >> d;
cout << "here is your data " << endl;
cout << i << endl << s << endl << d << endl;
return 0;
}
You forgot to #include <fstream>, the header file that actually defines all your ifstream goodness. You included <iostream> twice (or at least tried to), perhaps one of those was meant to be <fstream>?

Why is writing a std::string to cout causing an unknown operator << error?

I am getting an error when I try to output the return value from one of my methods:
Error: No operator "<<" matches these operands. Operand types are: std::ostream << std::string
Main.cpp
#include <iostream>
using namespace std;
#include "Book.h"
int main()
{
book.setTitle("Advanced C++ Programming");
book.setAuthorName("Linda", "Smith");
book.setPublisher("Microsoft Press", "One Microsoft Way", "Redmond");
book.setPrice(49.99);
cout << book.getBookInfo(); // <-= this won't compile because of the error above.
int i;
cin >> i;
return 0;
};
Method which should return string:
string Book::getBookInfo()
{
stringstream ss;
ss << title << endl << convertDoubleToString(price) << endl;
return ss.str();
}
#include <string> is missing.
How did the code get the definition of string? The header <string> also declares the stream inserter.