I am having trouble understanding the output of my very little program which should read characters from a text file until it finds a new line.
It correctly outputs the characters and stops, but I don't understand why it still outputs the newline ('\n) character in the terminal and doesn't end before getting to it.
I know that I could use getline() or find another way but I would really understand the reason behind this behaviour.
Thank you in advance!
Edo
Code:
int main() {
std::ifstream in_file;
in_file.open("../responses.txt");
char c;
while(c != '\n'){
in_file.get(c);
std::cout << c << std::endl;
}
return 0;
}
Output:
A
B
C
D
E
Time elapsed: 000:00:000
The
Related
I'm writing a little Domain Specific Language for my program, using JUCE::JavascriptEngine as the scripting engine. This takes a string as input and then parses it, but I need to do some pre-processing on the string to adapt it from my DSL to JavaScript. The pre-processing mainly consists of wrapping some terms inside functions, and placing object names in front of functions. So, for instance, I want to do something like this:
take some special string input "~/1/2"...
wrap it inside a function: "find("~/1/2")"...
and then attach an object to it: "someObject.find("~/1/2")" (the object name has to be a variable).
I've been using regex for this (now I have two problems...). The regexes are getting complicated and unreadable, and it's missing a lot of special cases. Since what I'm doing is grammatical, I thought I'd upgrade from regex to a proper parser (now I have three problems...). After quite a lot of research, I chose Boost.Spirit. I've been going through the documentation, but it's not taking me in the right direction. Can someone suggest how I might use this library to manipulate strings in the way I am looking for? Given that I am only trying to manipulate a string and am not interested in storing the parsed data, do I need to use karma for the output, or can I output the string with qi or x3, during the parsing process?
If I'm headed down the wrong path here, please feel free to re-direct me.
This seems too broad to answer.
What you're doing is parsing input, and transforming it to something else. What you're not doing is find/replace (otherwise you'd be fine using regular expressions).
Of course you can do what regular expressions do, but I'm not sure it buys you anything:
template <typename It, typename Out>
Out preprocess(It f, It l, Out out) {
namespace qi = boost::spirit::qi;
using boost::spirit::repository::qi::seek;
auto passthrough = [&out](boost::iterator_range<It> ignored, auto&&...) {
for (auto ch : ignored) *out++ = ch;
};
auto transform = [&out](std::string const& literal, auto&&...) {
for (auto ch : "someObject.find(\"~"s) *out++ = ch;
for (auto ch : literal) *out++ = ch;
for (auto ch : "\")"s) *out++ = ch;
};
auto pattern = qi::copy("\"~" >> (*~qi::char_('"')) >> '"');
qi::rule<It> ignore = qi::raw[+(!pattern >> qi::char_)] [passthrough];
qi::parse(f, l, -qi::as_string[pattern][transform] % ignore);
return out;
}
The nice thing about this way of writing it, is that it will work with any source iterator:
for (std::string const input : {
R"(function foo(a, b) { var path = "~/1/2"; })",
})
{
std::cout << "Input: " << input << "\n";
std::string result;
preprocess(begin(input), end(input), back_inserter(result));
std::cout << "Result: " << result << "\n";
}
std::cout << "\n -- Or directly transformed stdin to stdout:\n";
preprocess(
boost::spirit::istream_iterator(std::cin >> std::noskipws), {},
std::ostreambuf_iterator<char>(std::cout));
See it Live On Coliru, printing the output:
Input: function foo(a, b) { var path = "~/1/2"; }
Result: function foo(a, b) { var path = someObject.find("~/1/2"); }
-- Or directly transformed stdin to stdout:
function bar(c, d) { var path = someObject.find("~/1/42"); }
But this is very limited since it will not even do the right thing if such things are parts of comments or multiline strings etc.
So instead you probably want a dedicated library that knows how to parse javascript and use it to do your transformation, such as (one of the first hits when googling tooling library preprocess javascript transform): https://clojurescript.org/reference/javascript-library-preprocessing
1.i am trying to check whether the cin.get() leaves the end line character in stream and considered it for next input.
i have tried this code in code blocks but unable to provide input for next string,i am attaching code i have tried and the output .could anyone please explain.
#include<iostream>
using namespace std;
int main()
{
char s1[10];
char s2[10];
cout << "enter the first string: ";
cin.get(s1, 10);
cout << "enter the second string: ";
cin.getline(s2, 10);
cout << s1 << " " << s2;
return 0;
}
enter the first string: hello
enter the second string: hello
please explain the output
This get function reference says that your overload is
Same as get(s, count, widen('\n'))
And that overload of the function reads until (among other things)
the next available input character c equals delim, as determined by Traits::eq(c, delim). This character is not extracted (unlike basic_istream::getline())
[Emphasis mine]
So the newline is left in the input buffer, for the getline call to read as an "empty" line.
If you want to read lines, I suggest you use std::string and std::getline (which does read, and throw away, the newline).
cin.get() grabs the newline character by default. It will not leave the newline in the stream.
I wrote the following simple C++ structure implementation to see the usage of pointer to structure.
#include <iostream>
struct Employee
{
std::string name;
std::string sex;
int e_id;
}emp[2];
void printEmployee(struct Employee *e)
{
std::cout << e->name << std::endl;
std::cout << e->sex << std::endl;
std::cout << e->e_id << std::endl;
}
int main(int argc, char const *argv[])
{
struct Employee *e_ptr;
e_ptr = emp;
for (int i = 0; i < 2; ++i)
{
std::getline(std::cin, emp[i].name);
std::getline(std::cin, emp[i].sex);
std::cin >> emp[i].e_id;
}
for (int i = 0; i < 2; ++i)
{
printEmployee(e_ptr+i);
std::cout << std::endl;
}
return 0;
}
The inputs are
John Smith
male
123
Sarah Collin
female
After these input the program shows the output although the code is supposed to take one more input. The output is
John Smith
male
123
Sarah Collin
0
But If I don't include int e_id as a member then the code works perfectly.
This is from mixing getline and cin. Getline reads in the input until it hits a (generally) newline '\n'. It takes everything up to the newline, and throws away the newline.
cin reads until you hit white space (like, say, a newline), but doesn't throw it out of the stream. So, you type in 123 ENTER, meaning you have 123\n in the stream. Cin takes the 123 but leaves the \n.
Now you go back to the getline for employee name and immediately it sees the \n in the stream, which means it's done, and it throws it away. Out of curiosity, does it work if you type 123 SPACE instead of enter?
So what's actually happening is John Smith is good, male is good, 123 is good, but then the second employee's name is skipped, you typed Sarah Collin in for what was technically gender, then typed female for what was supposed to be e_id. Since female isn't an integer, what happens? Cin, by default, enters an error state and skips futher cin operations (you can also configure it to throw an exception). So really you actually never enter anything for the second e_id, and the 0 that you see is what it happened to be when it was created (you never initialized it, so it could actually be ANY value! Reading an uninitialized value is undefined behavior. Your compiler may help you out by setting ints to 0 for you, but that's not a kindness you can count on).
Here's someone else with your problem, and an example of how to use
cin.ignore();
to work around this. You need to manually ignore that newline character.
When and why do I need to use cin.ignore() in C++?
While reading integer std::cin stops when it encounters a character other than [+][-][0-9]. That is, std::cin stops at a character which cannot be included in a valid representation of an integer.
In the third line of input there are 4 characters are 123\n.
While reading std::string, std::getline stops reading characters when it encounters \n or delim characters. Also, std::getline does not store \n or delim characters in the string which is reads.
So, std::cin reads the integer emp[0].e_id as expected and stops at \n. After this std::getline reads \n and stops and stores nothing in emp[1].name
I am working on a portion of my code that is suppose to output the error message correctly.
Please see below screenshot, I am using on bash
./myProgram < input3a.in | diff -a -y output3a.out -
Left hand side is what I want to get to.
For some reason an extra "|" is printed before the char array 'line' is printed. I suspected that maybe the char array 'line' is not null terminated. but it is initialize by cin.getline(); which should null terminate the char array.
Here i try to print the 'line' array in my main procedure, and it left the | sign on the line before it.
my question is. why does std::cout display this behaviour?
Thanks
EDIT,
Below is my code in question. Thanks for taking a look again.
#include "char_stack.h"
#include <iostream>
void printErrorLine(int errorSpot, int c_count, char line[]){
//Print the first line of error message char by char, at the
//same time replace char with \t or space
for(int x = 0; x <= errorSpot; x++){
std::cout << line[x];
if(line[x] != '\t'){
line[x] = ' ';
}
}
std::cout << std::endl;
//Print out the second line, if the first line does not have a
//errorSpot, then dont print it
if(errorSpot != c_count){
std::cout << line << std::endl;
}
}
char findCounterPart(char bracket){
//pass.
}
int main(int argc, char * argv[]){
char line[250]; // 250 because spec sheet detailed max 250 char per line.
char c;
int l_count = 0; // number of lines already read
int c_count; // character count in a line
char_stack S;
bool isError;
while(!std::cin.peek() == std::cin.eof()){
std::cin.getline(line, 250);
c_count = std::cin.gcount();
l_count +=1;
//std::cout<< c_count << std::endl << std::endl;
//loop through the line
for(int x = 0; x < c_count; x++){
c = line[x];
//std::cout << c << " stack size is " << S.size() << std::endl;
if (c == '(' ||
c == '{' ||
c == '['){
S.push(c);
}
else if(c == ')' ||
c == '}' ||
c == ']'){
if(S.empty()){
std::cout << "Error on line " << l_count << ": Too many " << c << std::endl;
isError = true;
}
else{
char l = S.pop();
if(l != findCounterPart(c)){
std::cout << "Error on line " << l_count << ": Read " << c <<
", expected " << findCounterPart(l) << std::endl;
isError = true;
}
}
}
if (isError){
printErrorLine(x, c_count ,line);
return 0;
}
}
}
if (!S.empty()){
c = S.pop();
std::cout << "Error on line " << l_count << ": Too many " << c << std::endl;
printErrorLine(c_count, c_count , line);
}
else{
std::cout <<"No Errors Found" << std::endl;
}
return 0;
}
Learning to be a software engineer is about breaking problems down into manageable chunks, and here we have a couple of doosies. Lets rephrase your question slightly:
I am getting unexpected characters displayed when diff the output of my program against a file containing output of a previous run. Currently I think this is because of some weird behavior of std::cout.
Well, that might be a reasonable assumption, we can't see your code so we can't know if you're doing anything peculiar.
But it would have to be: std::cout is used, well, all over the place. It just doesn't have this behavior unless your code is deliberately writing a | somewhere.
There are a number of steps we could take to resolve this:
Run the program a 3rd time in the debugger and step through until you have some ideas where the '|' is appearing,
Run the program a 3rd time to the console and observe the output,
View the output using a command like cat, less or more, instead of diff
3 is perhaps the most sensible place to start, since the file is already right there and after that #2 will give us a mk1eyeball check.
What we find is: the | does not appear in the file or the output. It's not coming from your program.
Lets create a couple of .txt files and diff them:
osmith#WOTSIT MINGW64 ~
$ echo -e 'First line\nSecond line' >test1.txt
osmith#WOTSIT MINGW64 ~
$ echo -e 'First line\nFile two line 2' >test2.txt
osmith#WOTSIT MINGW64 ~
$ diff -a -y test1.txt test2.txt
First line First line
Second line | File two line 2
When using the -y switch, between the two columns of output, diff has a line of special characters to indicate lines that changed, were inserted or deleted.
Ok, I'm a rookie at this and here is what I've been sitting here for a while scratching my head doing.
My goal is to read in a file from a command line argument and store the contents of the file in an array strings of which each element is a line from the file. I need the whole line including white spaces. And I need to cycle through the whole text file without knowing how large/small it is.
I'm fairly sure that key.eof() here is not right, but I've tried so many things now that I need to ask for help because I feel like I'm getting further and further from the solution.
ifstream key(argv[2]);
if (!key) // if file doesn't exist, EXIT
{
cout << "Could not open the key file!\n";
return EXIT_FAILURE;
}
else
{
vector<string> lines;
for (unsigned i = 0; i != key.eof(); ++i)
{
getline(key, lines[i]);
}
for (auto x : lines)
cout << x;
If anyone could point me in the right direction, this is just the begging of what I have to do and if feel clueless. The goal is for me to be able to break down each line into a vector(or whatever I need) of chars INCLUDING white spaces.
I think you want something like this:
vector<string> lines;
string line;
while(getline(key, line)) // keep going until eof or error
lines.push_back(line); // add line to lines
To continuous read lines from file and keep it in array, I would do something like this using a while loop instead of a for loop.
int counter = 0;
while (getline(key, lines[counter]) {
counter++;
}