So I have a while look that checks every character in a file.
while (infile.get(ch))
The problem is that in the same loop I have to check the next character to check for some validation.
Is there anyway I could move the next character while keeping track of the current one?
Thanks
Use the peek() method so you will be able to look at the next character before extracting it. Here's an example:
std::istringstream iss("ABC");
for (char c; iss.get(c); )
{
std::cout << "Current character is: " << c << std::endl;
if (iss.peek() != EOF)
std::cout << "Next character is: " << (char)iss.peek();
}
This should output:
Current character is: A
Next character is: B
Current character is: B
Next character is: C
Current character is: C
Related
int main()
{
std::string previous = " ";
std::string current;
while (std::cin >> current)
{
if (previous == current)
std::cout << "\n repeated word: " << current;
previous = current;
}
};
The program works, but I don't know why. What exactly is the computer doing here? From what I understand, the computer first reads user input then checks if the word matches with "previous" which is initialized to a space character. Is the computer checking if both string variables are space characters? At what point does previous take on a different value?
In every step of the loop, current is checked against previous, and then previous is assigned to the value of current (in the last statement of the loop). Then another word is read into current, and so on.
In C++, I am trying to take text from a file and count the occurrences of characters, ignoring differences in case. So far, I can do this without ignoring case.
map<char, size_t> char_count;
char character;
while (myfile >> character)
++char_count[character]; // fetch and increment the counter for word
for (const auto &w : char_count) // for each element in the map
// print the results
cout << w.first << " occurs " << w.second
<< ((w.second > 1) ? " times" : " time") << endl;
My solution for this was going to be:
character = tolower(character)
but tolower() will not take a char, only an int. Any ideas? Am I approaching this the wrong way?
that's true, you can use tolower to convert a character to lowercase, i've modified your code, i hope it can help you :
while (myfile >> character)
++char_count[tolower(character)];
Your solution is applicable.
Just use tolower and convert the char to an int.
#include <iostream>
using namespace std;
int main() {
char ch1 = 'A';
char ch2 = 'B';
char ch3 = '\n';
cout << ch1 << '\t' << ch2 << ch3;
cout << 'C' << '\t' << 'D' << '\b' << ch1 << ch3;
//return 0;
system("pause");
}
Output is:
A B
C A
Why is the last letter A and not D?
Everything you cout gets outputted. It's just that a terminal will interpret '\b' as "go back one character". Try redirecting the output to a file and examine it with a (hex)editor to see that all the characters (including '\b') are there.
At a first glance, one might think that terminals print output as-is. That's incorrect, though. Terminals change the way they behave whenever they encounter one of special terminal control sequences or characters. The '\b' (=0x08=backspace) character is one of those. More can be found at http://ascii-table.com/ansi-escape-sequences.php . You can try printing some of those to a terminal and see it change colors, rewrite current lines and so on and so forth. In fact, you can use these special sequences and characters to make complete GUI-like apps in the command-line.
Note however, that not with all programs you can rely on the "redirect to a file" trick to see what terminal control sequences they write to stdout. Many programs detect whether they're writing to a terminal or not and adjust their usage (or lack thereof) of terminal control sequences accordingly.
\b is a backspace, so you move the cursor one position to the left and then you overwrite the D with ch1 which holds an A.
cout << ch1 << '\t' << ch2 << ch3;
prints A, a tab, B and then a newline character.
cout << 'C' << '\t' << 'D' << '\b' << ch1 << ch3;
prints C, a tab, D, then moves the cursor behind D, prints A(This overwrites the character D) and then, prints a newline character.
\b is an escape sequence which represents a backspace. It moves the cursor one step behind.
Others have explained why D is overwritten by A, because \b is the escape sequence for backspace.
I'd like to add that the output might be different on different machines. How \b is actually displayed is up to the implementation of the terminal.
Why is the last letter A and not D?
Because the last visible character you output is A:
cout << 'C' << '\t' << 'D' << '\b' << ch1 << ch3;
ch1 is A, ch3 is a new line. And D is not shown because you erased it with '\b'
What this line cout << 'C' << '\t' << 'D' << '\b' << ch1 << ch3; does is:
Print C,
Make space (tab \t)
Print D
Go back (backspace \b)
Print A where D was (D is now erased)
New line (\n)
Because of \b jumping back and overwriting D
Due to this line in code //'D' << '\b' << ch1 << ,
'D' will print D
'\b' is backspace, so D gets erased
ch1 prints value that is A
before I was doing a very simple programming exercise and I have a problem with the end-of-input character. I wrote this program to check if two words repetead in the text :
string previous = ""; //initalized to "not a word"
string current; //current word
while (cin >> current) { //input operation
if (previous == current) // check if the word is the same as last
cout << "repetead words : " << current << '\n';
previous = current;
}
cout << previous << "\n" << current << "\n";
My book says that if I want to terminate the input operation and to fall out the while loop I must insert the end-of-input character, but, if I insert that character on the same line of my input words I will not fall out the loop.Just if I insert it on a newline it works.Why ? I must insert the end-of-input character on a newline to make it work ?
std::cin::operator>> will return false instead of another reference to std::cin when it reaches end-of-stream. Passing a single eof is a way to signal end-of-stream.
When std::cin parses only an eof, it interprets it specially instead of considering it more data in the stream. If it parses any data in combination with eof, it's just considered data in the stream.
I'm printing a bunch of strings as following:
cout<<count<<"|"<<newTime.time<<"|"<<newCat<<"|"<<newCon<<endl;
in which count is a counter, newTime.time is a string of time, and newCat and newCon are both strings.
The output is like following:
06:02:11:20:08|DB Mgr|Sending query: “SELECT * FROM users”
Apparently, it left out the count and "|". However, if I change the code into
cout<<count<<"|"<<endl;
cout<<newTime.time<<"|"<<newCat<<"|"<<newCon<<endl;
The output just turned into
2|
06:02:11:20:08|DB Mgr|Sending query: “SELECT * FROM users”
I was first thinking if this is the problem of buffer. I changed endl to flush but the problem still exists.
Thanks for any help.
It sounds like your time string may have a carriage return \r in it. If that's the case, then outputting using your first method will still output the count and separator, but the \r will return to the start of the line and begin overwriting it.
Your second method will not overwrite the count since it's on the previous line (a \r will have little visible effect if you're already at the start of the line).
If you're running on a UNIX-like platform, you can pipe the output through something like od -xcb (a hex dump filter) to see if there is a \r in the output.
Alternatively, if you have a string in your code, you can see if it contains a carriage return with something like:
std::string s = "whatever";
size_t pos = s.find ('\r');
if (pos != std::string::npos) {
// carriage return was found.
}
By way of example, the following program:
#include <iostream>
int main (void) {
std::string s1 = "strA";
std::string s2 = "\rstrB";
std::string s3 = "strC";
std::cout << s1 << '|' << s2 << '|' << s3 << '\n';
std::cout << "=====\n";
std::cout << s1 << '|' << '\n';
std::cout << s2 << '|' << s3 << '\n';
std::cout << "=====\n";
size_t pos = s2.find ('\r');
if (pos != std::string::npos)
std::cout << "CR found at " << pos << '\n';
return 0;
}
seems to output the following:
strB|strC
=====
strA|
strB|strC
=====
CR found at 0
but in fact that first line is actually:
strA|(\r)strB|strC
where (\r) is the carriage return.
And keep in mind you rarely need endl - it's effectively a \n with a flush which is not really necessary in most cases. You can just get away with using \n and let the automated flushing take care of itself.