I am currently writing a infix to postfix converter. It works pretty well except I have problems adding the rest of the Stack to the postfix. The stack is a
vector<char>
and the postfix is a String. After I'm done reading everything I try the following:
while (!stack.empty()) {
postfix.push_back(stack.back());
stack.pop_back();
}
But there is nothing appended. I even tried it with Debug-mode and it seems fine, but nothing gets appended.
std::cout << postfix.c_str();
Leaves out the last operator from the stack. I even tried to save it temporary, but it does not get pushed.
I can not post all four files in pastebin because of the limit. I use Visual Studio 2010 Ultimate and there are no errors, just no character appended.
The way you're printing out that string is needlessly complicated - and possibly wrong. If you replace
std::cout << postfix.c_str();
with
std::cout << postfix;
You will then see what's really in the string, even if it contains embedded null characters.
Since you are using '\0' as an error indicator but not checking for it you are likely to have embedded nulls. And by using c_str() you are explicitly asking for the string to be truncated at the first null.
Related
When writing single characters to an output stream, the purist in me wants to use single quotes (e.g.):
unsigned int age{40};
std::ostringstream oss;
oss << "In 2022, I am " << age << '\n'; // 1. Single quotes around \n
oss << "In 2023, I will be " << age + 1u << "\n"; // 2. Minor ick--double quotes around \n
Because I'm writing a single character and not an arbitrary-length message, it doesn't seem necessary to have to provide a null-terminated string literal.
So I decided to measure the difference in speed. Naively, I'd expect option 1, the single-character version, to be faster (only one char, no need to handle \0). However, my test with Clang 13 on quick-bench indicates that option 2 is a hair faster. Is there an obvious reason for this?
https://quick-bench.com/q/3Zcp62Yfw_LMbh608cwHeCc0Nd4
Of course, if the program is spending a lot of time writing data to a stream anyway, chances are the program needs to be rethought. But I'd like to have a reasonably correct mental model, and because the opposite happened wrt what I expected, my model needs to be revised.
As you can see in the assembly and in the libc++ source here, both << operations in the end call the same function __put_character_sequence which the compiler decided to not inline in either case.
So, in the end you are passing a pointer to the single char object anyway and if there is a pointer indirection overhead it applies equally to both cases.
__put_character_sequence also takes the length of the string as argument, which the compiler can easily evaluate at compile-time for "\n" as well. So there is no benefit there any way either.
In the end it probably comes down to the compiler having to store the single character on the stack since without inlining it can't tell whether __put_character_sequence will modify it. (The string literal cannot be modified by the function and also would have the same identity between iterations of the loop.)
If the standard library used a different approach or the compiler did inline slightly differently, the result could easily be the other way around.
Today I tried to put together a simple OpenGL shader class, one that loads text from a file, does a little bit of parsing to build a pair of vertex and fragment shaders according to some (pretty sweet) custom syntax (for example, writing ".varying [type] [name];" would allow you to define a varying variable in both shaders while only writing it once, same with ".version",) then compiles an OpenGL shader program using the two, then marks the shader class as 'ready' if and only if the shader code compiled correctly.
Now, I did all this, but then encountered the most bizarre (and frankly kinda scary) problems. I set everything up, declared a new 'tt::Shader' with some file containing valid shader code, only to have it tell me that the shader was invalid but then give me an empty string when I asked what the error was (which means OpenGL gave me an empty string as that's where it gets it from.)
I tried again, this time with obviously invalid shader code, and while it identified that the shader was invalid, it still gave me nothing in terms of what the error was, just an empty string (from which I assumed that obviously the error identification portion of it was also just the same as before.)
Confused, I re-wrote both shaders, the valid and invalid one, by hand as a string, compiling the classes again with the string directly, with no file access. Doing this, the error vanished, the first one compiled correctly, and the second one failed but correctly identified what the error was.
Even more confused, I started comparing the strings from the files to those I wrote myself. Turns out the former were a tad longer than the ladder, despite printing the same. After doing a bit of counting, I realised that these characters must be Windows CR LF line ending carriage characters that got cut off in the importing process.
To test this, I took the hand-written strings, inserted carriages where they would be cut off, and ran my string comparison tests again. This time, it evaluated there lengths to be the same, but also told me that the two where still not equal, which was quite puzzling.
So, I wrote a simple for-loop to iterate through the characters of the two strings and print then each next to one another, and cast to integers so I could see their index values. I ran the program, looked through the (quite lengthy) list, and came to a vary insightful though even less clarifying answer: The hidden characters were in the right places, but they weren't carriages ... they were null-terminators!
Here's the code for the file reading function I'm using. It's nothing fancy, just standard library stuff.
// Attempts to read the file with the given path, returning a string of its contents.
// If the file could not be found and read, an empty string will be returned.
// File strings are build by reading the file line-by-line and assembling a single with new lines placed between them.
// Given this line-by-line method, take note that it will copy no more than 4096 bytes from a single line before moving on.
inline std::string fileRead(const std::string& path) {
if (!tt::fileExists(path))
return "";
std::ifstream a;
a.open(path);
std::string r;
const tt::uint32 _LIMIT = 4096;
char r0[_LIMIT];
tt::uint32 i = 0;
while (a.good()) {
a.getline(r0, _LIMIT);
if (i > 0)
r += "\n";
i++;
r += std::string(r0, static_cast<tt::uint32>(a.gcount()));
}
// TODO: Ask StackOverflow why on earth our file reading function is placing null characters where excess carriages should go.
for (tt::uint32 i = 0; i < r.length(); i++)
if (r[i] == '\0')
r[i] = '\r';
a.close();
tt::printL("Reading file '" + path + "' ...");
return r;
}
If y'all could take a read and tell me what the hell is going on with it, that'd be awesome, as I'm at a total loss for what its doing to my string to cause this.
Lastly, I do get why the null-terminators didn't show up to me but did for OpenGL, the ladder was using C-strings, while I was just doing everything with std::string objects, where store things based on length given that they're pretty much just fancy std::vector objects.
Read the documentation for std::string constructor. Constructor std::string(const char*, size_t n) creates string of size n regardless of input. It may contain null character inside or even more than 1. Note that size of std::string doesn't include the null character (so that str[str.size()] == '\0' always).
So clearly the code simply copies the null character from the output buffer of the getline function.
Why would it do that? Go to gcount() function documentation - it returns the number of extracted characters by the last operation. I.e., it includes the extracted character \n which is replaced in output by \0 voila. Exactly one number more that the constructor ask for.
So to fix it simply do replace:
r += std::string(r0, static_cast<tt::uint32>(a.gcount()-1));
Or you could've simply used getline() with std::string as input instead of a buffer - and none of this would've happened.
std::istream & Date::read(std::istream & istr)
{
char* buffer = nullptr;
const bool ISTREAM_IS_OKAY = !(istr.fail());//okay if it didn't fail
if (ISTREAM_IS_OKAY)
{
cout << "Enter a string: ";
const int SIZE = 256;
buffer = new char[SIZE];
istr.getline(buffer, SIZE);
cout << "\n" << buffer << " " << strlen(buffer) << endl;
istr.getline(buffer, SIZE, '/');
cout << "\n" << buffer << " " << strlen(buffer) << endl;
istr.getline(buffer, SIZE, '/');
cout << "\n" << buffer << " " << strlen(buffer) << endl;
}
else
{//CIN_FAILED is a pre-processor directive which is equal to 1
m_readErrorCode = CIN_FAILED; //m_readErrorCode is just an int
}
delete[] buffer;
return istr;
}
I am trying to read in a date in one string using cin.getline(). Dependent upon whether the boolean member variable m_dateOnly is true or false, the date is to be printed in one of the following two fashions:
1) if(m_dateOnly==true)....
2017/3/18
2) else...print the date and time
2017/3/18 , 12:36
I'm aware that the logic in my code does not entirely dictate what I just explained(It's still a WIP). I came to a halt because when I enter the following:
"abcd" ... no delimiter here
cin.getline() continues to run until the user enters a string with the given delimiter in it.
How can I get cin.getline() to stop on the first instance of an invalid string as opposed to it continuously running?
Note: I am required to use the istream passed as an argument
Thanks in advance!
Basically you can't, because getline will not stop until it encounters the terminator it expects, the buffer gets full or the input ends.
At any rate, you can't pass it a list of 2 characters or more (the expected terminator and/or some illegal characters) it should stop on.
If you really want your code to react on a character per character basis, you will need to use character by character input, with methods like sgetc or sbumpc.
I would not advise to do so, because that would force you to handle all the pesky edge cases like your input buffer getting full of the input being terminated, which getline can handle without headache.
You could also use the >> operator to grab bits of characters or numbers according to whatever format is expected for your date and time. Trouble is, that would force you to check the state of your input stream after each >> invokation, making for ponderous and nigh unreadable code.
Another possibility is to use scanf like functions, but they have the slight downside of including an undefined behaviour on numeric inputs, meaning typing a large number of digits when it expects a number could theoretically lead to a program crash, a random memory corruption or your mustache turning pink.
Yet another possibility is to piss a couple dozen lines of code to create your own homemade list of separators through the imbue method and a custom ctype object. I would not touch that with a 10 feet pole, but I'm sure a lot of senior developpers pull that trick to impress the chicks...
Now if you ask me, C++ string I/O is an appallingly awkward leftover from the 90's: no regular expressions, no garbage collection, no associative memory, so you will end up checking the characters you just read, monitoring the state of your I/O stream and allocating bits of buffers every second line of code. You're bound to suffer one way or another. I would just not make it more painful than it has to be, if I were you.
The usual way of circumventing the crappy C++ I/O is to read a plain line (terminated by a good old \n, usually what you get when you hit the enter key), and then analyze the resulting string buffer by hand. Once you're done with reading an actual input, you don't have to worry about buffers overflowing or input terminating at an awkward moment. That usually makes things a lot less messy.
btw. my personal preference goes to never having to call delete on a null pointer. You can do it, but that makes for pretty dangerous code that tends to break if you modify it one time too many. It could arguably save you a few minutes of coding, but might also cost you (or one of your infortunate coworkers) a few hours of debugging a few weeks/months later.
If your buffer is only used within a code block, better make it a local variable that will be cleaned up automatically. Use dynamic allocation only when you really need it.
No doubt a lot of C++ zealots will be eager to explain the contrary, but this bit of wisdom comes from long nights spent munching pizzas in front of buggy code, often written by people who were just a bit too smart for their own good (and the good of their coworkers, incidentally). Make what you want of it, it comes free of charge.
some simple code has begun failing in an sdk I've been working with, also it apparently has been working correctly for a long time, and indeed I'm almost positive I have compiled parts of the code like this and they have worked, but recently have failed.
example with values confirmed in debugger:
void SomeFunction(CString& paramstring) //let's pretend we pass a string with the value "hello"
{
int size=paramstring.GetLength(); //size now contains an incorrect shorter value like 4
CString localstring=paramstring;//localstring contains something like "hell" or "hel"
}
any ideas why this might be happening
ive tried your code in a console application and it works perfectly the problem comes from another part of your code here is the the code try it out (use MFC )
#include <iostream>
#include <afx.h>
using namespace std;
//let's pretend we pass a string with the value "hello"
void fun(CString& paramstring)
{
int size=paramstring.GetLength();
cout<<"size= "<<size<<"\n";
CString localstring=paramstring;
wcout<<"string = "<<(LPCTSTR)localstring<<"\n";
}
int main()
{
CString s ("Hello");
fun(s);
}
output:
size = 5 string = Hello
My only guess is you have a memory overwrite corrupting that object.
Time to bring out the power tools. Install either Purify or Boundschecker and hunt your bug down.
I have made a mistake in CString code in the past which stopped CStrings working correctly when passed as parameters. Your problem might be completely different, but I will explain here what I did to cause the problem, as it might help someone.
My CString contained a directory name. In order to clean it up a little, I checked if the last character was '\', and if so I replaced it with '\0' by directly overwriting the character inside the CString.
That probably somehow destroyed the integrity of the CString by creating a mismatch between the length of the string as measured by things like strlen(), and the actual size of the buffer. My explanation of the problem might be not be correct, but it basically boiled down to me corrupting the integrity of the CString, I assume.
I fixed my problem by replacing my statement with something like
dirname=dirname.Left(dirname.GetLength()-1);
I am writing this from memory and don't use the functions often, so forgive me if I have remembered a function name incorreclty. Anyway, my recommendation is not to write null characters into the middle of a CString to shorten it, and to look for that (among other things) if a problem occurs with CStrings as parameters.
Ah yes, I think the problem might be the reverse of yours. If you shorten a string by overwriting a character then maybe GetLength() will return the old value, which is larger than than you might expect.
My actual problem was that dir + "\" + filename was not working. I suppose it was concatentating strings containing a null and that the final value was just the directory part, as that is where the null had been added.
It took me a while to figure out why some cout output seem to disappear into the ether. The culprit:
std::cout<< "This line shows up just fine" << std::endl;
const char* some_string = a_function_that_returns_null();
if (some_string == 0)
std::cout<< "Let's check the value of some_string: " << some_string << std::endl;
std::cout<< "This line and any cout output afterwards will not show up" << std::endl;
The output from the snippet above will be:
This line shows up just fine
Let's check the value of some_string:
So feeding a NULL into cout will disable all output afterward. Why? And how to fix it?
This doesn't happen all the time - a co-worker with the same code gets all the expected output. And in case you wonder why I can't just prevent feeding NULL into cout with a if statement: I'm working in a large codebase, and don't know where else this happens! All I know is the cout statements I put never showed up.
More info:
a_function_that_returns_null() is actually getenv("HOST"). I checked on the commandline via echo $HOST that the HOST variable is empty. If I do export HOST= (bash flavor), the output are all there. I have no idea what the HOST variable contains initially nor what getenv returns initially when before I modify the HOST variable; all I know is (some_string == 0) is true.
const char* some_string = a_function_that_returns_null();
Do you mean that it literally returns a null pointer?
[2003: 27.6.2.5.4]:
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, const char* s);
3. Requires: s is non-null.
Then streaming some_string is Undefined Behaviour; you cannot dereference a pointer to get a string — even an empty one — if the pointer is not valid.
This doesn't happen all the time - a co-worker with the same code gets all the expected output
UB leads to unreliable symptoms. That you don't always get a crash can be slightly surprising because most modern OSs make a point of always SIGSEGVing when you try to dereference a null pointer.
However, from a C++ point of view, anything can happen; in your particular case, your standard library implementation may well be checking for a null pointer and setting an error flag on the stream instead of attempting to dereference the pointer. That is its prerogative.
(It's also probably why your subsequent stream operations are failing: attempting to write to a stream does nothing when there's an error flag set.)
For example, the libstdc++ that ships with GCC 4.6.0, despite naming s != 0 as a precondition, does do this:
00325 if (!__s)
00326 __out.setstate(ios_base::badbit);
00327 else
However, you must not rely on this behaviour; it could change at any time!
So, simply don't do this. Stream a valid, but empty, string if you really must.
And what's wrong with std::string?
I'm fairly sure that cout << (char*)NULL has undefined behavior. I'm afraid that "Don't do that" is the best advice I can offer.
When you are trying to output const char*, the stream prints all the bytes until it reaches '\0'. It is leading to undefined behavior. For example, you could print some control symbols (i.e. '\n','\r' and so on) and get unpredictable result.
EDIT: Actually streaming of NULL pointer is enough to get UB. I'm not going to delete my answer due to useful comments.