2011-04-05 42 views
1

我正在尝试完成一个C编程主题的高校作业。Solaris编译器使我的C代码行为怪异

我已经在我的MacBook上完成了我的任务,并且我的代码完全按照它的设计工作。然而,我们的讲师已经告诉我们,我们所有的代码都将使用大学的Solaris 10 Server进行编译,并且我们被告知如果您的代码不能编译和运行,将会扣除标记。

我们也接到指示,我们的应用程序将通过以下语法标记编译:

gcc -ansi -Wall -pedantic assign1.c -lm -o assign1 

使用和执行:

./assign1 

我的代码目前编译没有错误或警告并正确执行。但是,我的某个函数在此Solaris机器上无法正常工作。该函数应该是我们自己实现的基本字符串排序 - 用户输入一个长达40个字符的字符串,它应该被转换为小写字母并按照字母顺序排序,并删除所有非字母字符。

我的Mac上,它输出:

Enter a string (1-40 characters): asdfghjkl 
Output: adfghjkls 

在学院的Solaris系统,它输出:

Enter a string (1-40 characters): asdfghjkl 
Output: aa#?dfghjkls 

我的函数,它(大多数)输出的是:

void sortLine(int *optionStats, char* source) 
{ 
    char tempsort[MAX_SORT_LENGTH + 1]; 
    char comp_c; 
    int i,j,k; 
    char c = source[i++]; 
    i = j = k = 0; 
    optionStats[2]++; 
    while (c != '\n' && c != '\0' && c != EOF) { 
     /* convert uppercase characters to lowercase */ 
     if ((int)c >= (int)'A' && (int)c <= (int)'Z') 
     c = c + ((int)'a' - (int)'A'); 
     /* if the character is alphabeic then sort it else skip it */ 
     if ((int)c <= (int)'z' && (int)c >= (int)'a') { 
     for (j = 0; j <= MAX_SORT_LENGTH + 1; j++) { 
      comp_c = tempsort[j]; 
      if (comp_c == '\n' || comp_c == '\0' || comp_c == EOF) { 
       tempsort[j] = c; 
       break; 
      } 
      if ((int)c <= (int)comp_c) { 
       for (k = MAX_SORT_LENGTH + 1; k > j; k--) { 
        tempsort[k] = tempsort[k - 1]; 
       } 
       tempsort[j] = c; 
       break; 
      } 
     } 
     } 
     c = source[i++]; 
    } 
    /* copy the sorted temporary array into the source array */ 
    for (i = 0; i <= MAX_SORT_LENGTH + 1; i++) { 
     source[i] = tempsort[i]; 
    } 
} 

但是有一些注意事项:

  • 函数定义本身( 签名)由 讲师提供,因此名称,返回类型, 参数等不能被改变。 ,我们必须使用它(但我们 可以做任何我们想要的内部)。

  • 的代码必须是ANSI/C90兼容 (GRR!)

谁能帮我找出什么被吐出了这个功能造成这些奇怪的额外的字符 - 它做我的头?

+2

我的猜测是一个编译器初始化了一些东西(用0),而其他的不用。例如变量'i' – Anycorn 2011-04-05 04:35:19

+1

此代码可能会导致[鼻恶魔](http://www.catb.org/jargon/html/N/nasal-demons.html) – 2011-04-05 04:39:08

+0

感谢您的出色建议,但我解决了这个问题 - 但错误仍然发生。 :( – Ash 2011-04-05 04:44:26

回答

5
int i,j,k; 
char c = source[i++]; 
i = j = k = 0; 

在为其分配值之前,您正在使用i。您不能认为自动变量将被初始化为0

while (c != '\n' && c != '\0' && c != EOF) { 

因为cchar,它永远不能等于EOF。无关,但有一天你会看到这个bug :)你必须使用一个int这个成语:它初始化之前以及

int c; 

while((c=getchar()) != EOF) { 
    /* process c */ 
} 

您使用tempsort[]

 comp_c = tempsort[j]; 

你是写入数据的很多source[]数组:

for (i = 0; i <= MAX_SORT_LENGTH + 1; i++) { 
    source[i] = tempsort[i]; 
} 

我希望source[]数组是保证要足够大以容纳MAX_SORT_LENGTH数据,而不是仅仅足够容纳标准C字符串。由于这可能是一位友善的教授,这可能是好的,但这不是我会轻易做出的假设。

作为最后一个暗示,这些(int)演员中的每一个都是无用的;编译器知道如何对变量进行比较和算术运算。 :)

+0

WOOHOO你修好了!这是tempsort,我把第一行改成了char tempsort [MAX_SORT_LENGTH + 1] = {'\ 0'};'现在它也可以运行!很多!我想有时很难看到代码的错误,呵呵?我一直在盯着这个功能,感觉像是几个小时! – Ash 2011-04-05 04:48:46

+0

感谢您的其他建议,它们也非常好 - 尽管在演员阵容中'(int)'强制转换,我意识到它们不是必需的,但我仍然只学习C,它们适合我,而不是编译器!:P – Ash 2011-04-05 04:50:13

+1

@Ash,excellent!:)当然,我一直盯着一段代码太久,发现缺陷可能会很困难。这就是为什么在开发软件非常重要时进行良好的[代码审查](http://en.wikipedia.org/wiki/Code_review)过程的原因之一 - 新鲜眼睛可以找到不同的错误。 :) 玩的开心! – sarnold 2011-04-05 04:58:37

3

不知道这是什么原因,但我注意到,你用我它的正确初始化之前:

char c = source[i++]; 
i = j = k = 0; 

你要翻转过来,这两行。

2

也许错误是没有初始化本地变量我为零。

2

一对夫妇的提示:

  • 如果你有对不同的系统显示不同结果的程序,它往往是一个迹象表明它使用未初始化的数据
  • 你传递的“-Wall”(打印所有警告)标志为gcc,这很好,但是你可能想知道,如果你还使用“-O”(优化)标志,gcc可以更好地检测(并警告)未初始化的变量

另外,请仔细观察循环中的边界条件。你确定你没有访问超出阵列末尾的内存吗?请记住,如果您有像char x[10]这样的数组,有效值为x[0]x[9]; x[10]超出界限。

+0

这是伟大的建议。我刚刚使用-O,但gcc没有输出任何内容(像以前一样),所以我认为这意味着它的一切都好? – Ash 2011-04-05 04:43:08

+0

您需要同时使用-O和-Wall。当我从上面复制的代码上执行'gcc -O -ansi -Wall -pedantic'时,我得到了“警告:'我在这个函数中未被初始化使用”(正如许多人指出的那样) – 2011-04-05 04:45:56

+1

@Ash,我也像'-Wextra',但在这种情况下,它没有添加任何新的警告。 'WALL'实际上并不是警告。 :( – sarnold 2011-04-05 05:00:11