How to pass cin to a function? - c++

I am learning about different stream state flags/functions in C++ such as good(), goodbit, bad(), badbit and so on. While testing with std::cin, I am unable to pass cin as an argument to a function (the compiler shows a lot of errors)
#include <iostream>
#include <sstream>
void print_state (const std::istream& stream) {
std::cout << " good()=" << stream.good();
std::cout << " eof()=" << stream.eof();
std::cout << " fail()=" << stream.fail();
std::cout << " bad()=" << stream.bad();
}
int main() {
std::cin.clear (std::ios::goodbit);
std::cout << "goodbit: " << print_state(std::cin) << std::endl;
std::cin.clear (std::ios::eofbit);
std::cout << "eofbit: " << print_state(std::cin) << std::endl;
std::cin.clear (std::ios::failbit);
std::cout << "failbit: " << print_state(std::cin) << std::endl;
std::cin.clear (std::ios::badbit);
std::cout << "badbit: " << print_state(std::cin) << std::endl;
return 0;
}
Desired output:
goodbit: good()=1 eof()=0 fail()=0 bad()=0
eofbit: good()=0 eof()=1 fail()=0 bad()=0
failbit: good()=0 eof()=0 fail()=1 bad()=0
badbit: good()=0 eof()=0 fail()=1 bad()=1
I know I can call the function directly with cin, such as std::cin.good(), but I want to know how can I pass cin as an argument to a function.
Edit:
I get a LOT of errors during compilation. An example:
F:\cpp_programming\stream_states.cpp: In function 'int main()':
F:\cpp_programming\stream_states.cpp:13:27: error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'void')
std::cout << "goodbit: " << print_state(std::cin) << std::endl;
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~

Since print_state does not return a value, it cannot be used with the insertion operator <<. The simplest way to correct this, is to call print_state on its own.
print_state(std::cin);
The corrected code is given below:
#include <iostream>
#include <sstream>
void print_state (const std::istream& stream) {
std::cout << " good()=" << stream.good();
std::cout << " eof()=" << stream.eof();
std::cout << " fail()=" << stream.fail();
std::cout << " bad()=" << stream.bad();
}
int main() {
std::cin.clear (std::ios::goodbit);
std::cout << "goodbit: "; print_state(std::cin); std::cout << std::endl;
std::cin.clear (std::ios::eofbit);
std::cout << "eofbit: "; print_state(std::cin); std::cout << std::endl;
std::cin.clear (std::ios::failbit);
std::cout << "failbit: "; print_state(std::cin); std::cout<< std::endl;
std::cin.clear (std::ios::badbit);
std::cout << "badbit: "; print_state(std::cin); std::cout << std::endl;
return 0;
}
To answer my own question
cin can be passed to a function as a function argument, such as:
functionName(std::cin);

Related

Invalid use of non-static member function with header files

#define MYSQLPP_MYSQL_HEADERS_BURIED
#include <mysql++/mysql++.h>
#include <iostream>
#include "/home/sulli313/Project4/Film.h"
void Film::showList(){
std::cout << "\n-----------------------------------" << std::endl;
std::cout << " Query Application " << std::endl;
std::cout << "-----------------------------------" << std::endl;
std::cout << " 1 All letter name actors" << std::endl;
std::cout << " 2 First # PG-13 and Above" << std::endl;
std::cout << " 3 All active/inactive users by store" << std::endl;
std::cout << " 4 Actor Movie titles and ids" << std::endl;
std::cout << "-1 Exit" << std::endl;
std::cout << "-----------------------------------" << std::endl;
std::cout << ">> Enter your choice:" << std::endl;
}
void Film::showOne(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
// Create a query
mysqlpp::Query query = myDB.query();
std::cout << "Please enter a Letter A-Z!" << std::endl;
std::string letter;
std::cin >> letter;
///////////////////////////////////Do this part/////////////////////////////////////////////
//if(letter)
query << "SELECT first_name, last_name "
<< "FROM actor "
<< "WHERE first_name "
<< "LIKE '" + letter + "%'";
// << "WHERE code = \"IST\"";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
std::cout << "--First/Last Names of Actors Whos First ";
std::cout << "Name Stars With " + letter + "--\n" << std::endl;
std::cout << std::left << std::setw(12) << "First Name" <<
std::setw(10) << "Last Name" << std::endl;
std::cout << "------------------------" << std::endl;
for (const auto & row : result) {
std::cout << std::left << std::setw(12) << row[0].c_str();
std::cout << std::setw(5) << row[1] << std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
void Film::showTwo(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
//Selecting the second option's query
std::cout << "Please type a limit 1-30!" << std::endl;
std::string limit;
std::cin >> limit;
mysqlpp::Query query = myDB.query();
query << "SELECT title "
<< "FROM film "
<< "WHERE rating = 'PG-13' "
<< "OR rating = 'R' "
<< "OR rating = 'NC-17' "
<< "LIMIT " + limit + " ";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
std::cout << "--First "+ limit +" Titles PG-13 to NC-17--\n" << std::endl;
std::cout << std::left <<std::setw(20)<< "Title" << std::endl;
std::cout << "------------------------------" <<std::endl;
for (const auto & row : result) {
std::cout << std::left << std::setw(20) << row[0].c_str()<< std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
void Film::showThree(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
//bind variable
std::cout << "Please type 1 for active and 0 for inactive!" << std::endl;
std::string active;
std::cin >> active;
if(active != "1" && active != "0"){
std::cout << "Wrong!" << std::endl;
std::cout << "Please type 1 for active and 0 for inactive!" << std::endl;
std::cin >> active;
}
//Selecting the second option's query
mysqlpp::Query query = myDB.query();
query << "SELECT Count(*) "
<< "FROM customer "
<< "WHERE active = '"+ active + "' "
<< "GROUP BY store_id";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
if(active == "1"){
std::cout << "--Count of All Active Users Grouped by Store Id--\n" << std::endl;
std::cout << std::left <<std::setw(20)<< "Active User Ids" << std::endl;
std::cout << "--------------------" <<std::endl;
} else {
std::cout << "--Count of All Inactive Users Grouped by Store Id--\n" << std::endl;
std::cout << std::left <<std::setw(20)<< "Inactive User Ids" << std::endl;
std::cout << "--------------------" <<std::endl;
}
for (const auto & row : result) {
std::cout << std::left << std::setw(20) << row[0].c_str()<< std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
void Film::showFour(){
mysqlpp::Connection myDB("cse278F2022", "localhost", "cse278F2022",
"raspberrySeltzer");
//bind variable
std::cout << "Please type an actor id that is 1-200!" << std::endl;
std::string act_id;
std::cin >> act_id;
//Selecting the second option's query
mysqlpp::Query query = myDB.query();
query << "SELECT film.title, film.film_id, film_actor.actor_id "
<< "FROM film, film_actor "
<< "WHERE film_actor.actor_id = "+ act_id +" "
<< "GROUP BY title "
<< "LIMIT 20";
query.parse();
mysqlpp::StoreQueryResult result = query.store();
std::cout << "Here is your selection!\n" << std::endl;
std::cout << "--First 20 Titles and IDs of Actor Id 25--\n" << std::endl;
std::cout << std::left <<std::setw(22)<< "Title" <<
std::setw(10)<< "Film_id" << std::setw(0)<<"Actor_id" << std::endl;
std::cout << "----------------------------------------" <<std::endl;
for (const auto & row : result) {
std::cout << std::left<<std::setw(22)<< row[0].c_str() << std::setw(10) << row[1] << std::setw(0) << row[2].c_str() << std::endl;
}
std::cout << "\n" << "to continue, press enter..." << std::endl;
showList();
}
#ifndef FILM_H
#define FILM_H
#include <iostream>
#include <string>
class Film {
public:
void showList();
void showOne();
void showTwo();
void showThree();
void showFour();
private:
};
#endif
// Copyright
// Purpose: Project 4
// Date 11/25/2022
// Author: Colton Sullivan
#define MYSQLPP_MYSQL_HEADERS_BURIED
#include <mysql++/mysql++.h>
#include <iostream>
#include "/home/sulli313/Project4/Film.h"
int main() {
int choice;
showList();
std::cin >> choice;
if (choice == -1) {
std::cout << "Bye!" << std::endl;
}
while (choice != -1) {
while ( choice > 4 || choice < -1 || choice == 0 ) {
std::cout << "The wrong choice!!!" << std::endl;
std::cout << "" << std::endl;
std::cout << "to continue, press enter...";
showList();
std::cin >> choice;
}
if ( choice == 1 ) {
showOne();
}
if ( choice == 2 ) {
showTwo;
}
if ( choice == 3 ) {
showThree;
}
if ( choice == 4 ) {
showFour;
}
std::cin >> choice;
if ( choice == -1 ) {
std::cout << "Bye!" << std::endl;
}
}
}
When trying to switch the original program to object oriented programming, I ran into the problem of the error "Invalid use of non-static member function" popping up for the showOne, showTwo, showThree, showFour and showList functions.
If there is a way to access the functions that are created in the Film.cpp/Film.h files and use them in the QueryApp.cpp file to run that as the main, please let me know.
I have tried switching it from Film::showOne, Film::showTwo...etc to showOne(); and Film::showOne(); but either the same Invalid use of non-static member function error will show or it will say that it has not be declared in this scope.
Your showSomething() functions are all member functions of the Film type. In particular, because they are not marked as static, they are non-static member functions. That means they operate on an instance of Film:
class C {
public:
void a(); // <- non-static member function
static void b(); // <- static member function
};
void foo() {
C::b(); // okay, doesn't need an object
C::a(); // not okay, needs an object
C object; // instance of C
object.a(); // okay
object.b(); // also okay
}
Typically you would give your object some state information or it raises the question why you have a non-static member function to begin with. If you don't need state, make them free functions (i.e., functions that are not member functions) or make them static.
In your case, I suppose it would be helpful to create a database connection in your Film's constructor so you can use the database member in all the functions that need a database connection to function.
Something like this:
class Film {
private:
mysqlpp::Connection myDB;
public:
Film() : myDB("x", "localhost", "y", "z") {}
// ...
};

Move semantics in parameter passing

I have following test example:
#include <iostream>
#include <vector>
void foo (std::vector<int> value) {
std::cout << "value "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
void foo2 (std::vector<int>&& rvalure_ref) {
std::cout << "rvalue_ref "
<< &rvalure_ref
<< " "
<< rvalure_ref.data()
<< " "
<< rvalure_ref.size()
<< std::endl;
}
int main() {
std::vector<int> value(5, 0);
std::cout << "init "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
foo(std::move(value));
std::cout << "done "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
The result of the code above is:
init 0x7ffed27c6450 0x56480bc1eeb0 5
value 0x7ffed27c6470 0x56480bc1eeb0 5
done 0x7ffed27c6450 0 0
Looks great:
Now, move to:
#include <iostream>
#include <vector>
void foo (std::vector<int> value) {
std::cout << "value "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
void foo2 (std::vector<int>&& rvalure_ref) {
std::cout << "rvalue_ref "
<< &rvalure_ref
<< " "
<< rvalure_ref.data()
<< " "
<< rvalure_ref.size()
<< std::endl;
}
int main() {
std::vector<int> value(5, 0);
std::cout << "init "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
foo2(std::move(value));
std::cout << "done "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
The result is:
init 0x7ffccc93a5c0 0x56124b3a8eb0 5
rvalue_ref 0x7ffccc93a5c0 0x56124b3a8eb0 5
done 0x7ffccc93a5c0 0x56124b3a8eb0 5
My problem is:
For the 1st case, it is perfectly called by "move semantics", and as you see, the ownership of the vector has been transfered to the function parameter. Finally, at "done", the data is null to verify the the vector at main() no longer owns the vector.
Now to explicitly claim the parameter is "rvalue reference", as case 2. As you see, actually it is like "call by (l)reference".
How can I figure out it?

Using stringstream's ignore

I am trying to use a stringstream as a buffer but I am unable to update the underlying streambuf :
#include <iostream>
#include <sstream>
int main () {
std::stringstream ss(std::ios_base::app|std::ios_base::in|std::ios_base::out); //ostringstream gives the same output
ss << "foo";
std::cout << "position get: " << ss.tellg() << std::endl;
std::cout << "position put: " << ss.tellp() << std::endl;
ss << "b";
std::cout << "position get: " << ss.tellg() << std::endl;
std::cout << "position put: " << ss.tellp() << std::endl;
char c;
ss >> c;
std::cout << "position get: " << ss.tellg() << std::endl;
std::cout << "position put: " << ss.tellp() << std::endl;
ss.ignore(1);
std::cout << "position get: " << ss.tellg() << std::endl;
std::cout << "position put: " << ss.tellp() << std::endl;
std::cout << ss.str() << std::endl;
return 0;
}
yields:
position get: 0
position put: 3
position get: 0
position put: 4
position get: 1
position put: 4
position get: 2
position put: 4
foob
Is it possible to force a reallocation of the streambuf underlying object ? If not, is this reallocation automatic and in which circumstance is it triggered ?
I know I can use ss.str to change the underlying buffer. But it is a pain to use it to manually update the buffer to a substr's version.
Note: I am doing a school project and must compile to c++98, hence, if you have a solution which is comptabible, it would be much appreciated.

Passing std::ofstream object as argument to class method

As previous questions have been answered, the way to pass a std::ofstream object as a function argument seems to be to instead pass a reference: std::ofstream&.
Whilst this solution compiles, the resulting output is not equivalent to creating an std::ofstream object within the method then calling write().
The code below does not give the correct output:
In main.cpp:
std::ofstream file(path + "output.stubs");
stub->writeRaw(file); //stub is a pointer to an object of class Stub
file.close();
In Stub.cpp:
void Stub::writeRaw(std::ofstream& file) {
file.write((char*)this, sizeof(*this));
}
The correct output is given by both changing Stub.cpp to:
void Stub::writeRaw(void) {
std::ofstream file(path + "output.stubs");
file.write((char*)this, sizeof(*this));
file.close();
}
or writing the object to the file in main instead of calling a class method.
Any help on this behaviour would be greatly appreciated!
EDIT
Some context for the class Stub:
Stub.hpp
#pragma once
#include <iostream>
#include <ios>
#include <fstream>
#include "constants.hpp"
#include "DataTypes.hpp"
class Stub {
private:
StubHeader header;
StubIntrinsicCoordinates intrinsic;
StubPayload payload;
public:
Stub(void);
virtual ~Stub(void);
StubHeader getHeader(void);
StubIntrinsicCoordinates getIntrinsicCoordinates(void);
StubPayload getPayload(void);
void setHeader(StubHeader stub_header);
void setIntrinsicCoordinates(StubIntrinsicCoordinates stub_intrinsic);
void setPayload(StubPayload stub_payload);
void print(void);
void writeRaw(std::ofstream& file);
};
And the relevant data types are defined as follows:
struct StubHeader {
uint8_t bx;
uint8_t nonant;
};
struct StubIntrinsicCoordinates {
uint8_t strip;
uint8_t column;
int crossterm;
};
struct StubPayload {
bool valid;
int r;
int z;
int phi;
int8_t alpha;
int8_t bend;
uint8_t layer;
bool barrel;
bool module;
};
EDIT 2
The (toy) code to read the stub is as follows:
std::ifstream r(path + "output.stubs");
Stub s;
r.read((char*)&s, sizeof(s));
s.print();
Only one stub is written to the file as this was a test of functionality. The print function for the Stub class is as follows:
void Stub::print(void) {
std::cout << "----- Header -----" << '\n';
std::cout << "bx: " << std::dec << (int)header.bx << '\n';
std::cout << "nonant: " << std::dec << (int)header.nonant << '\n';
std::cout << "----- Intrinsic Coordinates -----" << '\n';
std::cout << "strip: " << std::dec << (int)intrinsic.strip << '\n';
std::cout << "column: " << std::dec << (int)intrinsic.column << '\n';
std::cout << "crossterm: " << std::dec << (int)intrinsic.crossterm << '\n';
std::cout << "----- Payload -----" << '\n';
std::cout << "valid: " << std::boolalpha << payload.valid << '\n';
std::cout << "r: " << std::dec << (int)payload.r << '\n';
std::cout << "z: " << std::dec << (int)payload.z << '\n';
std::cout << "phi: " << std::dec << (int)payload.phi << '\n';
std::cout << "alpha: " << std::dec << (int)payload.alpha << '\n';
std::cout << "bend: " << std::dec << (int)payload.bend << '\n';
std::cout << "layer: " << std::dec << (int)payload.layer << '\n';
std::cout << "barrel: " << std::boolalpha << payload.barrel << '\n';
std::cout << "module: " << std::boolalpha << payload.module << "\n\n";
}
EDIT 3
For completeness and transparency, please find below the exact code for main.cpp:
int main(int argc, char const *argv[]) {
Geometry g;
g.generateModuleLUTs();
g.generateCorrectionLUTs();
std::vector<std::array<Stub*, PAYLOAD_WIDTH> > all_stubs;
std::vector<Module> modules = g.getData();
for (int i = 0; i < LINK_NUMBER; i++) {
LinkGenerator link_gen;
LinkFormatter link_formatter(link_gen.run());
StubFormatter stub_formatter(link_formatter.run(), i);
std::array<Stub*, PAYLOAD_WIDTH> stubs = stub_formatter.run(modules);
CoordinateCorrector coordinate_corrector(stubs);
all_stubs.push_back(coordinate_corrector.run());
}
std::ofstream f(path + "output.stubs");
all_stubs[0][0]->writeRaw(f);
all_stubs[0][0]->print();
std::ifstream r(path + "output.stubs");
Stub s;
r.read((char*)&s, sizeof(s));
s.print();
return 0;
}
The bug in the code was that I was not calling file.close() before constructing the std::ifstream object to read the file again. This was the cause of the unexpected behaviour.
Writing a class to file using this seems to be valid, although it is important that you are careful and know exactly what you want to write to a file.
Thank you to everyone who commented and helped to answer this question!

What's the Difference Between floor and duration_cast?

So in c++11 the Chrono Library provides, duration_cast:
Computations are done in the widest type available and converted, as if by static_cast, to the result type only when finished
And c++17's floor:
Returns the greatest duration t representable in ToDuration that is less or equal to d
So for all x will the result of these 2 calls be equal:
chrono::duration_cast<chrono::seconds>(x)
chrono::floor<chrono::seconds>(x)
As far as I can tell, same as the difference between static_cast and std::floor: Negatives are rounded down instead of truncated toward zero.
#include <iostream>
#include <chrono>
using namespace std::chrono_literals;
int main() {
std::cout << "duration_cast:" << std::endl;
std::cout << "1.4s: " << std::chrono::duration_cast<std::chrono::seconds>(1400ms).count() << std::endl;
std::cout << "1.5s: " << std::chrono::duration_cast<std::chrono::seconds>(1500ms).count() << std::endl;
std::cout << "1.6s: " << std::chrono::duration_cast<std::chrono::seconds>(1600ms).count() << std::endl;
std::cout << "-1.4s: " << std::chrono::duration_cast<std::chrono::seconds>(-1400ms).count() << std::endl;
std::cout << "-1.5s: " << std::chrono::duration_cast<std::chrono::seconds>(-1500ms).count() << std::endl;
std::cout << "-1.6s: " << std::chrono::duration_cast<std::chrono::seconds>(-1600ms).count() << std::endl;
std::cout << "floor:" << std::endl;
std::cout << "1.4s: " << std::chrono::floor<std::chrono::seconds>(1400ms).count() << std::endl;
std::cout << "1.5s: " << std::chrono::floor<std::chrono::seconds>(1500ms).count() << std::endl;
std::cout << "1.6s: " << std::chrono::floor<std::chrono::seconds>(1600ms).count() << std::endl;
std::cout << "-1.4s: " << std::chrono::floor<std::chrono::seconds>(-1400ms).count() << std::endl;
std::cout << "-1.5s: " << std::chrono::floor<std::chrono::seconds>(-1500ms).count() << std::endl;
std::cout << "-1.6s: " << std::chrono::floor<std::chrono::seconds>(-1600ms).count() << std::endl;
return 0;
}
.
duration_cast:
1.4s: 1
1.5s: 1
1.6s: 1
-1.4s: -1
-1.5s: -1
-1.6s: -1
floor:
1.4s: 1
1.5s: 1
1.6s: 1
-1.4s: -2
-1.5s: -2
-1.6s: -2
https://wandbox.org/permlink/SsmpRz6RkvbL6Sru