Can you put breaks in a string literal? - c++

This is a constant I am using, it is split like this because I did not want to have to scroll my editor
const string PROGRAM_DESCRIPTION = "Program will calculate the amount "
"accumulated every month you save, until you reach your goal.";
int main()
{
cout << PROGRAM_DESCRIPTION;
return 0;
}
Currently prints out in command prompt as
Program will calculate the amount accumulated every month you save,until you re
ach your goal.
When this prints out I would like it to print on two separate lines like below...
Program will calculate the amount accumulated every month you save,
until you reach your goal.
I do not know where to put break statements in a string so I can get it to print out correctly.

Just insert a \n character to force a new line
const string PROGRAM_DESCRIPTION = "Program will calculate the amount "
"accumulated every month you save, \nuntil you reach your goal.";

You can use \n at the end of the first part of the literal for that, like this:
const string PROGRAM_DESCRIPTION = "Program will calculate the amount\n"
"accumulated every month you save, until you reach your goal."; // ^^
You do not have to split the literal into parts if you do not wish to do so for readability:
const string PROGRAM_DESCRIPTION = "Program will calculate the amount accumulated every month you save,\nuntil you reach your goal.";

In C++11, you can use a raw string literal
const char* stuff =
R"foo(this string
is for real)foo";
std::cout << stuff;
outputs:
this string
is for real
(I put this answer here for pedantic reasons, use \n)

Add \n in the string where you want the line to break.

Just insert a line break "\n" in the position you want in your const string, as you would do in a normal literal string:
const string PROGRAM_DESCRIPTION = "Program will calculate the amount\naccumulated every month you save, until you reach your goal.";
cout << PROGRAM_DESCRIPTION;
Simple. Just the same way as you should me used to in using a literal string:
cout << "Program will calculate the amount\naccumulated every month you save, until you reach your goal.";
Right?

Well answers are good, however my offer is to use \r\n for new line. Read here some more, these two symbols should always work (unless you are using Atari 8-bit OS).
And some more explanation.
\n - Line Feed. This should move printing pointer one line lower, but it may or may not set printing pointer to beginning o line.
\r - Carriage Return. This sets line pointer at the beginning o line, and may or may not change line.
\r\n - CR LF. Moves printing pointer to next line and sets it at the beginning of line.

Related

Find out the average value of inputted integers

I managed to get this program to work. If the user types an unfixed amount of integers, the program will calculate the average value of it. But I need to end it with <Ctrl-D> in my terminal (end of file) in order for it to work. Why can I not just press enter for it to work?
I also believe that I've used an unnecessary amount of variables. Can it be narrowed down to maybe 2 variables?
#include <iomanip>
#include <iostream>
using namespace std;
int main ()
{
int digit {};
int res {};
int counter {};
cout << "Type in integers: ";
while (cin >> digit)
{
counter ++;
res += digit;
}
cout << "The mean was " << setw(1) << setprecision(1) << fixed << static_cast<double>(res) / static_cast<double>(counter) << endl;
return 0;
}
Why can I not just press enter for it to work?
Because that's not how the overloaded >> formatted extraction operator works. This operator skips over an unlimited amount of whitespace characters, including newline characters, until it reads the integer. It's simply how it works: it will read newlines and spaces, after newlines, and spaces, until it sees a digit. That's its mission in life: read and skip over spaces and newlines until it reads at least one digit. It never gets tired of reading newlines and spaces, and will keep going as long that's the case.
To handle input in the fashion you describe requires a completely different approach: using std::getline to read a single line of input into a std::string, up until the next newline character. Then, once that's done, you can check if the std::string is empty, which means that no input was entered, and then terminate; otherwise take the input in std::string and convert it to an int value (using std::stoi, std::from_chars, or a std::istringstream -- take your pick), and then proceed with the existing algorithm.
Can it be narrowed down to maybe 2 variables?
How do you expect to do that? Hard, immutable logic dictates that you must keep track of at least two discrete values: the total sum and the number of values read. But then you just ran out of variables. You have no more variables to use for storing the next read value (if there is one), using whatever approach you chose to use. So, you can't do it. Rules of logic require the use of at least three variables, possibly more depending on how fancy and robust you want your input validation to work.

Does substr change the position where the find function starts searching?

Does substr change the position where the find function starts searching ?
I have a char * named search_text containing the following text:
ABC_NAME = 'XYZSomeone' AND ABC_CLASS = 'XYZSomething'
I want to display the "ABC_NAME" value from that string.
Here is what I am doing:
std::cout << std::string(search_text).substr ( 12, std::string( search_text ).find ("'", 13 )-1) << std::endl;
My logic in the above in the substr is as follows:
The ABC_NAME value always begins at the 12th character, so start the substring there.
Do a find for the character ' (single quotation mark) from the 13th character onwards, starting from the 13th character (the second argument of the find() function). The resulting number will be the outer bound of the substr.
However, my code prints out the following:
XYZSomeone' AND ABC_C
However, when I try to display the value of the find() function directly, I do get the correct number for the location of the second ' (single quotation mark)
std::cout << std::string( search_text ).find ("'", 13 ) << std::endl;
This prints out:
22
So why is it that the substr is not finding the value of 22 as its second argument ?
It's a rather simple matter to evaluate your expression by hand, seeing how you already verified the result of find:
std::string(search_text).substr ( 12, std::string( search_text ).find ("'", 13 )-1)
std::string("ABC_NAME = 'XYZSomeone' AND ABC_CLASS = 'XYZSomething'").substr ( 12, 22-1)
Now check the documentation for substr: "Returns a substring [pos, pos+count)". The character at position 12 is the 'X' for the name portion, and the character at position 12+21 = 33 is the 'L' from the class portion. So we expect the substring starting at that 'X' and going up to just before that 'L', which is "XYZSomeone' AND ABC_C". Check.
(It is understandable to forget whether substr takes a length or a position at which to end. Different languages do disagree on this. Hence the link to the documentation.)
Unsolicited commentary
Trying to do so much in one line makes your code harder to read and harder to debug. In this case, it also hurts performance. There is no need to convert search_text to a std::string twice.
std::string search_string{search_text};
std::size_t found = search_string.find('\'', 12);
if ( found != std::string::npos )
found -= 12;
std::cout << search_string.substr(12, found) << std::endl;
This cuts the number of times a string is constructed (hence the times the string data is copied) from three to two.
If you are using C++17, you can improve the performance even more by constructing no strings. Just use std::string_view instead of std::string. For this scenario, it has the same member functions taking the same parameters; all you have to change is the type of search_string. This puts the performance on par with C code.
Even better: since string views are so cheap to create, you could even write your code – without a performance hit – so that it doesn't matter whether substr takes a length or takes the past-the-end position.
std::string_view search_string{search_text};
std::string_view ltrimmed = search_string.substr(12);
std::size_t found = ltrimmed.find('\'');
std::cout << ltrimmed.substr(0, found) << std::endl;
Constructive laziness FTW!

Why is the length of a string off by one on the first read of a file?

I am perplexed with the way my program is performing. I am looping the following process:
1) take the name of a course from an input file
2) output the length of the name of the course
The problem is that the first value is always one less than the actual value of the string.
My first string contains 13 characters (including the colon), but nameOfClass.length() returns 12. The next string, the character count is 16 and indeed, nameOfClass.length() returns 16.
Every value after that also returns the expected value, it is only the first that returns the expected value minus 1.
Here's the (reduced) code:
std::ifstream inf("courseNames.txt");
int numberOfClasses = 10;
string nameOfClass;
for (int i = 0; i < numberOfClasses; i++) {
std::getline(inf, nameOfClass,':');
std::cout << nameOfClass.length() << "\n";
}
The file looks like this (courseNames.txt):
Pre-Calculus:
Public-Speaking:
English I:
Calculus I:
...etc. (6 more classes)
This is what I get:
12
16
10
11
Can anyone explain this behavior of the .length() function?
You have a problem, but you have the wrong conclusion. std::getline reads but doesn't output the delimiter, and so the first result is indeed 12.
It also doesn't output the delimiter for any subsequent lines, so why is there always one more? Well, look what is after that :. That's right, a new line!
Pre-Calculus:
^ a new line
So your nameOfClass variable, except for the first string, always stores an extra newline before the other characters.
The fix is easy enough, just ignore the newline after reading the string.
inf.ignore(); // ignore one character
So, not the first result was wrong, it was the only one right :)

istream and cin.get()

I have a question about the difference between these two pieces of code:
char buffer5[5];
cin.get(buffer5, 5);
cout << buffer5;
cin.get(buffer5, 5);
cout << buffer5;
and
char buffer4;
while (cin.get(buffer4))
{
cout << buffer4;
}
In the first piece of code, the code gets 5 characters and puts it in buffer5. However, because you press enter, a newline character isn't put into the stream when calling get(), so the program will terminate and will not ask you for another round of 5 characters.
In the second piece of code, cin.get() waits for input to the input stream, so the loop doesn't just terminate (I think). Lets say I input "Apple" into the input stream. This will put 5 characters into the input stream, and the loop will print all characters to the output. However, unlike the first piece of code, it does not stop, even after two inputs as I can continuously keep inputting.
Why is it that I can continuously input character sequences into the terminal in the second piece of code and not the first?
First off, "pressing enter" has no special meaning to the IOStreams beyond entering a newline character (\n) into the input sequence (note, when using text streams the platform specific end of line sequences are transformed into a single newline character). When entering data on a console, the data is normally line buffered by the console and only forwarded to the program when pressing enter (typically this can be turned off but the details of this are platform specific and irrelevant to this question anyway).
With this out of the way lets turn our attention to the behavior of s.get(buffer, n) for an std::istream s and a pointer to an array of at least n characters buffer. The description of what this does is quite trivial: it calls s.get(buffer, n, s.widen('\n')). Since we are talking about std::istream and you probably haven't changed the std::locale we can assume that s.widen('\n') just returns '\n', i.e., the call is equivalent to s.get(buffer, n, '\n') where '\n' is called a delimiter and the question becomes what this function does.
Well, this function extracts up to m = 0 < n? n - 1: 0 characters, stopping when either m is reached or when the next character is identical to the delimiter which is left in the stream (you'd used std::istream::getline() if you'd wanted the delimiter to be extracted). Any extracted character is stored in the corresponding location of buffer and if 0 < n a null character is stored into location buffer[n - 1]. In case, if no character is extracted std::ios_base::failbit is set.
OK, with this we should have all ingredients to the riddle in place: When you entered at least one character but less than 5 characters the first call to get() succeeded and left the newline character as next character in the buffer. The next attempt to get() more characters immediately found the delimiter, stored no character, and indicated failure by setting std::ios_base::failbit. It is easy to verify this theory:
#include <iostream>
int main()
{
char buffer[5];
for (int count(0); std::cin; ++count) {
if (std::cin.get(buffer, 5)) {
std::cout << "get[" << count << "]='" << buffer << "'\n";
}
else {
std::cout << "get[" << count << "] failed\n";
}
}
}
If you enter no character, the first call to std::cin.get() fails. If you enter 1 to 4 characters, the first call succeeds but the second one fails. If you enter more than 4 characters, the second call also succeeds, etc. There are several ways to deal with the potentially stuck newline character:
Just use std::istream::getline() which behaves the same as std::istream::get() but also extracts the delimiter if this is why it stopped reading. This may chop one line into multiple reads, however, which may or may not be desired.
To avoid the limitation of a fixed line length, you could use std::getline() together with an std::string (i.e., std::getline(std::cin, string)).
After a successful get() you could check if the next character is a newline using std::istream::peek() and std::istream::ignore() it when necessary.
Which of these approaches meets your needs depends on what you are trying to achieve.

C++ adding a carriage return at beginning of string when reading file

I have two questions:
1) Why is my code adding a carriage return at the beggining of the selected_line string?
2) Do you think the algorithm I'm using to return a random line from the file is good enough and won't cause any problems?
A sample file is:
line
number one
#
line number two
My code:
int main()
{
srand(time(0));
ifstream read("myfile.dat");
string line;
string selected_line;
int nlines = 0;
while(getline(read, line, '#')) {
if((rand() % ++nlines) == 0)
selected_line = line;
}
// this is adding a \n at the beginning of the string
cout << selected_line << endl;
}
EDIT: OK, what some of you suggested makes a lot of sense. The string is probably being read as "\nmystring". So I guess my question now is, how would i remove the first \n from the string?
What you probably want is something like this:
std::vector<std::string> allParagraphs;
std::string currentParagraph;
while (std::getline(read, line)) {
if (line == "#") { // modify this condition, if needed
// paragraph ended, store to vector
allParagraphs.push_back(currentParagraph);
currentParagraph = "";
else {
// paragraph continues...
if (!currentParagraph.empty()) {
currentParagraph += "\n";
}
currentParagraph += line;
}
}
// store the last paragraph, as well
// (in case it was not terminated by #)
if (!currentParagraph.empty()) {
allParagraphs.push_back(currentParagraph);
}
// this is not extremely random, but will get you started
size_t selectedIndex = rand() % allParagraphs.size();
std::string selectedParagraph = allParagraphs[selectedIndex];
For better randomness, you could opt for this instead:
size_t selectedIndex
= rand() / (double) (RAND_MAX + 1) * allParagraphs.size();
This is because the least significant bits returned by rand() tend to behave not so randomly at all.
Because you don't specify \n as a delimeter.
Your "random" selection is completely wrong. In fact, it will always select the first line:
rand() % 1 is always 0.
There is no way to uniformly select a random line without knowing the number of lines present.
In addition, why are you using # as a delimiter? Getline, by default, gets a line (ending with \n).
The newlines can appear from the second line that you print. This is because, the getline function halts on seeing the # character and resumes the next time it is called from where it left of i.e. a character past the # which as per your input file is a newline. Read the C FAQ 13.16 on effectively using rand().
One suggestion is to read the entire file in one go, store the lines in a vector and then output them as required.
Because # is your delimeter, the \n that exists right after that delimeter will be the beginning of your next line, thus making the \n be in front of your line.
1) You're not adding a \n to selected_line. Instead, by specifying '#' you are simply not removing the extra \n characters in your file. Note that your file actually looks something like this:
line\n
number one\n
#\n
line number two\n
<\pre>
So line number two is actually "\nline number two\n".
2) No. If you want to randomly select a line then you need to determine the number of lines in your file first.
You could use the substr method of the std::string class to remove the \n after you decide which line to use:
if ( line.substr(0,1) == "\n" ) { line = line.substr(1); }
As others have said, if you want to select the lines with uniform randomness, you'll need to read all the lines first and then select a line number. You could also use if (rand() % (++nlines+1)) which will select line 1 with 1/2 probability, line 2 with 1/2*1/3 probability, etc.