Getting strings with /'s and .'s

Started by
19 comments, last by OneMoreToGo 17 years, 10 months ago
Quote:Original post by wyrzy
btw,

"e" != 'e'

one is a string constant ("e") and the other is a character literal ('e'). One has an ascii value of something like 101 (that's the 'e'), and the other has some 32-bit address (I'm assuming a 32-bit system)



I am not comparing those two. As long as the user supplies "e", all my code will check for "e". 'e' is not involved. I was unaware of the fact that you could not use nested or statements though;

if (whatever == ("a" || "q") -> bad?

Thanks!
Advertisement
Quote:Original post by OneMoreToGo
if (whatever == ("a" || "q") -> bad?


Indeed. This sentence means "if whatever is equal to ("a" || "q")", not "if whatever is equal to "a" or "q"". Since "a" is not NULL and "q" is not NULL, ("a" || "q") is really (!NULL || !NULL) ie (true || true) ie true. So far

whatever == ("a" || "q") ==> whatever == true

To enforce what Zahlman said (he doesn't know it but he is the high priest of my own personnal religion), std::string and other "c++'s strange formats" have been created to help you. The C and C++ languages are hard enough, you don't have to lose your time to try to replicate something that already exists in a well tested, standard library.

And std::string is really the roxors :)
I shall attempt to keep that in mind, however, would it take a lot of adaptation to install the string method? I'll try to use in future code, but for the moment, I'll just convert all my "e" to 'e', a temporary fix for some code which is comparatively useless (when looked at besides c++'s original file i/o streams). Oh well. :)
Quote:Original post by OneMoreToGo
I shall attempt to keep that in mind, however, would it take a lot of adaptation to install the string method? I'll try to use in future code, but for the moment, I'll just convert all my "e" to 'e', a temporary fix for some code which is comparatively useless (when looked at besides c++'s original file i/o streams). Oh well. :)

The time it takes to learn and use std::string and other Standard Library constructs will be much less than the time wasted debugging problems like the ones you are having now.


jfl.
Quote:Original post by OneMoreToGo
I shall attempt to keep that in mind, however, would it take a lot of adaptation to install the string method? I'll try to use in future code, but for the moment, I'll just convert all my "e" to 'e', a temporary fix for some code which is comparatively useless (when looked at besides c++'s original file i/o streams). Oh well. :)



Quote:/Users/gareth/Desktop/flx testing/FLX_Test_IO/flx_fileIO.h:95: error: ISO C++ forbids comparison between pointer and integer


*sigh* Point taken. I'll google it.
Did you miss the part where we explained the logical error? There is no set of types (unless you implemented one yourself, and it would be probably roundly considered a very bad idea even if it actually worked according to spec) you can use such that OR-ing two values, and then comparing for equality to the result, is equivalent to checking whether you have one of the two values.

You don't know what you're doing, and you need to take several steps back and learn things properly. Including the standard library (not just the streams) this time. It's called the standard library for a reason.
Quote:Original post by Zahlman
Did you miss the part where we explained the logical error? There is no set of types (unless you implemented one yourself, and it would be probably roundly considered a very bad idea even if it actually worked according to spec) you can use such that OR-ing two values, and then comparing for equality to the result, is equivalent to checking whether you have one of the two values.

You don't know what you're doing, and you need to take several steps back and learn things properly. Including the standard library (not just the streams) this time. It's called the standard library for a reason.


The error was meant as a bit of humor, as in "You know what? I'm sick of this, I give in. I'll do it your way".

Is that what you were reffering to? The problem I see, is that I have always in the past used double-quotes around my letters that were always in char format. It's the way I was taught. Now a couple of years later, I'm going through SDL learning new things on a basis that appears to be wrong. I have a book on C++, and although it never mentioned the std:: operator (neither did the course I took, I swear! And everything worked too!) it seems fine in all other regards, so I'll go back and review arrays & pointers. I've googled a bit about string operators, and they seem useful. Do they comply with standard sizeof() & strlen() commands? I'll just test that myself though, so no worries.

Thanks for all your help! Hopefully I won't be back with to many bothersome problems for a while. (Yeah right.)
Quote:Original post by OneMoreToGo
I have a book on C++, and although it never mentioned the std:: operator (neither did the course I took, I swear! And everything worked too!) it seems fine in all other regards, so I'll go back and review arrays & pointers. I've googled a bit about string operators, and they seem useful. Do they comply with standard sizeof() & strlen() commands? I'll just test that myself though, so no worries.


To be able to use things correctly, you have to know what they are. Talking vaguely about "operators" and "commands" probably has a lot to do with why you're confused. Also, your C++ book is evidently several years out of date and needs to be thrown away, and most C++ programming courses out there that I've heard about are pretty much garbage as well. Sorry, but that's the state of things.

std:: is a namespace. Namespaces are a way of decorating identifiers (that's a catch-all term that includes variable names, function names and class/struct names - and probably other stuff I forgot) so that instead of using "foo_" prefixes to avoid name collisions, you use "foo::". But it's actually much better than that, because (a) they're a language construct that the compiler can actually do some checking with, and (b) you can set things up such that certain blocks of code omit the "foo::" for convenience, when it is not needed to avoid collisions. For example, suppose you made a "2d vector" class (of the sort that is reinvented a gazillion times by everyone; basically it just represents a pair of X and Y coordinates), and called it 'vector', and wanted to store a std::vector of them. In the code using that vector, you'd have to write "std::vector<vector>", in order to make things clear to the compiler. (Perhaps you would be smart enough to put your vector class in its own namespace, too; then you'd qualify that name as well.) But in some other source file of the same project that *didn't* use the local vector class but still used the standard library vector container, you could get away with "using std::vector;" at the top and "vector<int>" everywhere else.

'std::string' is a class. Thus you can declare variables of type std::string; each of these might be called "a std::string instance" or "a std::string object". It represents textual information. In C++, classes and structs can provide "member functions", as well as operator overloads . When you write "cout << foo;", 'cout' is a global object of type std::ostream, and you are invoking the overloaded operator<<(std::ostream&, T) for T = whatever type 'foo' happens to have. This is the same sort of process as when you write "foo + bar" and it invokes operator+(int, int) (except that there isn't really such a function in a library somewhere; the compiler just directly emits the appropriate machine code) if foo and bar are both ints, or operator+(const std::string&, const std::string&) if foo and bar are both std::strings. Note that the operator+ in question yields another std::string object which represents the concatenation of those two input strings. You can't directly, or even with a relatively small amount of work, do that properly with char*'s.

A single-quoted string in your program, like 'a' or '\n', is a "character literal". That is to say, a single byte value. (Back when all this stuff was designed, "characters" and "bytes" were considered equivalent. Now that we have Unicode, huge monkey wrenches are thrown in to that system.) It's a value that could be assigned to a variable of type char, which is an integral numeric type. When output, the numeric value is translated into a character via the ASCII table.

A double-quoted string in your program is a "string literal". What happens when you write that is that the compiler embeds the contained sequence of characters into the executable's data segment, and puts a zero-valued character ('\0') at the end as well. Then, in an expression using the string literal, that literal becomes a value of type char* (pointer to char), which points at (has a value which is the memory address of) the beginning of that sequence of characters. So a string literal is a completely different thing from a character literal, even if the string happens to be only "one character long" (note that actually two bytes are used in the static storage, because of the aforementioned 'null terminator').

sizeof is an operator. It yields, *at compile-time*, the number of bytes that are needed to represent the provided variable or type, using the *static* type.

Note that a character *array* is different from a character *pointer* - in a few ways. You need to read this. Example:

#include <iostream>using namespace std;int main() {  char foo[16];  char* bar = foo; // that causes bar to point to the beginning of the foo storage  cout << sizeof(foo) << ' '        << sizeof(char[16]) << ' '       << sizeof(bar) << ' '       << sizeof(char*) << endl;}


You *can* use sizeof() on any variable or type, but it is rarely something that a beginning programmer ought to find useful.

strlen() is a function. It accepts a specific argument type (const char*), so that's all you can pass to it. It's intended for figuring out the length of a "string" represented by a char*, in the way that string literals represent things. It does this by checking character values, starting at the provided location and advancing forward through memory, until it finds a zero byte (such as the one automatically inserted at the end of a string literal).

The std::string object does provide a way to extract a const char* representing its internal buffer: its .c_str() member function. This allows you to pass the data to some C APIs. However, you would not want to do it with strlen(), for at least three reasons:

1) It would be terminally retarded to do so, because the std::string object already provides a function that does that directly: its .length() member function.

2) You would lose efficiency: the std::string object already includes a length count, which is only updated when something happens that might change the string length, so all its .length() member does is return the value there. By contrast, calling strlen() requires searching through memory over the entire length of the string - every time you call it, because the information didn't get remembered anywhere.

3) You could get a wrong answer, because std::strings are capable of holding zero bytes within the "real" string data, whereas char* strings basically aren't - if you tried to make a string "hello\0world", then strlen() would stop at the *first* \0 it saw, and report a length of 5, as if all you had was "hello".
Wow... thanks for explaining that in such detail. You might as well have written a book for me. ;)

Well, as much as I'm a cheap guy, it looks like time to get a new reference.

On a completely unrelated note:

Wow, I just tried Code::Blocks IDE. Amazing. I love it. Not only is it free, but it has built in templates for OpenGL, OGRE and SDL (and others). A nice interface, support for multiple compilers... and did I mention it was free? ;)

Once again, Thanks!
Quote:Original post by OneMoreToGo
Wow... thanks for explaining that in such detail. You might as well have written a book for me. ;)

Well, as much as I'm a cheap guy, it looks like time to get a new reference.

On a completely unrelated note:

Wow, I just tried Code::Blocks IDE. Amazing. I love it. Not only is it free, but it has built in templates for OpenGL, OGRE and SDL (and others). A nice interface, support for multiple compilers... and did I mention it was free? ;)

Once again, Thanks!


I really enjoyed Code::Blocks while I used it. It was easy to set up, and had tons of features like a rusimentary intellisense and a decent debugger. I would also look at the Microsoft Visual C++ Express edition. It definately is a bit bett with debugging and such. However, since you already are using Code::Blocks, you might as well stick with it.
Sean Henley [C++ Tutor]Rensselaer Polytechnic Institute

This topic is closed to new replies.

Advertisement