C++ Char - Relational Operators - c++

I have a little problem working on with char in C++ as I have tried comparing 2 texts in an if and there is what I've got:
Input:
if ( "bac" < "ab" ) cout<<"1";
if ( "ab" > "bac" ) cout<<"1";
Output :
11
I don't really understand why it is printing "11", but moreover if I erase the first 'if' it will no longer print anything on the screen. Could you please explain why it has such a behaviour on these IFs?

`if("abc" < "bcd" );
This is equivalent to:
char* a= "abc";
char* b ="bcd";
if( a < b );
a and b are pointers, addresses in memory. So no matter what are in the two strings, they are in different places in memory. That means no matter what the content of the two strings, a will never be equal to b.
When you "abc" you get the memory location of that string. So that is what is meant by, "You are comparing pointers."; C++ is not like other languages where the machine is abstracted away. You are working with the real one's and zero's that the machine uses. And everything lives somewhere in memory.
strcmp is a function that take two pointers then compares the values in the memory location that those pointers refer to.
if( ! strcmp(a,b) )
;//then the two strings are the same

You are comparing pointers, not characters.
If you're using a modern compiler you can do it like this instead:
if ("bac"s < "ab"s) cout << "1";
if ("ab"s > "bac"s) cout << "1";
The s suffix tells the compiler that the string literals are of type std::string.
If your compiler doesn't support that, you can do it the old fashioned way:
if (string("bac") < string("ab")) cout << "1";
if (string("ab") > string("bac")) cout << "1";
Or the ancient C-style way:
if (strcmp("bac, "ab") < 0) cout << "1";
if (strcmp("ab, "bac") > 0) cout << "1";

Related

How does "to_string" work in array of string?

I want to combine the first 4 characters of each line in txt file and compare it with the keyword I have, but
when I combine the characters, I get the sum of these 4 characters' ascii numbers(whatever).
How can I solve this problem. My code is here:
When I debuged, I saw the string search(variable) was 321.
int main() {
ifstream file("sentence.txt");
if (file.is_open()) {
string line;
while (getline(file, line)) {
string search = to_string(line[0] + line[1] + line[2]); // you see what I mean
if ("dog" == search) {
cout << "there is dog";
}
else {
cout << "there is no dog"<<endl;
}
}
}
}
The function std::to_string() is designed to convert a number into a string representation. It is not what you need.
There is no need to create the new string search to check whether the string line starts with the string "dog".
Creating the new string search is inefficient.
Instead, you could write for example
if ( line.compare( 0, 3, "dog" ) == 0 ) {
cout << "there is dog";
}
else {
cout << "there is no dog" << endl;
}
Or, if your compiler supports C++20, you can also write:
if ( line.starts_with( "dog" ) ) {
cout << "there is dog";
}
else {
cout << "there is no dog" << endl;
}
line[0], line[1], and line[2] are chars, not std::strings. char is an integer type, so adding two chars together results in a single integer that is the sum of the two operands. It does not produce a std::string that is the concatenation of the two chars.
To get a substring of a std::string use the substr member function:
std::string search = line.substr(0, 3);
Or, if you actually need to construct a std::string from individual chars, use the constructor that accepts a std::initializer_list<char>:
std::string search{line[0], line[1], line[2]};
A string made from the first characters of line can be obtained via std::substr. In this case I'd actually prefer the constructor that takes two iterators:
std::string first3chars{line.begin(),line.begin()+3};
Take care of lines that are less than 3 characters.
Your code adds the values of three chars. Adding chars via + does not concatenate them, and if it would why call std::to_string on the result? char is an integer type and what you see as 321 is the result of adding the number representations of the first 3 characters in line.
Is there a way for you to cast those chars (which appear to be integer type for some reason) into char type once again. Perhaps that ought to resolve the issue in case the "to_string" concatenates those 3 inputs into one; additionally intelli-sense should do the trick of explaining parameter usage and returning value.
The problem with this code is that when you access an element of a string you get a character which is an ASCII number, when you try to sum two characters you are adding their ASCII codes.
In your specific case, as you want sequential characters, the best solution would probably be to use the substr function (documentation) for strings. Otherwise, you would probably need to convert one of the characters to a string and then “add” the other characters to it.

Confused by a part of a code

There is a part of a code for "making the first letter of each word capitalized" I dont understand.
http://www.cplusplus.com/forum/beginner/117463/
std::string str = x;
str [0] = toupper (str[0]);
std::for_each(str.begin()+1, str.end(), printChars);
std::cout << str;
return 0;
}
Void printChars(char& c)
{
if( (*(&c - sizeof(char))) == " ")
c = toupper(c);
}
I understand it sets the first letter to capital always, and checks for each one in the string after.
But why does he use if((*(&c - sizeof(char))) == " ") and how does the * , & and setting it to blank work in this case?
how does ... work in this case?
It does not work. The program that you show is ill-formed and is not likely to compile.
Void printChars(char& c)
There is no type Void in C++. I suspect that you intended to write void instead.
(some_char_value) == " " // expression simplified by me
You may not compare a character to a string literal.
But why does he use if((*(&c - sizeof(char))) == " ")
He doesn't. He uses if( (*(&c - sizeof(char))) == ' ').
how does the & work in this case?
It is the address-of operator. It is used here to get a temporary pointer to the memory address of c.
how does the * work in this case?
It is the indirection operator. It is used here to get the character at the memory location &c - 1. Which is a character in str right before the character referred to by c.
and setting it to blank work in this case?
He doesn't set anything in the quoted expression. == is the equality comparison operator. He compares the values of the &c - 1 and the character literal ' '.
In english: He tests whether the character before c is space. In other words: He test whether c is the first character of a word.
This code is performing simple pointer arithmetic. The code you are asking about is using the reference operator & to grab the address of the variable c. Then performing subtraction of the size of a char to check if the char before c is a space if so it calls toUpper(). So for example
if the address of c is 100 then &c - sizeof(char) is checking the char at address 99 then the * is used to dereference the variable which allows for the comparison of the variable using == " ".

How to write one line and nested 'if' statement without '?:' (is it possible?)

Is it possible to write a one line if-else statement (i.e. only using one ;) without using the ?: expression? For instance something of the form:
if (p == 1) " " else "\n";
Potential purpose could be:
cout << if (p == 1) " " else "\n";
Just curious if this is possible, don't know if there are any practical applications for this.
Thanks
You're asking "how do I do X, without using any of the tools the language provides to do X". It's silly.
And the answer's no. It's not possible.
This doesn't address the general question, but it does work for the specific example you provided.
std::cout << " \n"[(bool)(p - 1)];
Explanation:
First, a string literal (such as " \n") is an array. As such, it participates in pointer decay, and can be indexed just like any other pointer or array.
Second, an integer can be converted to a bool, and the conversion has the special property that a zero is converted to false, and anything else is converted to true. So when I subtract 1 from p, then convert it to bool, it is false if p is 1, and true otherwise.
Third, a bool can be (implicitly) converted back to an integer. false converts to 0, and true converts to 1. So converting from an int to a bool and back has the result that a 0 stays a 0, and anything else becomes a 1.
So, with those three points taken into consideration, the expression:
" \n"[(bool)(p - 1)]
results in one of these two possibilities:
" \n"[0] // a space (if p == 1)
" \n"[1] // or a newline (if p != 1)
I'd downvote this answer if I could.
You already used the two important words that are key to undestand why what you intend is not possible, but you probably haven't grasped their full meaning: Statement and expression.
The if statement (like all statements) does not yield a value, while the ?: operator is an expression that does yield a value.
Distinguishing between statements and expressions is a fundamental concept that is worth learning (check out the links in this answer and take your time!), not just for C++ but for almost all programming languages.
cout << [=]{ if (p == 1) return " "; else return "\n"; }();
Basically: no, it's not possible to do this:
cout << if (p == 1) " " else "\n";
That is exactly the purpose of ?: operator - it yields value. Some things may not be possible with if-else syntax. Example: conditional initialization. Consider:
if(p == 1)
int value = 1; //local variable!
else
int value = 0; //and so is this one!
//here 'value' is unknown
Above problem could be solved this way:
int value; //default initialization
if(p == 1)
value = 1; //assignment to already initialized variable!
else
value = 0; //and so is this!
But these two are not equal. For some types, it may result in totally different behavior, because initialization is different from assignment. ?: is a solution:
int value == (p == 1) ? 1 : 0; //'value' is initialized with value, that depends on 'p'
Do not try to do things without tools, that were designed to do that things for you.

c++ dynamic allocation initial values

I'm trying to concatenate two strings into a new one (finalString) like this:
finalString = string1 + '&' + string2
Firstly, I allocate the memory for finalString, then i use strcat().
finalString = new char[strlen(string1 ) + strlen(string2) + 2];
cout << finalString << endl;
finalString = strcat(finalString , string1 );
finalString = strcat(finalString , "&");
finalString = strcat(finalString , string2);
cout << finalString << endl;
I'll suppose that string1 is "Mixt" and string2 is "Supermarket".
The output looks like this:
═════════════════řřřř //(which has 21 characters)
═════════════════řřřřMixt&Supermarket
I know that if I use round brackets in "new char" the string will be initialized to 0 and I'll get the desired result, but my question is why does the first output has 21 characters, supposing that I allocated only 17. And even so, why does the final string length exceed the initial allocation size (21 > 17) ?
Thanks in advance!
Two words for you "buffer overrun"
The reason you have 21 characters initially is because there is a '/0' (also called null) character 22 characters away from the memory address that finalString points to. This may or may not be consistent based on what is in your memory.
As for the reason why you have a longer than what you wanted again you wrote outside the initial buffer into random memory. You did not crash because you did not write over something important.
strcat will take the memory address given, find the first '/0' it finds and from that place on it will copy the data from the second memory pointer you provide until the first '/0' it finds there.
What you are doing is VERY DANGEROUS, if you do not hit a /0' before you hit something vital you will cause a crash or at minimum bad behavior.
Undersand in C/C++ a char[] is just a pointer to the initial memory location of the first element. THERE ARE NO SAFEGUARDS! You alone must be careful with that..
if you set the first character of the finalString[0] = 0 then you the logic will work better.
As a different answer, why not use std::string:
std::string a, b, c;
a = "part1";
b = "part2";
c = a + " & " + b;
std::cout << c << '\n';
part1 & part2
Live example: http://ideone.com/pjqz9T
It will make your life easier! You should always look to use stl types with c++.
If you really do need a char * then at the end you can do c.c_str().
Your string is not initialized which leads to undefined behavior. In strcat, string will be appended when it finds the null character.
So, as others already mentioned, either you can do
finalString[0] = 0;
or in place of your first strcat use strcpy. This will copy the first string and put a null character at the end.
why 21 characters?
This is due to undefined behavior. It will keep on printing until it won't find a null or else it will crash as soon as it tries to access any illegal memory.

Loop efficiency - C++

Beginners question, on loop efficiency. I've started programming in C++ (my first language) and have been using 'Principles and Practice Using C++' by Bjarne Stroustrup. I've been making my way through the earlier chapters and have just been introduced to the concept of loops.
The first exercise regarding loops asks of me the following:
The character 'b' is char('a'+1), 'c' is char('a'+2), etc. Use a loop to write out
a table of characters with their corresponding integer values:
a 97, b 98, ..., z 122
Although, I used uppercase, I created the following:
int number = 64; //integer value for # sign, character before A
char letter = number;//converts integer to char value
int i = 0;
while (i<=25){
cout << ++letter << "\t" << ++number << endl;
++i;
}
Should I aim for only having 'i' be present in a loop or is it simply not possible when converting between types? I can't really think of any other way the above can be done apart from having the character value being converted to it's integer counterpart(i.e. opposite of current method) or simply not having the conversion at all and have letter store '#'.
Following on from jk you could even use the letter itself in the loop (letter <= 'z'). I'd also use a for loop but that's just me.
for( char letter = 'a'; letter <= 'z'; ++letter )
std::cout << letter << "\t" << static_cast<int>( letter ) << std::endl;
You should aim for clarity first and you try to micro-optimize instead. You could better rewrite that as a for loop:
const int offsetToA = 65;
const int numberOfCharacters = 26;
for( int i = 0; i < numberOfCharacters; ++i ) {
const int characterValue = i + offsetToA;
cout << static_cast<char>( characterValue ) << characterValue << endl;
}
and you can convert between different types - that's called casting (the static_cast construct in the code above).
That's not a bad way to do it, but you can do it with only one loop variable like this:
char letter = 65;
while(letter <= 65+25){
printf("%c\t%d\n", letter, letter);
++letter;
}
there is nothing particularly inefficient about the way you are doing it but it certainly is possible to just convert between chars and ints (a char is an integer type). this would mean you only need to store 1 counter rather than the 3 (i, letter + number) you curently have
also, for looping from a fixed start to end a 'for' loop is perhaps more idiomatic (though its possible you havent met this yet!)
If you are concerned about the efficiency of your loop, I would urge you to try this:
Get this code compiled and running under an IDE, such as Visual Studio, and set a break point at the beginning. When you get there, switch to the disassembly view (instruction view) and start hitting the F11 (single-step) key, and keep a mental count of how many times you are hitting it.
You will see that it enters the loop, compares i against 25, and then starts doing the code for the cout line. That involves incrementing letter, and then going into the << routine for cout. It does a number of things in there, possibly going deeper into subroutines, etc., and finally comes back out, returning an object. Then it pushes "\t" as an argument and passes it to that object, and goes back in and does all the stuff it did before. Then it takes number, increments it, and passes it to the cout::<< routine that accepts an integer, calls a function to convert it to a string (which involves a loop), then does all the stuff it did before to loop that string into the output buffer and return.
Tired? You're not done yet. The endl has to be output, and when that happens, not only does it put "\n" in the buffer, but it calls the system routine to flush that buffer to the file or console where you are sending the I/O. You probably can't F11 into that, but rest assured it takes lots of cycles and doesn't return until the I/O is done.
By now, your F11-count should be in the vicinity of several thousand, more or less.
Finally, you come out and get to the ++i statement, which takes 1 or 2 instructions, and jumps back to the top of the loop to start the next iteration.
NOW, are you still worried about the efficiency of the loop?
There's an easier way to make this point, and it's just as instructive. Wrap an infinite loop around your entire code so it runs forever. While it's running, hit the "pause" button in the IDE, and look at the call stack. (This is called a "stackshot".) If you do this several times you get a good idea of how it spends time. Here's an example:
NTDLL! 7c90e514()
KERNEL32! 7c81cbfe()
KERNEL32! 7c81cc75()
KERNEL32! 7c81cc89()
MSVCRTD! 1021bed3()
MSVCRTD! 1021bd59()
MSVCRTD! 10218833()
MSVCRTD! 1023a500()
std::_Fputc() line 42 + 18 bytes
std::basic_filebuf<char,std::char_traits<char> >::overflow() line 108 + 25 bytes
std::basic_streambuf<char,std::char_traits<char> >::sputc() line 85 + 94 bytes
std::ostreambuf_iterator<char,std::char_traits<char> >::operator=() line 304 + 24 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Putc() line 633 + 32 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Iput() line 615 + 25 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::do_put() line 481 + 71 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::put() line 444 + 44 bytes
std::basic_ostream<char,std::char_traits<char> >::operator<<() line 115 + 114 bytes
main() line 43 + 96 bytes
mainCRTStartup() line 338 + 17 bytes
I did this a bunch of times, and not ONCE did it stop in the code for the outer i<=25 loop. So optimizing that loop is like someone's great metaphor: "getting a haircut to lose weight".
Since no one else mentioned it: Having a fixed amount of iterations, this is also a candidate for post-condition iteration with do..while.
char letter = 'a';
do {
std::cout << letter << "\t" << static_cast<int>( letter ) << std::endl;
} while ( ++letter <= 'z' );
However, as shown in Patrick's answer the for idiom is often shorter (in number of lines in this case).
You can promote char to int...
//characters and their corresponding integer values
#include"../../std_lib_facilities.h"
int main()
{
char a = 'a';
while(a<='z'){
cout<<a<<'\t'<<a*1<<'\n'; //a*1 => char operand promoted to integer!
++a;
}
cout<<endl;
}
Incrementing three separate variables is probably a little confusing. Here's a possibility:
for (int i = 0; i != 26; ++i)
{
int chr = 'a' + i;
std::cout << static_cast<char>(chr) << ":\t" << chr << std::endl;
}
Note that using a for loop keeps all the logic of setting up, testing and incrementing the loop variable in one place.
At this point, I wouldn't worry about micro-optimizations such as an efficient way to write a small loop like this. What you have allows a for loop to do the job nicely, but if you are more comfortable with while, you should use that. But I am not sure if that is your question.
I don't think you have understood the question properly. You are writing the code, knowing that 'A' is 65. The whole point of the exercise is to print the value of 'A' to 'Z' on your system, without knowing what value they have.
Now, to get an integer value for a character c, you can do: static_cast<int>(c). I believe that is what you're asking.
I haven't written any code because it should be more fun for you to do so.
Question for the experts: In C, I know that 'a'...'z' need not have continuous values (same for 'A'...'Z'). Is the same true for C++? I would think so, but then it seems highly unlikely that Stroustrup's book assumes that.
thanks for the help.. all i wrote down was
int main()
{
char letter = 96;
int number = letter;
int i = 0;
while(i <26)
{
cout <<++letter <<":" <<++numbers <<" ";
++i;
}
works great...and pretty simple to understand now.
I've tried this and worked fine:
char a = 'a';
int i = a; //represent char a as an int
while (a <= 'z') {
cout << a << '\t' << i << '\n';
++a;
++i;
}
Programming Principles and Practice using C++ (2nd Edition) | Bjarne Stroustrup
Chapter 4 - Computation (Try this #3 - Character Loop)
The character 'b' is char('a'+1), 'c' is char('a'+2), etc. Use
a loop to write out a table of characters with their corresponding integer values:
a 97 b 98 . . . z 122
This is how I solved the problem (from 10 years ago :D)
I am a freshmen btw, so I just started reading this book now... just want to input my solution
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while (i < 26) {
cout << char('a' + i) << '\t' << int(97 + i) << '\n';
++i;
}
}
I solved it by analyzing first the problem which is knowing the char value of 'a' which is 97 up to 'z'. According to this ASCII table
https://www.ascii-code.com/#:~:text=ASCII%20printable%20characters%20%28character%20code%2032-127%29%20Codes%2032-127,digits%2C%20punctuation%20marks%2C%20and%20a%20few%20miscellaneous%20symbols.
Now, we have a clearer understanding on how to solve the said problem.