ofstream does not print out newline to txt in Windows7 - c++

I have some issue when I want to print out \n I'm using endl for that. And the problem is when I run the code on Windows7 it won't print out the newline. But it will print out newline in Ubuntu. Both OS is using the same compiler GNU g++.
So I wonder if there are some different way to print newline to file in Windows?
void translate(ofstream &out, const string &line, map<string, string> m)
{
stringstream ss(line);
string word;
while(ss >> word)
{
if(m[word].size() == 0)
out << "A";
else
out << m[word] << " ";
}
out << "\n";
}

Outputting either '\n' or using endl will result in the exact same content (the only difference is endl also flushes). When that \n character is written, if the file is in "text mode", the runtime library converts it to the platform's native mechanism to indicate lines. On unix, this is unnecessary because that mechanism is a \n byte. On Windows, that \n becomes \r\n (carriage return, line feed). I suspect you know all of this, but I'm reviewing it just in case.
In short, as long as your runtime library is setup for Windows, the code you have will work as you expect. I suspect you are using cygwin's g++, or some other g++ port, that is not setup for Windows-style lines, even in text mode. Some editors will not correctly interpret that untranslated \n.

Related

ofstream not generating new lines in Windows subsystem for Linux

I'm trying to write a .dat file using Windows subsystem for Linux, but the fstream library seems to bypass every endline command.
Here is my code:
int main()
{
string fname = "DataSheet.dat";
ofstream fdata (fname.c_str(), ios::out);
fdata << "First line" << endl;
fdata << "Second line" << endl;
fdata.close();
return = 0;
}
I tried substituting << endl with << "\n" and modifying the ofstream command like showed there, but nothing worked; the output was always First lineSecond line instead of First line and Second line on subsequent lines.
Besides, the code works perfectly well when I print the output to video using cout command or when I compile and run it on cygwin.
Is it a problem of Windows subsystem for Linux or am I missing something important?
By a comment.
Try substituting << endl with \r\n
This is due to the differences in the line endings of linux and windows.
In windows you need to add a carriage return and then the new line character.
While in linux there is not need for the carriage return.
The problem comes from the fact that you are compiling for linux so std::endl places the linux version line ending but you are trying to view the output in windows.

Newline character treated differently between Visual Studio compiler and g++

I'm writing a C++ program that parses XML into JSON for a class and it works great when I compile in Visual Studio but behaves strangely when compiled with g++ in Linux.
With a bit of testing, I believe I have tracked the issue down into a difference in the way new lines are handled between the different compilers, here's some of the code I'm using to debug:
while (!fileToRead.eof()) { //Until we have reached the end of the file: ...
cout << endl << "newloop: ";
char c;
fileToRead.get(c);
cout << "read " << c << " ";
if (c != '\n' && c != '\t')
cout << "is a text character.";
}
When I run an executable created in Visual Studio, it outputs the following for new line characters it reads:
newloop: read
newloop: read
newloop: read
newloop: read
When I run it on Linux when compiled with g++, it outputs the following for new line characters it reads:
is a text character.
newloop: read
is a text character.
newloop: read
is a text character.
newloop: read
newloop: read
As you can see, when compiled with g++ there are 2 problems:
The third cout ("is a text character.") runs before the first and seconds couts ('"endl << << "newloop: "' and '"read " << c << "')
The if statement ("if (c != '\n' && c != '\t')") runs even when c is a new line character.
Can anyone explain what's going on here?
You are not parsing the same XML file. Even if it looks the same in a text editor.
My guess is, the one on windows contains CRLF newlines (\r\n or 0x0D 0x0A), the other only contains LF (\n or 0x0A) newlines.
Make sure you have the exact same file on either system, and you'll get the same results.

Comparing strings from a text file

I am parsing a text file, and for some reason string::compare() isn't working as intended.
The text file: http://pastebin.com/raw.php?i=WZDWmb56
The read function (called from inside while loop):
string StopName = "***";
bool Person::ReadOnePersonFromFile(ifstream& fin)
{
getline(fin,m_name);
cout << m_name << endl;
if( m_name == StopName )
return false;
fin >> m_id;
fin.ignore(50,'\n');
return true;
}
Whenever "***" is reached, if( m_name == StopName ) doesn't return true. What is going on?
This function works on Windows (Visual Studio). I am currently compiling this on Linux. Does this have anything to do with how the text is stored?
It looks like you're comparing StopName rather than Stop in your code, so "***" isn't ever checked (assuming that Stop and StopName aren't the same thing).
Found my answer. I believe this is because of the way newline characters are encoded on Windows.
Windows: \r\n (CR + LF)
Linux: \n
Mac: \r
I had to convert my Windows text file to a Unix text file with dos2unix. The program works fine.

Read File line by line using C++

I am trying to read a file line by line using the code below :
void main()
{
cout << "b";
getGrades("C:\Users\TOUCHMATE\Documents\VS projects\GradeSystem\input.txt");
}
void getGrades(string file){
string buf;
string line;
ifstream in(file);
if (in.fail())
{
cout << "Input file error !!!\n";
return;
}
while(getline(in, line))
{
cout << "read : " << buf << "\n";
}
}
For some reason it keeps returning "input file error!!!". I have tried to full path and relative path (by just using the name of the file as its located in the same folder as the project). what am I doing wrong?
You did not escape the string. Try to change with:
getGrades("C:\\Users\\TOUCHMATE\\Documents\\VS projects\\GradeSystem\\input.txt");
otherwise all the \something are misinterpreted.
As Felice said the '\' is an escape. Thus you need two.
Or you can use the '/' character.
As windows has accepted this as a directory separator for a decade or more now.
getGrades("C:/Users/TOUCHMATE/Documents/VS projects/GradeSystem/input.txt");
This has the advantage that it looks much neater.
first, if you wanna say '\' in a string, you should put '\\', that's the path issue.
then, the string buf is not in connect to your file..
The backslash in C strings is used for escape sequences (e.g. \n is newline, \r carriage return, \t is a tabulation, ...), thus your string is getting garbled because for each backslash+character sequence the compiler is replacing the corresponding escape sequence. To enter backslashes in a C string you have to escape them, using \\:
getGrades("C:\\Users\\TOUCHMATE\\Documents\\VS projects\\GradeSystem\\input.txt");
By the way, it's int main, not void main, and you should return an exit code (usually 0 if everything went fine).

C++ - string.compare issues when output to text file is different to console output?

I'm trying to find out if two strings I have are the same, for the purpose of unit testing. The first is a predefined string, hard-coded into the program. The second is a read in from a text file with an ifstream using std::getline(), and then taken as a substring. Both values are stored as C++ strings.
When I output both of the strings to the console using cout for testing, they both appear to be identical:
ThisIsATestStringOutputtedToAFile
ThisIsATestStringOutputtedToAFile
However, the string.compare returns stating they are not equal. When outputting to a text file, the two strings appear as follows:
ThisIsATestStringOutputtedToAFile
T^#h^#i^#s^#I^#s^#A^#T^#e^#s^#t^#S^#t^#r^#i^#n^#g^#O^#u^#t^#p^#u^#t^#
t^#e^#d^#T^#o^#A^#F^#i^#l^#e
I'm guessing this is some kind of encoding problem, and if I was in my native language (good old C#), I wouldn't have too many problems. As it is I'm with C/C++ and Vi, and frankly don't really know where to go from here! I've tried looking at maybe converting to/from ansi/unicode, and also removing the odd characters, but I'm not even sure if they really exist or not..
Thanks in advance for any suggestions.
EDIT
Apologies, this is my first time posting here. The code below is how I'm going through the process:
ifstream myInput;
ofstream myOutput;
myInput.open(fileLocation.c_str());
myOutput.open("test.txt");
TEST_ASSERT(myInput.is_open() == 1);
string compare1 = "ThisIsATestStringOutputtedToAFile";
string fileBuffer;
std::getline(myInput, fileBuffer);
string compare2 = fileBuffer.substr(400,100);
cout << compare1 + "\n";
cout << compare2 + "\n";
myOutput << compare1 + "\n";
myOutput << compare2 + "\n";
cin.get();
myInput.close();
myOutput.close();
TEST_ASSERT(compare1.compare(compare2) == 0);
How did you create the content of myInput? I would guess that this file is created in two-byte encoding. You can use hex-dump to verify this theory, or use a different editor to create this file.
The simpliest way would be to launch cmd.exe and type
echo "ThisIsATestStringOutputtedToAFile" > test.txt
UPDATE:
If you cannot change the encoding of the myInput file, you can try to use wide-chars in your program. I.e. use wstring instead of string, wifstream instead of ifstream, wofstream, wcout, etc.
The following works for me and writes the text pasted below into the file. Note the '\0' character embedded into the string.
#include <iostream>
#include <fstream>
#include <sstream>
int main()
{
std::istringstream myInput("0123456789ThisIsATestStringOutputtedToAFile\x0 12ou 9 21 3r8f8 reohb jfbhv jshdbv coerbgf vibdfjchbv jdfhbv jdfhbvg jhbdfejh vbfjdsb vjdfvb jfvfdhjs jfhbsd jkefhsv gjhvbdfsjh jdsfhb vjhdfbs vjhdsfg kbhjsadlj bckslASB VBAK VKLFB VLHBFDSL VHBDFSLHVGFDJSHBVG LFS1BDV LH1BJDFLV HBDSH VBLDFSHB VGLDFKHB KAPBLKFBSV LFHBV YBlkjb dflkvb sfvbsljbv sldb fvlfs1hbd vljkh1ykcvb skdfbv nkldsbf vsgdb lkjhbsgd lkdcfb vlkbsdc xlkvbxkclbklxcbv");
std::ofstream myOutput("test.txt");
//std::ostringstream myOutput;
std::string str1 = "ThisIsATestStringOutputtedToAFile";
std::string fileBuffer;
std::getline(myInput, fileBuffer);
std::string str2 = fileBuffer.substr(10,100);
std::cout << str1 + "\n";
std::cout << str2 + "\n";
myOutput << str1 + "\n";
myOutput << str2 + "\n";
std::cout << str1.compare(str2) << '\n';
//std::cout << myOutput.str() << '\n';
return 0;
}
Output:
ThisIsATestStringOutputtedToAFile
ThisIsATestStringOutputtedToAFile
It turns out that the problem was that the file encoding of myInput was UTF-16, whereas the comparison string was UTF-8. The way to convert them with the OS limitations I had for this project (Linux, C/C++ code), was to use the iconv() functions. To keep the compatibility of the C++ strings I'd been using, I ended up saving the string to a new text file, then running iconv through the system() command.
system("iconv -f UTF-16 -t UTF-8 subStr.txt -o convertedSubStr.txt");
Reading the outputted string back in then gave me the string in the format I needed for the comparison to work properly.
NOTE
I'm aware that this is not the most efficient way to do this. I've I'd had the luxury of a Windows environment and the windows.h libraries, things would have been a lot easier. In this case though, the code was in some rarely used unit tests, and as such didn't need to be highly optimized, hence the creation, destruction and I/O operations of some text files wasn't an issue.