0

I have created my solution for pset3's problem "Fifteen". It compiles fine with the standard makefile in cs50's on-line terminal window, and runs correctly as well (also tested with the given 3x3 and 4x4 test move files).

However, when I then run check50 cs50/2017/x/fifteen, it complains that the file didn't compile correctly. What gives?

The output it gives is:

Connecting......
Authenticating.......
Preparing..................
Uploading.............
Running checks.......
:) fifteen.c exists.
:( fifteen.c compiles.
    expected exit code 0, not 1
:| 3x3 board: init initializes board correctly
    can't check until a frown turns upside down
etc.; the rest is all frownies

At the end the link with more details reports this for the failed compilation step:

:( fifteen.c compiles.

expected exit code 0, not 1

Log
running sed -i='' '/#include <unistd.h>/a \ #define usleep(x)' fifteen.c...
running clang -S -std=c99 -Wall -Werror -Wno-deprecated-declarations fifteen.c -o fifteen.S...
checking that program exited with status 0...
running sed -i='' -e 's/callq _draw/callq _simple_draw/g' fifteen.S...
running sed -i='' -e 's/callq draw/callq simple_draw/g' fifteen.S...
running clang -std=c99 -Wall -Werror -Wno-deprecated-declarations -o fifteen simple_draw.c fifteen.S -lcs50 -lm...
checking that program exited with status 0... 

It's a shame those lines are truncated, otherwise the source of the compilation error should have showed up.

Trying things out I figured out that calling self-made functions from the draw and/or move function seems to be the culprit. Could it be that check50 extracts these expected functions from your source and pastes them into a test harness, thus losing any extra functions you add?

I'd rather keep those extra utility functions though; they make my code a lot cleaner...

Addition

It indeed seems that check50's replacement of the draw function is somehow involved.

In my case I wanted to print a +----+- ... ---+ border between each row. Since I needed to do this at 2 spots (once before each row itself and once at the end to print the final bottom border), I created a simple void drawRowBorder(void) function doing just that, and called it twice. It didn't have any side effects, and only use the already global var d to determine how many column's worth to draw.

Did compile in the cs50-IDE terminal, but didn't with check50...

My submitted code (which works) is like this (though condensed a bit for succinctness):

void draw() {
    const string rowBorder = "+----+----+----+----+----+----+----+----+----+";
    int rowBorderSize = d * 5 + 1;    
    for (int rowNr = 0; rowNr < d; ++rowNr) {
        printf("%.*s\n", rowBorderSize, rowBorder);
        for (int colNr = 0; colNr < d; ++colNr) {
            int tile = board[rowNr][colNr];
            if (tile == 0) {
                printf("| -- ");
            } else {
                printf("| %2i ", tile);
            }
        }
        printf("|\n");
    }
    printf("%.*s\n", rowBorderSize, rowBorder);
}

But when factoring out the two identical printf("%.*s\n" ... statements (incl. the rowBorder and rowBorderSize vars) into a new drawRowBorder() function, the code doesn't compile with check50 anymore:

void drawRowBorder(void) {
    const string rowBorder = "+----+----+----+----+----+----+----+----+----+";
    int rowBorderSize = d * 5 + 1;    
    printf("%.*s\n", rowBorderSize, rowBorder);
}

void draw() {
    for (int rowNr = 0; rowNr < d; ++rowNr) {
        drawRowBorder();
        for (int colNr = 0; colNr < d; ++colNr) {
            int tile = board[rowNr][colNr];
            if (tile == 0) {
                printf("| -- ");
            } else {
                printf("| %2i ", tile);
            }
        }
        printf("|\n");
    }
    drawRowBorder();
}

I also tested adding a prototype for the drawRowBorder function at the top of the .c file, though that shouldn't matter a thing since it was already located above the draw function, and after check50's replacement no-one should call it anymore.

So you'd assume check50 just replacing the entire draw function shouldn't lead to any compilation errors in this case, though it does...?

3
  • check50 will replace your draw routine with its own, but last time I saw that error, the error seemed to happen because of some unusual (and illogical) condition. After that condition got fixed, the code went through. Not sure your case is the same, as we don't get the compiler's complaint.
    – Blauelf
    Aug 28 '17 at 14:44
  • @Blauelf: thanks for that info. I already saw that question, but I didn't use anything fancy like that yet, so I dismissed it :) One of the extra functions was just a void function(void), that printed a row border of the correct length for the board. Inlining that code fixed the check50 issue. I also use a helper function in void move(void), but that one does work under check50. So it indeed seems check50 replaces the draw code, but in a weird (breaking) way... Care to make it an answer? Aug 28 '17 at 16:25
  • btw: is there a support mail address for cs50 I can send this issue to? They might be interested in looking into it. Or is the staff actively browsing this site? Aug 28 '17 at 16:28
1

check50 for fifteen replaces the draw function with a simple one whose output is then used for the tests. If your own draw function contains code (setting the values of global variables or calling other functions, for example) that would prevent fifteen.c from compiling, you'll see this issue.

The spec will be updated soon to make it clearer that your draw function should simply print the existing board and not include any other features.

5
  • That should indeed be the case then; good to point that out. Problem is though, that I didn't do anything like that... I'll update my question with the details of what specifically didn't work. Aug 30 '17 at 7:12
  • @CarlColijn If you change your function name to something that doesn't start with draw, check50 won't fail. It has to do with how the function draw is pulled out of your code. (searching for a function that begins "draw").
    – curiouskiwi
    Aug 30 '17 at 11:58
  • I'll pass it along to the team.
    – curiouskiwi
    Aug 30 '17 at 12:01
  • Ah, that explains. So it doesn't scan for an exact function signature (say, "void<whitespace>draw[<whitespace>](void)"), but uses a more partial search for exactly "void<whitespace>draw", which then also matches my new "void drawRowBorder(void)". Might be easy to improve for the staff for the next round? Which would fix these issues from then on. Thanks for clarifying it, and passing it along! I've accepted this as the answer, but you might want to add this function name matching as well to get it out of the comments. Aug 30 '17 at 16:27
  • @CarlColijn Fix in progress: github.com/cs50/check50/pull/67
    – curiouskiwi
    Aug 30 '17 at 21:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .