0

I have got a problem with vigenere:

:) vigenere.c exists
:) vigenere.c compiles
:) encrypts "a" as "a" using "a" as keyword
:( encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword
   \ expected output, but not "xosme, tbz ifmmp!\n"
:( encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
   \ expected output, but not "CaSGpp\n"
:( encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
   \ expected output, but not "CASGPP\n"
:) handles lack of argv[1]
:) handles argc > 2
:) rejects "Hax0r2" as keyword

This is the output I got from check50. However, I found that the third character of the code is always wrong. I cannot find my mistake. Any suggestions?

4
  • @Kareem I don't think this is the same problem as that question - the output is different.
    – Air
    Jul 23 '14 at 21:14
  • Hi, @AirThomas! That's why I said it's a possible duplicate. The answers there though contain some useful tips to get vigenere up and running. Besides, I think he's not ignoring non-alphabetical chars correctly, so I thought this might be relative.
    – kzidane
    Jul 23 '14 at 21:49
  • @Kareem The code in this question does indeed have different problems to the other question. This code does appear to filter non-alphabetical characters correctly using isalpha. The problems here are with the modulo operator, key case conversion, and final output. Jul 23 '14 at 23:22
  • @LukeVanIn I see! Deleted the comment and retracted the closing vote. Thank you!
    – kzidane
    Jul 23 '14 at 23:26
2

There are a few subtle problems here. I'm not going to give you the answer directly, but I can give you some hints.

Tip #1:

Look at the line of output from check50 relating to the error:

encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword \ expected output, but not "xosme, tbz ifmmp!\n"

This tells you:

  1. The program is being given the string world, say hello! as input.
  2. The program is being given baz as the key.
  3. Check50 is expecting the output to be xoqmd, rby gflkp!.
  4. Your program is outputting xosme, tbz ifmmp!\n.

Consider the calculations for each character:

  • w + b = 22 + 1 = 23 = x
  • o + a = 14 + 0 = 14 = o
  • r + z = 17 + 25 = 42 = 42 modulo 26 = 16 = q?

You're obviously not getting an q, which you should be by your calculations.

Tip #2

To see what is going on here, you might use the printf statement just to display the values of the variables. As you will see later in the course, there are more sophisticated ways, but this is easiest for now.

For example, you could add code into your loop to print out the value of j and the result of strlen(argv[1]), considering that those are relevant to the key:

for (int i = 0; i < plainn; i++)
{
    printf("\n\n");                            # add these lines
    printf("j: %d\n", j);                      # to inspect some
    printf("argv[1]: %d\n", strlen(argv[1]));  # important values

    if (j>=(strlen(argv[1])))
    {
        j = 0;
    }

    ...

Now when you run your program you might see the values as follows:

j: 0
argv[1]: 3
x

j: 1
argv[1]: 3
o

j: 2
argv[1]: 1
s

j: 1
argv[1]: 1
m

...etc

From this output can see that everything was working as expected in the first two iterations of the loop. On the third iteration something strange happened - the length of argv[1] suddenly went to 1.

Tip #3:

The final output comparison is very literal. Even when you have the encryption working you will not pass check50 unless your output matches the problem set specifications exactly.

Tip #4:

To understand why the key is changing, trace the flow of information in the program. , specifically in the lines below. I have commented out some code to highlight the relevant lines:

// include files

int main(int argc, string argv[])
{
    // validate arguments

    // Assign the argv[1] parameter to the key.
    // This is a pointer assignment, only the address is changed.
    // After this key and argv[1] point to the same location.
    // Modifying key will also modify argv[1], this is the essence of pointers.
    string key = argv[1];

    // validate the key and initialise variables

    for (int i = 0; i < plainn; i++)
    {

        // check the length of argv[1]
        if (j >= strlen(argv[1]))
        {
            ...
        }


        if (islower(key[j]))
        {
            // Assign a value to key.
            // Remember that key points to the same location as argv[1]
            // Setting key also updates argv[1]
            // Think carefully about what happens here.
            // If you get the letter 'a' (char 97) for example.
            //    key[j] = key[j] - 97
            //    key[j] = 0
            // Remember that this is also setting argv[1]. 
            // What happens when you call strlen(argv[1]) in the code above?
            key[j] = key[j] - 97;
        }

        ...

    }

    ...
}
2
  • @user1638 As the others have commented, please follow stack overflow guidelines and update your question, or add comment on a specific answer, it just makes it easier for others who might also be learning from this. Jul 26 '14 at 13:16
  • @user1638 I have update the question with another tip, highlighting the relevant code. You are dealing with pointers, which admittedly have not been fully covered at this point in the course. You may want to watch some of the later shorts to understand this more fully. Jul 26 '14 at 13:18

You must log in to answer this question.

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