1

I was working with a group on a Google Code Jam practice problem (you can read it here). Our code is as follows:

#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;
  }
}

The problem is the output seems to correctly read the input for the "recieved alien code" part with out putchar, but when it is entered into the test case, it becomes corrupted. Here is the part I am talking about:

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

When we give it this input:

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

we get

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

So, we can't understand why there are random characters like 7 and b printed out.

gsamaras
  • 66,800
  • 33
  • 152
  • 256
MegaZeroX
  • 215
  • 1
  • 7
  • 1
    One bug is here: `test[j+1] = '\0';` It should be `test[j] = '\0';`, since `j` has already been incremented past the previous character index. – Tom Karzes Apr 01 '16 at 20:45
  • Thank you so much for the help! – MegaZeroX Apr 01 '16 at 20:51
  • That is a contest site. You are supposd to solve the problem yourself. You could even look up an answer, there are always 'cheat' sites. – Weather Vane Apr 01 '16 at 21:05
  • 1
    I don't want to cheat, it is just practice. My group couldn't figure it out, and we just wanted to know what went wrong. – MegaZeroX Apr 01 '16 at 21:08
  • @TomKarzes the OP mentioned the comments section, where I now see that you had spotted the bug too, didn't know that before posting the answer! – gsamaras Apr 01 '16 at 21:36

1 Answers1

0

Change this:

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

to this:

test[j] = '\0';

The reason is that you already incremented j's value, at the end of the while loop, before the terminating condition was met:

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

So, with test[j + 1], you actually skipped a cell. That means that you are experiencing Undefined Behaviour, since that skipped cell contains junk, since test was not initialized to nothing. As a result, we do not know what that cell contains, it contains junk.

Output with the corrected code:

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

Moreover, use:

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

For more, read this: What should main() return in C and C++?

Community
  • 1
  • 1
gsamaras
  • 66,800
  • 33
  • 152
  • 256
  • 1
    Thanks! I'm learning c right now, so I didn't know that it was expected for the main function to have those standards! Sorry if the question wasn't asked well, as an upperclassman told me a few minutes ago! This is all I really needed, as the rest of the problem is definitely within my ability to figure out why we aren't getting the correct number of cases! – MegaZeroX Apr 01 '16 at 21:27
  • @MegaZeroX now you learned. :) Make sure to check my updated answer (did that just now)! OK, good luck! – gsamaras Apr 01 '16 at 21:32