I am printing a line like this
cout<<"Hello //stackoverflow";
And this produces the following output
Hello //stackoverflow
I want to know why it does not give me an error as I commented half of the statement and there should be
missing terminating " character
error.
The grammar of C++ (like most of programming languages) is context-sensitive. Simply, // does not start a comment if it is within a string literal.
For an in depth analysis of this, you'd have to refer to the language grammar, and the string literal production rules in particular.
Informally speaking, the fact that // appears in the quoted string literal means that it does not denote a comment block. The same applies to /* and */.
The converse applies to other constructs, where maximal munch requires parsing into the token denoting the start of a comment block; a space is needed before the pointer dereference operator in
#include <iostream>
using namespace std;
int main() {
int n = 1;
int* p = &n;
cout << 1 / *p; // Removing the final space will fail compilation.
}
In easy terms, This is because everything inside quotes is recognized as a string and so the computer does not evaluate // as the way to start a comment.
Related
I need help with C++ <string.h> char tables.... How to cut word from sentence, using "*" operator, with no strstr? For example: "StackOverFlow is online website". I have to cut off "StackOverFlow" and leave in table "is online website" using operator, with no strstr. I couldn't find it anywhere.
Mostly like:
char t[]
int main
{
strcpy(t,"Stackoverflow is online website");
???
(Setting first char to NULL, then strcat/strcpy rest of sentence into table)
}
Sorry for English problems/Bad naming... I'm starting to learning C++
You can do something like this. Explain better what you need, please.
char szFirstStr[] = "StackOverflow, flowers and vine.";
strcpy(szFirstStr, szFirstStr + 15);
std::cout << szFirstStr << std::endl;
Will output "flowers and vine".
Using c strings is not good style for C++ programmer, use std::string class.
Your code is obviously syntactically incorrect, but I guess you are aware of that.
Your variable t is really a char array and you have a pointer that points to the first character of that char array, like you have a pointer that points to the first character of your null terminated string. What you can do is to change the pointer value to point to the new starting point of your string.
You can either do that, or if you indeed use an array, you can copy from the pointer of the new starting point you wish to use. So if the data you wish to copy resides in memory pointed to by:
const char* str = "Stackoverflow is an online website";
This looks like the following in memory:
Stackoverflow is an online website\0
str points to: --^
If you want to point to a different starting point you can alter the pointer to point at a different starting location:
Stackoverflow is an online website\0
str + 14 points to: --------------^
You can pass the address of the "i" to your strcpy, like so:
strcpy(t, str + 14);
Obviously it is not certain that you know the size to cut off without an analysis (the 14), what you might do is search through the string for the first character following a white space.
// Notice that this is just a sample of a search that could be made
// much more elegant, but I will leave that to you.
const char* FindSecondWord(const char* strToSearch) {
// Loop until the end of the string is reached or the first
// white space character
while (*strToSearch && !isspace(*strToSearch)) strToSearch++;
// Loop until the end of the string is reached or the first
// non white space character is found (our new starting point)
while (*strToSearch && isspace(*strToSearch)) strToSearch++;
return strToSearch;
}
strcpy(t, FindSecondWord("Stackoverflow is an online website"));
cout << t << endl;
This will output: is an online website
Since this is most likely a school assignment, I will skip the lecture on more modern C++ string handling, as I expect this has something to do with learning pointers. But obviously this is very low level modification of a string.
As a beginner why make it harder then it really have to be?
Use std::string
and
substr()
Link
I've just been introduced to toupper, and I'm a little confused by the syntax; it seems like it's repeating itself. What I've been using it for is for every character of a string, it converts the character into an uppercase character if possible.
for (int i = 0; i < string.length(); i++)
{
if (isalpha(string[i]))
{
if (islower(string[i]))
{
string[i] = toupper(string[i]);
}
}
}
Why do you have to list string[i] twice? Shouldn't this work?
toupper(string[i]); (I tried it, so I know it doesn't.)
toupper is a function that takes its argument by value. It could have been defined to take a reference to character and modify it in-place, but that would have made it more awkward to write code that just examines the upper-case variant of a character, as in this example:
// compare chars case-insensitively without modifying anything
if (std::toupper(*s1++) == std::toupper(*s2++))
...
In other words, toupper(c) doesn't change c for the same reasons that sin(x) doesn't change x.
To avoid repeating expressions like string[i] on the left and right side of the assignment, take a reference to a character and use it to read and write to the string:
for (size_t i = 0; i < string.length(); i++) {
char& c = string[i]; // reference to character inside string
c = std::toupper(c);
}
Using range-based for, the above can be written more briefly (and executed more efficiently) as:
for (auto& c: string)
c = std::toupper(c);
As from the documentation, the character is passed by value.
Because of that, the answer is no, it shouldn't.
The prototype of toupper is:
int toupper( int ch );
As you can see, the character is passed by value, transformed and returned by value.
If you don't assign the returned value to a variable, it will be definitely lost.
That's why in your example it is reassigned so that to replace the original one.
As many of the other answers already say, the argument to std::toupper is passed and the result returned by-value which makes sense because otherwise, you wouldn't be able to call, say std::toupper('a'). You cannot modify the literal 'a' in-place. It is also likely that you have your input in a read-only buffer and want to store the uppercase-output in another buffer. So the by-value approach is much more flexible.
What is redundant, on the other hand, is your checking for isalpha and islower. If the character is not a lower-case alphabetic character, toupper will leave it alone anyway so the logic reduces to this.
#include <cctype>
#include <iostream>
int
main()
{
char text[] = "Please send me 400 $ worth of dark chocolate by Wednesday!";
for (auto s = text; *s != '\0'; ++s)
*s = std::toupper(*s);
std::cout << text << '\n';
}
You could further eliminate the raw loop by using an algorithm, if you find this prettier.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <utility>
int
main()
{
char text[] = "Please send me 400 $ worth of dark chocolate by Wednesday!";
std::transform(std::cbegin(text), std::cend(text), std::begin(text),
[](auto c){ return std::toupper(c); });
std::cout << text << '\n';
}
toupper takes an int by value and returns the int value of the char of that uppercase character. Every time a function doesn't take a pointer or reference as a parameter the parameter will be passed by value which means that there is no possible way to see the changes from outside the function because the parameter will actually be a copy of the variable passed to the function, the way you catch the changes is by saving what the function returns. In this case, the character upper-cased.
Note that there is a nasty gotcha in isalpha(), which is the following: the function only works correctly for inputs in the range 0-255 + EOF.
So what, you think.
Well, if your char type happens to be signed, and you pass a value greater than 127, this is considered a negative value, and thus the int passed to isalpha will also be negative (and thus outside the range of 0-255 + EOF).
In Visual Studio, this will crash your application. I have complained about this to Microsoft, on the grounds that a character classification function that is not safe for all inputs is basically pointless, but received an answer stating that this was entirely standards conforming and I should just write better code. Ok, fair enough, but nowhere else in the standard does anyone care about whether char is signed or unsigned. Only in the isxxx functions does it serve as a landmine that could easily make it through testing without anyone noticing.
The following code crashes Visual Studio 2015 (and, as far as I know, all earlier versions):
int x = toupper ('é');
So not only is the isalpha() in your code redundant, it is in fact actively harmful, as it will cause any strings that contain characters with values greater than 127 to crash your application.
See http://en.cppreference.com/w/cpp/string/byte/isalpha: "The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF."
This question already has answers here:
Why allow concatenation of string literals?
(10 answers)
Closed 9 years ago.
#include <iostream>
#include <string>
int main() {
std::string str = "hello " "world" "!";
std::cout << str;
}
The following compiles, runs, and prints:
hello world!
see live
It seems as though the string literals are being concatenated together, but interestingly this can not be done with operator +:
#include <iostream>
#include <string>
int main() {
std::string str = "hello " + "world";
std::cout << str;
}
This will fail to compile.
see live
Why is this behavior in the language? My theory is that it is allows strings to be constructed with multiple #include statements because #include statements are required to be on their own line. Is this behavior simply possible due to the grammar of the language, or is it an exception that was added to help solve a problem?
Adjacent string literals are concatenated we can see this in the draft C++ standard section 2.2 Phases of translation paragraph 6 which says:
Adjacent string literal tokens are concatenated
In your other case, there is no operator+ defined to take two *const char**.
As to why, this comes from C and we can go to the Rationale for International Standard—Programming Languages—C and it says in section 6.4.5 String literals:
A string can be continued across multiple lines by using the backslash–newline line continuation, but this requires that the continuation of the string start in the first position of the next line. To permit more flexible layout, and to solve some preprocessing problems (see §6.10.3), the C89 Committee introduced string literal concatenation. Two string literals in a row are pasted together, with no null character in the middle, to make one combined string literal. This addition to the C language allows a programmer to extend a string literal beyond the end of a physical line without having to use the backslash–newline mechanism and thereby destroying the indentation scheme of the program. An explicit concatenation operator was not introduced because the concatenation is a lexical construct rather than a run-time operation.
without this feature you would have to do this to continue a string literal over multiple lines:
std::string str = "hello \
world\
!";
which is pretty ugly.
Like #erenon said, the compiler will merge multiple string literals into one, which is especially helpful if you want to use multiple lines like so:
cout << "This is a very long string-literal, "
"which for readability in the code "
"is divided over multiple lines.";
However, when you try to concatenate string-literals together using operator+, the compiler will complain because there is no operator+ defined for two char const *'s. The operator is defined for the string class (which is totally different from C-strings), so it is legal to do this:
string str = string("Hello ") + "world";
The compiler concatenates the string literals automatically into a single one.
When the compiler sees "hello " + "world"; is looking for a global + operator which takes two const char* ... And since by default there is none it fails.
The "hello " "world" "!" is resolved by the compiler as a single string. This allows you to have concatenated strings written over multiple lines .
In the first example, the consecutive string literals are concatenated by magic, before compilation has properly started. The compiler sees a single literal, as if you'd written "hello world!".
In the second example, once compilation has begun, the literals become static arrays. You can't apply + to two arrays.
Why is this behavior in the language?
This is a legacy of C, which comes from a time when memory was a precious resource. It allows you to do quite a lot of string manipulation without requiring dynamic memory allocation (as more modern idioms like std::string often do); the price for that is some rather quirky semantics.
I was solving a question my teacher gave me and hit a little snag.
I am supposed to give the output of the following code:(It's written in Turbo C++)
#include<iostream.h>
void main()
{
char *p = "School";
char c;
c=++(*(p++));
cout<<c<<","<<p<<endl;
cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<endl;
}
The output the program gives is:
T,chool
ijool,j,i
I got the part where the pointer itself increments and then increments the value which the pointer points to. But i don't get the part where the string prints out ijool
Can someone help me out?
The program you showed is non-standard and ill-formed (and should not compile).
"Small" problems:
The proper header for input/output streams in C++ is <iostream>, not <iostream.h>
main() returns an int, not a void.
cout and endl cannot be used without a using namespace std; at the beginning of the file, or better: use std::cout and std::endl.
"Core" problems:
char* p = "School"; is a pointer to string litteral. This conversion is valid in C++03 and deprecated in C++11. Aside from that, normally string litterals are read only, and attempts to modify them often result in segfaults (and modifying a string litteral is undefined behvior by the standard). So, you have undefined behavior everytime you use p, because you modify what it points to, which is the string litteral.
More subtle (and the practical explanation): you are modifying p several times in the line std::cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<std::endl;. It is undefined behavior. The order used for the operations on p is not defined, here it seems the compiler starts from the right. You can see sequence points, sequence before/after for a better explanation.
You might be interested with the live code here, which is more like what you seemed to expect from your program.
Let's assume you correct:
the header to <iostream> - there is no iostream.h header
your uses of cout and endl with std::cout and std::endl respectively
the return type of main to int
Okay,
char *p = "School";
The string literal "School" is of type "array of 7 const char." The conversion to char* was deprecated in C++03. In C++11, this is invalid.
c=++(*(p++));
Here we hit undefined behaviour. As I said before, the chars in a string literal are const. You simply can't modify them. The prefix ++ here will attempt to modify the S character in the string literal.
So from this point onwards, there's no use making conjectures about what should happen. You have undefined behaviour. Anything can happen.
Even if the preceding lines were legal, this line is also undefined behavior, which means that you cannot accurately predict what the output will be:
cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<endl;
Notice how it modifies the value of p multiple times on that line (really between sequence points)? That's not allowed. At best you can say "on this compiler with this run-time library and this environment at this moment of execution I observed the following behavior", but because it is undefined behavior you can't count on it to do the same thing every time you run the program, or even if the same code is encountered multiple times within the same run of the program.
There are at least three problems with this code (and maybe more; I'm not a C++ expert).
The first problem is that string constants like should not be modified as they can be placed in read-only parts of the program memory that the OS maps directly to the exe file on disk (the OS may share them between several running instances of that same program for example, or avoid those parts of memory needing to be written to the swap file when RAM is low, as it knows it can get the original from the exe). The example crashes on my compiler, for example. To modify the string you should allocate a modifiable duplicate of the string, such as with strdup.
The second problem is it's using cout and endl from the std namespace without declaring that. You should prefix their accesses with std:: or add a using namespace std; declaration.
The third problem is that the order in which the operations on the second cout line happen is undefined behavior, leading to the apparently mysterious change of the string between the time it was displayed at the end of the first cout line and the next line.
Since this code is not intended to do anything in particular, there are different, valid ways you could fix it. This will probably run:
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
int main()
{
char *string = strdup("School");
char *p = string;
char c;
c=++(*(p++));
cout<<c<<","<<p<<endl;
cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<endl;
free(string);
}
(On my compiler this outputs: T,chool, diool,i,d.)
It still has undefined behavior though. To fix that, rework the second cout line as follows:
cout << p << ",";
cout << ++(*(p--)) << ",";
cout << ++(*(p++)) << endl;
That should give T,chool, chool,d,U (assuming a character set that has A to Z in order).
p++ moves the position of p from "School" to "chool". Before that, since it is p++, not ++p, it increments the value of the char. Now c = "T" from "S"
When you output p, you output the remainder of p, which we identified before as "chool".
Since it is best to learn from trial and error, run this code with a debugger. That is a great tool which will follow you forever. That will help for the second set of cout statements. If you need help with gdb or VS debugger, we can walk through it.
I am a newbie to C++ and learning from the MSDN C++ Beginner's Guide.
While trying the strcat function it works but I get three strange characters at the
beginning.
Here is my code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
char first_name[40],last_name[40],full_name[80],space[1];
space[0] = ' ';
cout << "Enter your first name: ";
gets(first_name);
cout << "Enter your last name: ";
gets(last_name);
strcat(full_name,first_name);
strcat(full_name,space);
strcat(full_name,last_name);
cout << "Your name is: " << full_name;
return 0;
}
And here is the output
Enter your first name: Taher
Enter your last name: Abouzeid
Your name is: Y}#Taher Abouzeid
I wonder why Y}# appear before my name ?
You aren't initializing full_name by setting the first character to '\0' so there are garbage characters in it and when you strcat you are adding your new data after the garbage characters.
The array that you are creating is full of random data. C++ will allocate the space for the data but does not initialize the array with known data. The strcat will attach the data to the end of the string (the first '\0') as the array of characters has not been initialized (and is full of random data) this will not be the first character.
This could be corrected by replacing
char first_name[40],last_name[40],full_name[80],space[1];
with
char first_name[40] = {0};
char last_name[40] = {0};
char full_name[80] = {0};
char space[2] = {0};
the = {0} will set the first element to '\0' which is the string terminator symbol, and c++ will automatically fill all non specified elements with '\0' (provided that at least one element is specified).
The variable full_name isn't being initialized before being appended to.
Change this:
strcat(full_name,first_name);
to this:
strcpy(full_name,first_name);
You can not see any problem in your test, but your space string is also not null-terminated after initializing its only character with ' '.
As others have said, you must initialize the data, but have you ever thought about learning the standard c++ library? It is more intuitive sometimes, and probably more efficient.
With it would be:
string full_name=first_name+" "+last_name;
and you won't have to bother with terminating null characters. For a reference go to cplusplus
Oh and a full working example so you could understand better (from operator+=):
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string name ("John");
string family ("Smith");
name += " K. "; // c-string
name += family; // string
name += '\n'; // character
cout << name;
return 0;
}
The problem is with your space text.
The strcat function requires a C-style string, which is zero or more characters followed by a null, terminating, character. So when allocating arrays for C-style strings, you need to allocate one extra character for the terminating null character.
So, your space array needs to be of length 2, one for the space character and one for the null character.
Since space is constant, you can use a string literal instead of an array:
const char space[] = " ";
Also, since you are a newbie, here are some tips:
1. Declare one variable per line.
This will be easier to modify and change variable types.
2. Either flush std::cout, use std::endl, or include a '\n'.
This will flush the buffers and display any remaining text.
3. Read the C++ language FAQ.
Click here for the C++ language Frequently Asked Questions (FAQ)
4. You can avoid C-style string problems by using std::string
5. Invest in Scott Myers Effective C++ and More Effective C++ books.
Strings are null-terminated in C and C++ (the strcat function is a legacy of C). This means that when you point to a random memory address (new char[] variables point to a stack address with random content that does not get initialized), the compiler will interpret everything up to the first \0 (null) character as a string (and will go beyond the allocated size if you use pointer arithmetic).
This can lead to very obscure bugs, security issues (buffer overflow exploits) and very unreadable and unmaintainable code. Modern compilers have features that can help with the detection of such issues.
Here is a good summary of your options.