C++ written on Windows doesn't work on Linux

Hi,

I have written a small program on Windows using CodeBlocks and MinGW. What it does is read data from a CSV file and generate various other data from it and write them to a TXT file. It's very short, about 100 lines.

My problem is that the program compiles and works just fine on Windows, but when compiled and run on Linux, it does not produce the expected results. And I think I haven't used anything Windows specific. I can post the source code if needed. What could the problem be?
Do post the code. Although I don't have a linux partition to test it..
Could it be a / and \ problem in paths?
Also, what exactly does the linux version do?
Last edited on
You surely have to post the code or at least some part of it.

Also it would help if you be more specific about what
it does not produce the expected results
exactly means.

Your program compiles fine, executes fine and the sole problem is the output is not the expected one?
I guess you are producing a text file, so maybe is it something with the program you examine your output.

For example when I open text files from linux to windows new line does not correspond exactly to each other. Windows require \r\n I think for getting the \n on Linux. Is this kind of error you are getting or something worse?
Last edited on
If the file is read/written as a text file, the mapping of \n to \r\n and back will happen automatically on Windows. But if you want to read the same file on a Windows and a Linux machine this is not what you want, In that case, you prob want to write \n to your file.

The path delimiter shouldn't be a prob. The Windows File API automatically converts / to \ for input paths, and then carries on as usual.

As the others have said, you need to be more specific about what the problem is.

I assume you're working with regular Ansi text files, rather than Unicode.

Andy
Yeah it might be the newlines. Although the CSV displayed fine using "cat" and also "gedit", I can still imagine that my program didn't see them.

I'll post the code now with some "disclaimers":
1. I'm Hungarian, sorry for not changing the variable names and stuff to English.
2. It was a test at university, I was very tired and so the code is not the clearest possible.
3. What the program does is the following:
- Read data about Santa Claus's present deliveries in the following line format:
departure date and time,arrival date and time,town;street;number,present
- Read data about the weight of each present type from a separate file
- How many puppies ("kis kutya") and toy cars ("kisauto") were delivered in each hour?
- To which addresses were dolls ("baba") delivered?
- To which addresses were more than one deliveries made?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<vector>
using namespace std;

struct sulyok{string ajnev; double s;};
sulyok getsulyfrom(ifstream& in){sulyok su; getline(in, su.ajnev, ','); in>>su.s; in>>ws; return su;}

struct varos_suly{string vnev; double vsuly;};

struct delivery
{
    string ind;
    string erk;
    int erk_ora()
    {
        stringstream sst;
        int i;
        sst<<erk;
        sst.ignore(100, ' ');
        sst>>i;
        return i;
    }
    string cim;
    string varos(){return cim.substr(0, cim.find(';'));}
    string ajandek;
    double ajandeksulya(vector<sulyok> v)
    {
        double a=0;
        for (unsigned int i=0; i<v.size(); i++) if (v[i].ajnev==ajandek) a=v[i].s;
        return a;
    }
    varos_suly fvnev(vector<sulyok> ssulyok){varos_suly vs; vs.vnev=varos(); vs.vsuly=ajandeksulya(ssulyok); return vs;}
};  delivery getdelivfrom(ifstream& in)
    {
        delivery d;
        getline(in, d.ind, ',');
        getline(in, d.erk, ',');
        getline(in, d.cim, ',');
        d.cim[0]=toupper(d.cim[0]);
        d.cim[d.cim.find(';')+1]=toupper(d.cim[d.cim.find(';')+1]);
        getline(in, d.ajandek);
        return d;
    }

struct report
{
    int kutyaszam, autoszam;
    report operator+=(report b){kutyaszam+=b.kutyaszam; autoszam+=b.autoszam; return *this;}
};  report getfrom(delivery d){report r; r.kutyaszam=d.ajandek=="kiskutya"; r.autoszam=d.ajandek=="kis auto"; return r;}

int main()
{
    //READ
    ifstream bf("naplo.csv");
    ifstream sbf("suly.txt");
    ofstream kf("jelentes.txt");
    vector<delivery> v;
    vector<sulyok> vsvs;
    while (bf.good()) v.push_back(getdelivfrom(bf));
    while (sbf.good()) vsvs.push_back(getsulyfrom(sbf));

    //PROCESSING
    vector<report> jelentes;
    vector<string> babacimek;
    jelentes.push_back(getfrom(v[0]));
    for (unsigned int i=1; i<v.size(); i++)
    {
        if (v[i].erk_ora()==v[i-1].erk_ora()) jelentes.back()+=getfrom(v[i]);
        else jelentes.push_back(getfrom(v[i]));
        if (v[i].ajandek=="baba") babacimek.push_back(v[i].cim);
    }
    vector<string> cimek;
    for (unsigned int i=0; i<v.size(); i++) for (unsigned int j=0; j<v.size(); j++) if (v[i].cim==v[j].cim && v[i].erk!=v[j].erk) cimek.push_back(v[i].cim);
    vector<varos_suly> varosonkent;
    varosonkent.push_back(v[0].fvnev(vsvs));
    for (unsigned int i=1; i<v.size(); i++)
    {
        if (v[i].varos()==v[i-1].varos()) varosonkent.back().vsuly+=v[i].ajandeksulya(vsvs);
        else varosonkent.push_back(v[i].fvnev(vsvs));
    }

    //OUTPUT
    kf<<"- Orankenti kutyak es autok mennyisege:\nOra\tKutya\tAuto\n";
    for (unsigned int i=0; i<jelentes.size(); i++) kf<<i<<'\t'<<jelentes[i].kutyaszam<<'\t'<<jelentes[i].autoszam<<endl;
    kf<<"\n- Babak a kovetkezo cimekre kerultek szallitasra:";
    for (unsigned int i=1; i<babacimek.size(); i++)
    {
        kf<<endl<<babacimek[i-1];
        if (babacimek[i]==babacimek[i-1]) {kf<<" (2 db)"; i++;}
    }
    kf<<"\n\n- A kovetkezo cimeket erintettuk ketszer:\n";
    for (unsigned int i=1; i<cimek.size(); i++) if (cimek[i] != cimek[i-1]) kf<<cimek[i-1]<<endl<<cimek[i]<<endl;
    kf<<"\n- Varosonkenti ajandekok sulya:\n";
    for (unsigned int i=0; i<varosonkent.size(); i++) kf<<varosonkent[i].vnev<<' '<<varosonkent[i].vsuly<<endl;
    cout<<"A jelentes elkeszult a jelentes.txt fajlba.\n";
    bf.close(); kf.close(); sbf.close();
}


And yeah, it's exactly 100 lines :)
But what are the unexpected results??

Andy
On Windows this program correctly solves all tasks as specified above. On Linux it outputs all zeros, like zero weight of presents delivered to all towns, zero towns visited twice, zero deliveries of dolls and puppies and toy cars.

And I've compiled and run it on several computers running Windows and several computers running Linux.
@marczellm
if that's true what ur saying then this code desirves to be reported to the C++ comitee.

joke, lol.
Is the file you use for your testing provided to you? Can we see a bit of it?

Have you added logging code to your app to check what it's doing in getdelivfrom(), etc.

To start with, are there the same number of elements in vector<delivery> v and vector<sulyok> vsvs after loading the same/equivalent files on Windows and on Linux?

And can you just use your file reading code to output the values it finds?

Andy
naplo.csv sample:

2011.12.05. 11:55:52,2011.12.05. 12:41:7,Dravagardony;Deseda utca;26,baba
2011.12.05. 12:41:7,2011.12.05. 12:45:43,Magyarlukafa;Benedek Elek utca;56,kis auto
2011.12.05. 12:45:43,2011.12.05. 13:25:48,Csesztve;Cserhat;49,kombany
2011.12.05. 13:25:48,2011.12.05. 14:22:48,Erdosmarok;Fenyves koz;91,ruzs

suly.txt sample:

baba,20
kis auto,50
kombany,80
laptop,40
cica,20
ruzs,0.50
csuzli,10
labda,10
kerekpar,70

I've just checked that on both OS-s the program reads all content correctly, by outputting everything just after reading it, from the variable it was put into. I'll continue doing more checks.

Sidenote: I think it's legal posting these, as the teacher himself gave me the files because he could not evaluate my work as he was running Linux. :S
$ cat jelentes.txt
- Orankenti kutyak es autok mennyisege:
Ora	Kutya	Auto
0	0	1
1	0	0
2	0	0
3	0	0

- Babak a kovetkezo cimekre kerultek szallitasra:

- A kovetkezo cimeket erintettuk ketszer:

- Varosonkenti ajandekok sulya:
Dravagardony 20
Magyarlukafa 50
Csesztve 80
Erdosmarok 0.5
 0
It is loosing the 'baba' because you start the loops at 1 instead of 0.

To which addresses were more than one deliveries made?
¿Aren't you outputting the 'weight' of the load instead?


And yeah, it's exactly 100 lines :)
Whitespace is free.
Last edited on
It is losing the 'baba' because you start the loops at 1 instead of 0.

Thank you, I should put it in a separate loop to avoid the segfault at the v[i-1] part.

More interesting:
I've managed to reduce the problem to a smaller code. Consider the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;

struct delivery
{
    string ind;
    string erk;   
    string cim;    
    string ajandek;   
};  

delivery getdelivfrom(ifstream& in)
    {
        delivery d;
        getline(in, d.ind, ',');
        getline(in, d.erk, ',');
        getline(in, d.cim, ',');        
        getline(in, d.ajandek);
	cout<<d.ajandek<<endl;
        return d;
    }

void getfrom(delivery d){cout<<d.ajandek;}

int main()
{
    ifstream bf("naplo.csv");
    vector<delivery> v;
    while (bf.good()) v.push_back(getdelivfrom(bf));
    cout<<"_______________________________________________\n";
    for (int i=0; i<v.size(); i++) getfrom(v[i]);
    bf.close();
}


Compile it with g++ on Linux. Run it on the following file: http://users.itk.ppke.hu/~marma/naplo.csv
(This is the original file.)
I get output that ends with this:
csuzli
labda
kombany
cica
csuzli
laptop

_______________________________________________


As you can see there is no output after the horizontal line.
Now change the getfrom() function to:

void getfrom(delivery d){cout<<d.ajandek<<endl;}

I've only added an "endl". Compile and run it again. Now I get full and correct output, with all presents repeated after the line. Why can the "endl" do this?

(I've checked it on two computers running Linux. Actually they are university servers, running g++ 3.3.5 and g++ 4.3.2. On my Windows home computer, everything is fine.)
In that file every line ends with a '\r' that gets stored in your strings.
So when you print them the carriage return make them go back to the begginning, overwritting the previous item.
OK, thank you very much! I've now added a line to the original code which removes the carriage return, so now the output is correct.

In function getdelivfrom (ifstream&)
if (d.ajandek[d.ajandek.length()]=='\r') d.ajandek=d.ajandek.substr(0,d.ajandek.length()-1);
Is there a shorter way of doing this anyway?

This is something like what eypros and andywestken were saying. I'll continue looking for other errors, because although I can display the name of the present now, it still returns false for d.ajandek=="kis auto" even if I print d.ajandek to the console just before this line and it prints it's very much a toy car. Are there any more escape characters that can make my program output FUBAR? (http://en.wikipedia.org/wiki/Fubar)

I also tried isspace(d.ajandek[d.ajandek.length()]) instead of =='\r' to no result.

perl -pe 's/\r//' < naplo.csv > aux && mv aux naplo.csv
Does 0 == strncmp(d.ajandek.c_str(), "kis auto", 8) work?

You did say the "toy car" displays OK, so the part of the string that displays must be ok, yes?

Andy
Topic archived. No new replies allowed.