C带有字符数组的意外输入

时间:2016-04-01 20:34:17

标签: c arrays char undefined-behavior

我正在与一个关于Google Code Jam练习题的小组合作(您可以阅读here)。我们的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

main(){
  int c;
  int n = 0;
  int l = 0;
  int d = 0;
  int caseCount = 0;
  int i = 0;
  int j = 0;
  //A boolean value used in determining parenthesees.
  bool letBool = false;
  //A boolean value used in determining something;
  bool wordBool = false;
  //Temporary space for test characters
  char test[1000];
  //Gets word length
  while((c=getchar())!=' ' && c!= '\n'){
    l = (l * 10) + c - '0';
    //printf("%d\n", l);
  }
  //Gets number of valid words.
  while((c=getchar())!=' ' && c!= '\n'){
    d = (d * 10) + c - '0';
    //printf("%d\n", d);
  }
  //Gets number of test cases.
  while((c=getchar())!= '\n'){
    n = (n * 10) + c - '0';
    //printf("%d\n", n);
  }
  //Array of all valid words.
  char dict[d][l];
  c=getchar();
  //While we still have words to read in.
  while(i < d){
    //If not new line
    if(c!='\n'){
      //Then read character
      dict[i][j] = c;
    }
    else{
      i++;
      j=0;
    }
    c=getchar();
    j++;
  }
  i = 0;
  j = 0;
  while(i < n){
    j = 0;
    while((c=getchar())!='\n' && c!=EOF){
      putchar(c);
      test[j] = c;
      j++;
    }
    putchar('\n');
    test[j+1] = '\0';
    printf("%s\n", test);
    int word = 0;
    //Going through valid words
    while(word < d){
      wordBool=true;
      j = 0;
      int letter = 0;
      //Going through valid letters
      while(letter < l){
        letBool=false;
        if(test[j] == '('){
          while(test[j++]!=')'){
            if(dict[word][letter]==test[j]){
              letBool=true;
              //printf("%s%d%s%d\n" "letBool is true at word: ", word, "letter: ", letter);
            }
          }
        }
        else{
          if(test[j]==dict[word][letter]){
            letBool=true;
            //printf("%s%d%s%d\n" "letBool is true at word: ", word, "letter: ", letter);
          }
        }
        j++;
        letter++;
        if(!letBool){
          wordBool=false;
          //printf("%s%d%s%d\n" "wordBool is false at word: ", word, "letter: ", letter);
        }
      }
      if(wordBool){
        caseCount++;
      }
      word++;
    }
    printf("%s%d%s%d\n", "Case #", i+1, ": ", caseCount);
    i++;
    j=0;
    caseCount=0;
  }
}

问题是输出似乎正确读取了&#34;收到的外星人代码&#34;没有putchar的部分,但是当它进入测试用例时,它就会被破坏。以下是我要谈的部分:

while((c=getchar())!='\n' && c!=EOF){
      putchar(c);
      test[j] = c;
      j++;
    }
    putchar('\n');
    test[j+1] = '\0';
    printf("%s\n", test);

当我们给出这个输入时:

3 5 4
abc
bca
dac
dbc
cba
(ab)(bc)(ca)
abc
(abc)(abc)(abc)
(zyx)bc

我们得到了

ab)(bc)(ca)
ab)(bc)(ca)
7
Case #1: 0
abc
abc
b
Case #2: 1
(abc)(abc)(abc)
(abc)(abc)(abc)
Case #3: 0
(zyx)bc
(zyx)bcb
Case #4: 0

(
Case #5: 0

所以,我们无法理解为什么会出现像7和b这样的随机字符。

1 个答案:

答案 0 :(得分:0)

改变这个:

test[j+1] = '\0';

到此:

test[j] = '\0';

原因是在满足终止条件之前,你已经在while循环结束时递增了j的值:

j = 0;
while((c=getchar())!='\n' && c!=EOF){
  putchar(c);
  test[j] = c;
  j++;    <------
}
putchar('\n');
test[j] = '\0';

因此,对于test[j + 1],您实际上跳过了一个单元格。这意味着您遇到未定义的行为,因为跳过的单元格包含垃圾,因为test未初始化为空。因此,我们不知道该单元格包含什么,它包含 junk

使用更正后的代码输出:

gsamaras@gsamaras:~$ gcc -Wall px.c
gsamaras@gsamaras:~$ ./a.out 
3 5 4
abc
bca
dac
dbc
cba
(ab)(bc)(ca)
abc
(abc)(abc)(abc)
(zyx)bcab)(bc)(ca)
ab)(bc)(ca)
Case #1: 0
abc
abc
Case #2: 1
(abc)(abc)(abc)
(abc)(abc)(abc)
Case #3: 0

(zyx)bc
(zyx)bc
Case #4: 0

此外,使用:

int main(void) {
  ...
  return 0;
}

有关详情,请参阅:What should main() return in C and C++?