2014-09-10 68 views
0

我有以下C++程序:C++代码产生通过Visual StudioÇ不同的输出++和GCC

//============================================================================ 
// Name  : 
// Author  : Bryce Sandlund 
// Version  : 
// Copyright : 
// Description : Code skeleton 
//============================================================================ 

#include <iostream> 
#include <iomanip> 
#include <set> 
#include <vector> 
#include <algorithm> 
#include <cmath> 
#include <complex> 
#include <cstdlib> 
#include <sstream> 
#include <list> 
#include <map> 
#include <fstream> 
#include <string> 
#include <time.h> 
#include <queue> 
#include <tuple> 
#include <functional> 
#include <unordered_set> 
#include <unordered_map> 

#define INF 1000000000 
#define all(c) (c).begin(),(c).end() 
#define tr(c,i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i) 
#define EP .00001 

using namespace std; 

typedef pair<int, int> ii; 
typedef vector<int> vi; 
typedef vector<bool> vb; 
typedef vector<vi> vvi; 
typedef vector<vb> vvb; 
typedef vector<ii> vii; 
typedef vector<double> vd; 
typedef vector<vd> vvd; 
typedef long long LL; 

vvi adjList; 
unordered_map<string, int> targs; 

int add(string &s) 
{ 
    if (targs.count(s)) 
     return targs[s]; 

    targs[s] = targs.size(); 
    adjList.push_back(vi()); 
    return targs.size()-1; 
} 

void connect(int si, int ti) 
{ 
    if (si == ti) 
     return; 

    for (int i = 0; i < adjList[si].size(); ++i) 
    { 
     if (adjList[si][i] == ti) 
      return; 
    } 

    adjList[si].push_back(ti); 
} 

vi bfs(int s) 
{ 
    queue<ii> q; 
    q.push(ii(s, -1)); 

    vi dist(adjList.size(), INF); 

    while (!q.empty()) 
    { 
     int top = q.front().first; 
     int hops = q.front().second; 
     q.pop(); 
     if (dist[top] != INF) 
      continue; 

     dist[top] = hops; 
     for (int i = 0; i < adjList[top].size(); ++i) 
     { 
      q.push(ii(adjList[top][i], hops+1)); 
     } 
    } 

    return dist; 
} 

int main() { 
    int caseNum = 1; 
    cout << "Case " << caseNum << ":" << endl; 
    string line; 
    while (getline(cin, line)) 
    { 
     stringstream ss(line); 

     string command; 
     ss >> command; 
     if (command == "add") 
     { 
      string s, t; 
      ss >> s; 

      int si = add(s); 
      if (ss >> t) 
      { 
       int ti = add(t); 

       connect(si, ti); 
       connect(ti, si); 
      } 
     } 
     else if (command == "connections") 
     { 
      string s; 
      ss >> s; 

      if (!targs.count(s)) 
      { 
       cout << "target does not exist" << endl; 
       continue; 
      } 

      int st = targs[s]; 
      if (adjList[st].empty()) 
      { 
       cout << "no connections" << endl; 
      } 
      else 
      { 
       vi dist = bfs(st); 

       vi away(adjList.size(), 0); 
       int maxd = -1; 
       for (int i = 0; i < dist.size(); ++i) 
       { 
        if (dist[i] == INF || dist[i] == -1) 
         continue; 

        ++away[dist[i]]; 
        maxd = max(maxd, dist[i]); 
       } 

       for (int i = 0; i <= maxd; ++i) 
       { 
        cout << i << ": " << away[i] << endl; 
       } 
      } 
     } 
     else if (command == "associated") 
     { 
      string s, t; 
      ss >> s >> t; 

      if (!targs.count(s) || !targs.count(t)) 
      { 
       cout << "target does not exist" << endl; 
       continue; 
      } 

      int si = targs[s], ti = targs[t]; 
      vi dist = bfs(si); 

      if (dist[ti] == INF) 
      { 
       cout << "no" << endl; 
      } 
      else 
      { 
       cout << "yes " << dist[ti] << endl; 
      } 
     } 
     else 
     { 
      adjList.clear(); 
      targs.clear(); 
      cout << "----------" << endl; 
      cout << "Case " << ++caseNum << ":" << endl; 
     } 
    } 

    cout << "----------" << endl; 
    return 0; 
} 

我使用这个作为输入:

add a b 
add a c 
add b d 
add e b 
add c f 
add c g 
add f h 
add h i 
add j k 
associated a i 
associated i a 
associated f k 
associated a h 
connections a 
connections i 
add k g 
associated a j 
connections a 
add h a 
connections a 
associated a h 
add m 
add n n 
connections n 
add a n 
connections n 

在Visual C++,代码产生这输出(它这样做的调试或释放):

Case 1: 
yes: 3 
yes: 3 
no 
yes: 2 
0: 2 
1: 4 
2: 1 
3: 1 
0: 1 
1: 1 
2: 1 
3: 2 
4: 1 
5: 2 
yes: 3 
0: 2 
1: 4 
2: 2 
3: 2 
0: 3 
1: 5 
2: 1 
3: 1 
yes: 0 
no connections 
0: 1 
1: 3 
2: 5 
3: 1 
4: 1 
---------- 

在GCC克++,它产生以下输出:

Case 1: 
no 
no 
yes 0 
no 
0: 2 
1: 2 
2: 2 
3: 1 
0: 1 
no 
0: 2 
1: 2 
2: 2 
3: 1 
0: 3 
1: 2 
2: 2 
3: 1 
yes 0 
---------- 

仅供参考,我正在尝试解决此问题:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=620&page=show_problem&problem=4574

任何想法为什么输入和输出在不同的编译器上会有所不同?我不相信我正在使用任何未定义的行为。

+1

您需要调试策略,例如,添加一些代码将内部状态转储到日志文件,然后在两个编译器上运行代码并比较日志文件,以便可以识别(或至少缩小)差异来自哪里。重复,直到你发现问题。 – 2014-09-10 14:54:11

+1

有意义的变量名称的概念很重要。 http://stackoverflow.com/questions/203618/how-to-name-variables – 2014-09-10 14:55:27

+0

有趣的部分是VS我们产生正确的输出。在出界情况下,我们不会期望垃圾? – 2014-09-10 15:17:45

回答

1

两种平台中代码行为差异的原因是add函数。您有:

int add(string &s) 
{ 
    if (targs.count(s)) 
     return targs[s]; 

    targs[s] = targs.size(); 
    adjList.push_back(vi()); 
    return targs.size()-1; 
} 

在该功能中,有问题的路线是:

targs[s] = targs.size(); 

该生产线是棘手,因为这取决于赋值运算符的一侧首先得到评价,你会得到不同的行为。请注意,targs[s]涉及更改对象的函数调用。

您可以稍微更改该功能,以使其在各个平台上保持一致和可预测。

int add(string &s) 
{ 
    if (targs.count(s)) 
     return targs[s]; 

    int size = targs.size(); 
    targs[s] = size; 
    adjList.push_back(vi()); 
    return size; 
} 
+0

很好的捕获。我非常有信心,这不是一个矢量问题。 – 2014-09-10 17:25:32