I don't understand why I got this error message at line "if (sentToGroup(client_fd, ss) == -1){"
While running the following code:
stringstream ss;
// ss.get();
ss << "test";
if (sentToGroup(client_fd, ss) == -1){
perror("Fail sending to group");
}
I got the error message below, why??
Initializing argument 2 of ‘int sentToGroup(int, std::stringstream)’
The sentToGroup function is as below:
int sentToGroup(int sender_fd, stringstream str){
char buffer[MAX];
stringstream sender;
sender << int(sender_fd) << "> " << str;
int bytes = recv(sender_fd, buffer, sizeof(buffer), 0);
for (int c = printerCnt; c < sizeof(printer); c++){
if (printer[c] != sender_fd){
if (send(printer[c], sender, bytes, 0) == -1){
return -1;
}
}
}
return 0;
}
It's not clear how that message is produced, but stringstream is not copyable. You should pass by reference and copy data out of it, if you do not wish to pass a stringstream but not modify it.
However, you typically should not pass a stringstream at all. If the purpose is to pass a string into the function, use string. If the purpose is to treat it as a stream, use istream & or ostream & or iostream &. You can still pass the same stringstream because of polymorphism.
I'm not really sure what you're doing here, but changing stringstream to iostream & should fix the immediate problem and possible later issues too.
You cannot copy stringstream, try to pass it by reference:
int sentToGroup(int sender_fd, stringstream& str)
Related
I'm taking a basic OOP in C++ class. One of our assignments is to read lines from a file, run them through a function (parseLine()) that converts a string to a string stream, throw exceptions from that parseLine, catch the exceptions in the readFile function and write the lines that threw exceptions to the console. The lines that did not throw exceptions should be added to a struct array.
The problem: The throws are not being thrown, or not being caught.
I have spent hours playing with the formatting trying to figure out why my try catch statement isn't working. I wish I could ask a more specific question, but I believe the answer will be obvious to a more experienced programmer who sees my code
Note: Formatting style is prescribed by the class.
/**********************************************************************
* struct: Record
* fileName
* user
* time
***********************************************************************/
struct Record
{
string file;
string user;
long time;
};
/**********************************************************************
* function: parseLine
* parse line into struct
***********************************************************************/
void parseLine(const string & line, Record & buffer) throw (string)
{
assert(line.length() > 0);
stringstream ss;
ss.str(line);
// stream string to struct
ss >> buffer.file;
if (ss.fail())
{
ss.clear();
throw string(line);
}
ss >> buffer.user;
if (ss.fail())
{
ss.clear();
throw string(line);
}
ss >> buffer.time;
if (ss.fail() || buffer.time < 1,000,000,000 || buffer.time > 10,000,000,000)
{
ss.clear();
throw string(line);
}
}
/**********************************************************************
* function: readFile
* read from the file name provided by the user
***********************************************************************/
int readFile(const string & fileName, Record record[])
{
// declare fstream variable
ifstream fin(fileName.c_str());
// error check
if (fin.fail())
{
cout << "ERROR: Unable to read file "
<< fileName
<< endl;
return 0;
}
// loop through file and store it
Record buffer;
string line;
int size = 0;
while (getline(fin, line) && size < 500)
{
try
{
parseLine(line, buffer);
record[size] = buffer;
}
catch (string text)
{
cout << "Error parsing line: "
<< text
<< endl;
}
size++;
}
// close the file
fin.close();
return size;
}
Question 1 The file being read purposely contains errors (Empty lines, ints in unexpected places, etc), it seems like the ss.fail() is not being triggered, how could that happen?
Question 2 Is my try/catch block written correctly?
Thank you very much for your help!
Your integer literals should not contain commas.
The comma is actually a C++ operator.
I'm kind of new with programming and I have wired problem.
I tried to search and read about it, but without success.
I have main file and one class (on windows)
main:
main()
{
LogOut x();
x.WriteToDelayFile(1.2, 3);
}
LogOut class:
void LogOut::WriteToDelayFile(double simTime, int nodeNum)
{
string fileName = "Delay" + nodeNum;
FILE* pFile = OpenFile(fileName);
fputs ("something\n",pFile);
}
I can't figure it out but when I call to WriteToDelayFile(2, 3) with values, I get garbage values edit: (for example, on debug- nodeNum=321546 instead of nodeNum=3) on the LogOut::WriteToDelayFile(double simTime, int nodeNum) implementation
Why does it happen?
Thanks.
As user657267 pointed out in his comment, you may not concatenate a string literal and an int string fileName = "Delay" + nodeNum;. Here you are getting a pointer into the literal, that may even be out of range:
string s = "hello"+1; // leads to "ello" in s
The probably intended concatenation can be done using a stringstream:
#include <sstream>
#include <assert>
void concat_check()
{
std::stringstream ss;
ss << "hello" << 1;
assert(ss.str() == "hello1");
}
Wolf you are a little bit wrong
string s = "hello"+3;
gives "lo" in s data
and
string si = string("hello")+3;
is incorrect you need to use stringstream instead
std::stringstream ss;
ss << "hello" << 3;
std::string s = ss.str();
Dudi Reuveni how can you tell that nodeNum has wrong data?
I tested the following two code snippets and found that code snippet A was more efficient than code snippet B. Why? str() has copy operations but rdbuf() don't. Is str("") is more expensive than str()?
code snippet A:
ofstream out("foo.txt");
stringstream ss;
for(int i = 0; i < 300000; i++) {
// append long text to ss
out<<ss.str();
ss.seekp(ios_base::beg);
}
out.close();
code snippet B:
ofstream out("foo.txt");
stringstream ss;
for(int i = 0; i < 300000; i++) {
// append long text to ss
out<<ss.rdbuf();
ss.str("");
}
out.close();
Two potential differences can be detected:
out<<ss.str(); copies the data as std::basic_string, where out<<ss.rdbuf(); returns a pointer of type std::basic_streambuf<CharT,Traits>
ss.str(""); replaces the content in the stringstream, where ss.seekp(ios_base::beg); only sets the output position indicator
ps.
ss.str("") and ss.str() are two different operations.
See:
http://en.cppreference.com/w/cpp/io/basic_stringstream/str
Confusingly, ss.str() does not do the same thing as ss.str(""):
ss.str() returns a copy of the underlying string, whereas ss.str(const string&) changes the underlying storage.
Documentation
I would like to translate the following C code to C++.
FILE *fp = NULL;
fp = fopen("./filename", "r");
int i = 0;
fscanf(fp, "%d\n", &i);
uint16_t j = (uint16_t) i;
This is what I came up with this:
ifstream file;
string filename = "./filename";
file.open(filename.c_str(), ios::in);
errno = 0;
if (file.fail()) {
int tmp = errno;
std::cout << file.c_str () << " not found: strerror(" << tmp << "): " << strerror(tmp) );
}
int i = 0;
file >> i >> std::endl;
uint16_t j = (uint16_t) i;
I would like to know whether the syntax is correct or improvable and more importantly whether it's safe against all kinds of inputs.
int read_int(const std::string file_name) {
std::ifstream file(file_name); //the file will close itself on destruction
std::uint16_t i;
//extract type, don't worry about what it is it will either compile or not
if(!(file >> i)) { //Catch failure
//or however you wish to deal with it.
throw std::runtime_error("can't read file");
}
return i;
}
int main() {
try{
std::uint16_t i=read_int("./filepath");
//do with i...
}
catch(const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Note if you do not have C++11 then you will need to use c_str() to open the file, but the string method is prefered.
EDIT: fstream close themselves, there is no need to close it yourself, the functionality is there incase you do have to do that however it is far better to rely on RAII semantics:
http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
RAII dictates that you should open the file on construction and it will close on destructions, this ensures that there isn't any invalid (exclude EOF, file not found...) fstream object preventing bugs. RAII is a fundamental construct in C++ and should be used where ever resources are concerned.
The docs for the fstream destructors is here:
http://en.cppreference.com/w/cpp/io/basic_fstream
destructs the basic_fstream and the associated buffer, closes the file
The exact equivalent would be:
std::ifstream fs( "./filename" );
int i = 0;
fs >> i >> std::ws;
uint16_t j = i;
Whether this is what you really want is another question: the use of a
"\n" in the format string for fscanf suggests (to me, at least) that
you really want to read a single '\n', and not arbitrary white space;
what the "\n" means in fscanf, however, is to skip up to the next
non-whitespace. (In the case of interactive input, this can be a real
problem, since you won't return from your scanf—or my
replacement above—until you've encountered a non-white space
character or end of file. For input from a file, it may not be an
issue.)
When reading line oriented input, the classical solution is to use
std::getline, and then an std::istringstream to parse it.
I'm using a third party code which has its own implementation for std::ostream operator<<, to handle the third party's type.
I'm using stringstream for this output - like:
string ToString(const thrdPartyType& structure)
{
stringstream outputStream;
outputStream<<structure;
return outputStream.str();
}
...
string str = ToString(structure);
...
This structure contains pointer members, which are set to NULL. When using the operator<< and the assignment of str() into a string, I see (via gdb - print str) that there are many leading '\000' characters, then the string data I need.
How can I trim those NULLs in order to get only the real, not empty data?
P.S. The exact code works fine in Windows VC++...
Thank you.
Are you looking for a workoround like this?
string ToString(const thrdPartyType& structure)
{
stringstream outputStream;
outputStream << structure;
stringstream workaround;
while(! outputStream.eof ) {
char t;
outputStream >> t;
if(t != '\0')
workaround << t;
}
return workaround .str();
}
If you have boost available, something like the following will replace all instances of null in a string with another value.
boost::replace_all(str,boost::as_array(""),"NULL");
For example
char buf[10] = "hello";
string str(buf,buf+10);
boost::replace_all(str,boost::as_array(""),"NULL");
cout << str << endl;
Produces the following output
helloNULLNULLNULLNULLNULL