Vectors in C++ are behaving differently in Windows and Ubuntu - c++

I have to compare two strings which are stored in a vector. Comparison works fine in Windows which uses mingw-g++ compiler(version 4.4.1).
But when I try to do the same in Ubuntu which is running g++ version 4.7.2 I am getting weird problems. I listed them below:
When I try to print the elements individually, they are giving correct output and both strings are same.
But when I try to compare them using == operator or strcmp() it is saying that they are not equal even though they are same.
When I try to print the elements which are compared above some string is replacing first string's value. The code is given below. Ideally the if loop shouldn't be executed, but it is still executing and printing some garbage value instead of v1[i].
vector<string> v1 = r1->GetSchema().GetAttrTypes();
vector<string> v2 = r2->GetSchema().GetAttrTypes();
for(i=0; i<v2.size();i++)
if(v1[i] != v2[i])
cout << v1[i] << " " << v2[i] << " awdsd" << endl;
I don't know what to search for these kind of errors. I am taking strings from same file and storing in vectors in both Windows and Ubuntu.
EDIT: I am attaching part of the code here. The function right side returns vector of strings. I can't paste above classe's code as it is very big code.

The problem has to be in:
r1->GetSchema().GetAttrTypes();
This function must be mucking about with how it's std::string's are created.
Can you show us the code?

Well, everything was just fine, except file from which I am reading input string. Since I created that file on windows, it's End of line is different(\r\n) where as in Ubuntu it is (\n).
In Ubuntu I had to convert the text file I am reading input Unix Mode.
After that everything is fine.
I don't know how I missed this small point.
Thank you for your input.

Related

C++ FileIO weird behaviour

While writing a program I came accross a strange behaviour of std::ofstream. Please refer to the code below
ofstream dire;
dire.open("dir.txt", std::ios::out);
// some other code
for(int i=0;i<dir.size();i++)
{
dire << dir[i] << "\t"; // dir is integer vector containing values between 0-9
}
Now when I open dir.txt contents are:
ऴऴऴऴवववववववववशशशशशशशशशशषषषषषषषषरररररररऱऱऱऱऱऱऱऱऱललललललललललललळ.. and so on
if I give a space and then tab(\t) then it works correctly or for that matter \n also works correctly. dire << dir[i] << " \t";
And now the output is:
4 4 4 4 5 5 5 5 5 5.. and so on
I also tried dire.flush() to flush the output buffer to file, but still the same result.
I can definitely get away by using \t but I would like to learn why this is happening.
If you are using Notepad to look at the file then the bug Bush hid the facts can be the problem.
The bug occurs when the string is passed to the Win32 charset detection function IsTextUnicode with no other characters. IsTextUnicode sees what it thinks is valid UTF-16LE Chinese and returns true, and the application then incorrectly interprets the text as UTF-16LE.

C++ Opening file with *i pointer, Overrides in Linux but not in Windows

So I've got this program working in Windows, and I'm trying to make it also work on a Linux machine. I believe the Linux machine is running an outdated version of g++ compiler but that is out of my control. Anyway, heres my function:
for (vector<string>::iterator i = groups.begin(); i != groups.end(); ++i)
{
inStream.open((*i + "List.txt").c_str());
while (getline(inStream, next))
{
if (next == n) {
memberOf.push_back(*i);
}
}
inStream.close();
}
The issue lies with the inStream.open() call. In windows this works fine, but in Linux it seems that *i (for example lets say that *i is pointing to "Tigers") is being overridden and therefore the call is just inStream.open("List.txt"); as opposed to inStream.open("TigersList.txt");
I've tried various ways of solving this, such as setting string k = *i; which works in itself in the sense that if I call cout << k; it prints "Tigers". However as soon as I try to concatenate "List.txt" to the end it just overrides "Tigers" and I'm left with only "List.txt"
ex:
k += "List.txt";
k.append("List.txt");
etc. Nothing seems to work in Linux, however everything I've tried has the same (correct) end result in windows.
What am I doing wrong???
Edit: inStream is an ifStream object.
memberOf is another vector of strings.
It sounds like you are reading Tigers from a file that contains Windows line endings. If you read this file in Linux, then reading the line:
Tigers\r\n
will result in your string in memory being Tigers\r. Then when you concatenate to it, even though the result actually ends up being Tigers\rList.txt, when you print it out then your terminal treats \r as carriage return and so List.txt overwrites Tigers on your screen.
Of course, opening the file fails because the filename didn't contain an embedded \r.
To fix this you could do one of the following:
In Linux, make sure that the file you're opening has Linux line endings (e.g. run dos2unix on it)
Update your program to look for and discard a \r on the end of a line that it has read from the file.

Reading file line by line with C++ always output 2 lines even if file is different

I need to store each lines of a text document into a vector. However any file text I try, the output is always 2 lines. First one is empty and second one always output: "DONE". I'm on Windows7 X64, using VC++2013.
I have been trying to solve this for many hours. I tried many different approach but the result stay the same. I suspect that "DONE" is the return value from getline() however I don't understand with my code is not working like it should.
int main() {
ifstream hFile("test.txt");
vector<string> lines;
string line;
while (std::getline(hFile, line))
lines.push_back(line);
cout << lines[1];
hFile.close();
getchar();
return 0;
}
EDIT: It works fine when executing the program from the compilation folder but not in the debug console of VC++...
The program looks mostly correct. The only problem is that your code assumes that there are, at least, two lines in your file: if there are few lines, e.g., just one or the files couldn't be opened, the statement
cout << lines[1];
result in undefined behavior. Did you mean to print each line of the file rather than just the second line?
From the description of the behavior I would suspect that you file either contains the string DONE or you are actually executing a different program!
Be careful, it proves nothing about the count of lines:
cout << lines[1];
Use line.size() to count the read lines. In fact for a file with one line, it's undefined behavior to access second item.

Strange stdout behavior

I'm currently writing a socket program in C++ and I've stumbled across very strange behavior when trying to write to the console (a required task), for some reason.
cout << themsg[0] << themsg[1] << endl;
cout << "Phase 3: Supernode sent the message " << themsg[0] << " on dynamic port number " << themsg[1] << endl;
themsg[0] is the string "User#2:What's up Dick?"
themsg[1] is the string "39416"
The first line should write "User#2:What's up Dick?" to the console, followed by "39416".
The second line should print "Phase 3: Supernode sent the message User#2:What's up Dick? on dynamic port number 39416"
The console output reads as follows:
394162:What's up Dick?
on dynamic port number 39416essage User#2:What's up Dick?
I know that themsg[0] and themsg[1] are correct because I wrote their values to a file for verification. It surely has to be some weird stdout issue.
For the first line it appears the 5 characters of themsg[1] overwrite the first five characters of themsg[0]. For the second line, it appears that the first two parameters for cout are ignored, and then there is a message fragment appended.
If anyone can help, I would really appreciate it. I tried using flush() but to no avail. I'm not really sure how the output buffer works, so I'm really lost with this.
You probably have a carriage return symbol, \r, at the end of themsg[0]. I can reproduce the behavior with the following program on Linux:
int main()
{
std::cout << "User#2: what's up?\r" << "39416" << std::endl;
}
The \r, when not followed by \n, has the effect of returning the virtual "carriage" of the terminal to the beginning of the line, so the next print will overwrite what was already there. You won't see this showing up in a file, though, as the file will just contain both strings including the CR.
Strip off the \r before printing.
I suspect the problem is in your themes variable. I tested your exact setup - and, with proper values, it works correctly. However I then tested the same setup but appended \r to the end of themsg[1] and themsg[2] - and got exactly your behaviour. As your string themsg[1] is coming from the network, it probably has line ending included - and from a different operating system (e.g. UNIX vs Windows) - this is converted to a carriage return without the line feed - resulting in the behaviour you're seeing.

Interesting problem in std::string to str::string.c_str() conversion with file paths

I've ran into an interesting problem. I have the following code:
cout << "\nFILE";
cout << "\tLocation:" << file.location << endl;
cout << "\tLocation (c_str()): " << file.location.c_str() << endl;
where location is set by a function that finds a file location in a file with the format
DRIVE:\dir1\dir2...\filename.extension
For example, the function will have successfully set file.location to
C:\Documents and Settings\admin\testfile.foo
However, the strangest thing happens. It outputs something that looks like this:
FILE
Location: C:\Documents and Settings\admin\testfile.foo
Location (c_str()): C:\Documents
Note the lack of the remaining file path. Being the astute programmer I am, I decided to test absolute paths. I physically set the string file.location to
C:\\Documents and Settings\\admin\\testfile.foo
and the corresponding output was
FILE
Location: C:\Documents and Settings\admin\testfile.foo
Location (c_str()): C:\Documents and Settings\admin\testfile.foo
as expected. I then tested
C:\Documents and Settings\admin\testfile.foo
and the output was
FILE
Location: C:Documents and Settingsadmintestfile.foo
Location (c_str()): C:Documents and Settingsadmintestfile.foo
also expected.
I cannot for the life of me figure out what could possibly be going wrong. The file path is clearly correct in the string itself, why would it change only in this case?
There are so many wrong things in your code... Here is the number 1 problem:
temp2 = char(HexToInt(temp2));
temp2 is empty at this point, so HexToInt returns 0.
Here are more problem:
temp = Location[i+1] + Location[i+2];
this adds two char resulting in an int. It does not concatenate them. Use std::string::substr instead.
temp += j * pow(16.00, k);
don't use floating point like this.
P.S. and this just demonstrates that you code is more important than your problem description.
I'm not quite sure I understand what exactly you're asking here, but I have a suggestion that can save you a lot of headache when manipulating paths: use Boost.Filesystem.Path. It will probably solve the problem you're having here as well. :)
Now, for your first case - if I understand correctly, file.location is an std::string. If you write it directly to a stream, it gives you the full string, but if you use c_str(), the string gets cut in the middle. That probably means you've got a NULL character in the middle of your string, after the document. I don't know why is that, but if you could post here the code that actually sets file.location, we may be able to help you.