Strange error printing getline() strings in cout - c++

I was trying to test my classes when I encountered a weird problem in the input of test cases.
I tried to simplify the input to see what went wrong so I created the program below.
#include <iostream>
#include <string>
int main()
{
std::string number;
while (std::getline(std::cin, number))
{
std::cout << std::string(number) << " ";
}
}
Basically, I am getting each line of text and storing it in a string variable using getline(). Then I display each string using std::cout and append a single space character.
My input file contains this:
one six
one seven
The expected output should be like this:
one six one seven
But instead, I get this:
one seven
That is a space character followed by the second line of the input. It disregards the first line of input. I know for a fact that each line are being read properly because they were correctly displayed when I replaced the code with this:
std::cout << std::string(number) << std::endl;
This error is quite new to me. What's happening here? Can anybody explain? TIA!

Ok, its clear.
Your input file must be : one six\r\ntwo seven\r\n with normal Windows EOL.
When you read it under cygwin, you get in first read one six\r, only the \n being eaten by getline, and same one seven\r on the second line.
So you write : one six\r one seven\r (with an ending blank). But the \r alone put the curson back in first column of same line and second line erases first.
And normally the problem is not visible if you replace the ending blank by a std::eol that puts the cursor on a new line. The tab (\t) if really a special case : it put the cursor on eighth column exactly where you expect it, but by pure chance. If you invert the two lines it would be more apparent because you would see the remaining of first line at end of second.
You can confirm it by writing the output to a file and editing it.
I could reproduce it under Linux with a Windows EOL. The reason for that is that Cygwin closely mimics Unix-Linux and use Unix EOL convention of only \n.

Related

Why do I need std::endl to reproduce input lines I got with getline()?

I am a newbie learning C++ to read or write from a file. I searched how to read all contents from a file and got the answer I can use a while loop.
string fileName = "data.txt";
string line ;
ifstream myFile ;
myFile.open(fileName);
while(getline(myFile,line)){
cout << line << endl;
}
data.txt has three lines of content and output as below.
Line 1
Line 2
Line 3
but if I remove "endl" and only use cout<<line; in the curly bracket of the while loop, the output change to :
Line 1Line 2Line 3
From my understanding, the while loop was executed 3 times, what's the logic behind it?
endl means "end line" and it does two things:
Move the output cursor to the next line.
Flush the output, in case you're writing to a file this means the file will be updated right away.
By removing endl you are writing all the input lines onto a single output line, because you never told cout to go to the next line.
Your question regards a semantic ambiguity with std::getline(): Should it result be "a line", in which case the result should include the line-ending newline character, or should the result be the contents of a line, in which case the trailing newline should be dropped?
In the C programming language, getline() takes the first approach:
getline() reads an entire line from stream ... The [result] buffer is
null-terminated and includes the newline character, if one was found.
but in C++, the semantics are different: The newline is considered to be a delimiter, and the results of repeated calls to std::getline() is the content without the delimiter. Note that the function actually takes the delimiter in a third parameter, which defaults to '\n', but could be replaced with any other single character. That makes std::getline() more of a tokenizer.

weird visual studio to linux results

I have this project where we have to convert a made up simple coding language given through a txt into a c++ language and currently I am having a problem with checking my work through linux (where it will be tested on). On the other hand Visual Studio where I wrote my code works how it should be.
From what I observed something weird is going on when I am taking each line in the text, separating each word and placing it in a vector. How I do this is by starting with an empty string, looking at each character of the line, and when I see a space or a tab or any kind of character that signifies a separator then I push back that string to a vector then make the string empty again for the next characters. So something line "STR man = bloo" turns into <"STR", "man", "=", "bloo"> and so on.
In visual studio it worked like this, but it seems like in linux.. somehow the second element seems to add a weird character which would be "man ". Its not a space or an empty line and when I tried to look at size with a format std::cout << name << ":" << size << std::endl, it couts not the right format or result.
enter image description here
enter image description here
Looking at visual Studio.
first line: "size" how many elements in that vector.
second line: is a name that I want to check if its already in a vector along with the length of that name
third line: shows all the elements in that vector (which should only show 1 since the size is 1) along with its length as well.
Looking at the linux result
-first line: "size" equals 1. Which is right
second line: the name im checking and its length, which is right
third line: is where the problem occurs. The name is 1 character greater than what it is suppose to be and instead of adding onto whats printed out, it replaces the first 3 letters instead?
fourth line: should not even happen because the size is only 1 and its a basic for loop of (int i = 0; i < size; i++)
Ive tried to use brute force and just pop back the last character of the second element causing my visual studio code to fail the tests but that still fails the conditional of if the name is = to the name in the vector (which should be true) in linux. Whatever character I add on the second element when I cout that value, such as << name << "." << endl; it seems to always go and replaces first letters of that string.
Pls help
Sorry for the delay, the problem was that I was not handling invisible characters such as \r.

When reading from a file in C++, can I just copy the text itself?

Sorry, the wording for the actual question is probably wrong. I have a program that reads in a line from a .txt file and then puts the string into an object to compare it to a string entered by the user. I haven't been able to get it to match, and when I've tried to see what is entered, I don't see much. Maybe there's an invisible character denoting the end of the line? I've tried code like this:
std::cout << "...." << table[row][col]->get() << "...." <<std::endl;
And got
....a
as the result. When reading the file I used std::getline() if that makes a difference.
I didn't find a true fix, although I did see that the length of the read-in string was one int longer than the actual word. I was able to use a substring to cut the end off of the string.

how to get rid of blank line in c++?

I'm trying to fill text document, but when I do - I get first line blank.
My text document, I'm reading from, looks like this:
3
first fr random 5
second 9
third shazam 2
I've tried removing first value and so blank line went away. So it correlates, but I need that value.
// My code
ifstream in("U2.txt");
ofstream out("U2.txt");
int n;
in>>n;
char vardaiStart[n][21];
in.read(vardaiStart[0], 21);
out << vardaiStart[0]<< endl;
output looks like this:
*blank*
first fr random
but what I want is:
first fr random
So, in other projects I won't be using old C since now, but for this project I red that [endline] and ignored it like this: in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Your input file looks like:
3[endline]
first fr random 5[endline]
second 9[endline]
third shazam 2[endline]
Note the [endline] I added: they can be '\n', '\r\n' depending on the system that generated the file.
Your first instruction is:
in >> n;
a formatted input read: you are asking to read an integer from the file, so only characters that can form valid integers will be read.
This means that after that instruction the remaining portion of the file will be:
[endline]
first fr random 5[endline]
second 9[endline]
third shazam 2[endline]
The rest of your code reads raw bytes, so it will read the first [endline] as well (and print it).
As other suggested in the comments, you should not be using variable length arrays as they are not part of any C++ standard (but part of the C one). Try to use the C++ standard library instead.

Is it possible to skip a line in a data file?

I have a data file that I am trying to input and the data is split into sections via a blank line. The data will be read in from a text file.
How do I make my code skip a blank line to read in the next piece of data? I am currently just in the planning stages of my application.
I'm a beginner so I'm not really sure how to go about this.
Can anyone advise a method on how to approach this?
I have just written it out and my code looks like this:
string ship2_id;
char ship2_journey_id[20];
float ship2_l;
int ship2_s;
getline(itinerary_file, ship2_id);
if (ship2_id = ' ')
{
itinerary_file.ignore(numeric_limits<streamsize>::max(), '\n');
}
else
getline(itinerary_file, ship2_id);
cout << ship2_id << endl;
Yes,
stream.ignore(max_number_of_chars_to_be_skipped, '\n');
I usually just use 1ul<<30 or similar for the first parameter, but
this could be a DoS vector if the input is untrusted and slow to skip those chars
the "pedant" value would read std::numeric_limits<std::stream_pos>::max() or similar
I don't what are you using to read the file, but, to search for a blank line, look for two "line breaks" together. Take in account that the "line breaker" character is different for some OS. In Windows, by default, there are two characters that are used together for a line break.