2

I have a program here where I'm trying to decode a string of letters using a ceasar cipher; essentially I'm moving each character in the string "down" a letter ("a" -> "b", "f" -> "g", "z" -> "a").

The amount that I move a letter down depends on the key I give it.

In this specific program, I have a secret coded message hardcoded into the main() function, and a for loop iterating through each possible key.

The idea is that if this secret message is simply shifted downward by x amount of letters, spitting out 25 versions of the cipher will reveal an intelligible answer.

Unfortunately I'm using some concepts that are new to me - argc, argv, and multiple functions in one program. I am very new to this.

Can someone help explain the segmentation fault error I'm getting? I don't think I'm causing any overflows on arguments.

#include <stdio.h>
#include <cs50.h>
#include <string.h>

string decode(int key, string message);

int main(void)
{
    string secret_message = "ueuag rKJ AGIQ GIAR FEgN";

    for (int i = 0; i < 25; i++)
    {
        decode(i, secret_message);
        printf("%s", secret_message);
    }

    return 0;
}

string decode(int key, string message)
{
    int i;

    for (i = 0; i < strlen(message); i++)
    {
        if (message[i] >= 'a' && message[i] <= 'z')
        {
            message[i] = ((message[i] - 97 + key) % 26) + 97;
        }
        else if (message[i] >= 'A' && message[i] <= 'Z')
        {
            message[i] = ((message[i] - 65 + key) % 26) + 65;
        }
    }

    return message;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
David Maness
  • 91
  • 12
  • This `for (i = 0; i < strlen(message); i++)` is expensive, `strlen()` too loops through the `message` pointer. – Iharob Al Asimi Feb 13 '16 at 00:54
  • 2
    Not knowing its definition, I guess passing `string` directly to `printf` isn't good. – MikeCAT Feb 13 '16 at 00:55
  • Which language are you using, C or C++? What is `string`? – aschepler Feb 13 '16 at 00:55
  • 1
    What is `string`??? Where is it declared? And to avoid unnecessary confusion with `std::string` I'd remove [C++] tag from this. This is not C++.. – AnT stands with Russia Feb 13 '16 at 00:57
  • 1
    It looks like `string` is a typedef of `char*` from [`cs50.h`](http://dkui3cmikz357.cloudfront.net/library50/c/cs50-library-c-3.0/cs50.h), a _popular_ library for a Computer Science course. – rodrigo Feb 13 '16 at 00:59
  • 5
    Wow.. that's a really bad idea when trying to teach people C. – David Hoelzer Feb 13 '16 at 00:59
  • 1
    @rodrigo: In that case [C++] tag has no business being here. – AnT stands with Russia Feb 13 '16 at 00:59
  • It's [tag:c] and `string` is defined as `char *` in *cs50.h*! – Iharob Al Asimi Feb 13 '16 at 01:00
  • Alright guys, tags changed accordingly, and like rogrigo said I'm using a library or two from CS50. I'm well aware I won't be using "string" in the "real world", so I've change it to char *variable_name and I'm still having the same problem. Should I change my code in OP, or is that... uncouth? – David Maness Feb 13 '16 at 01:04
  • @DavidHoelzer And it's really common actually. It causes infinite confusion, and as you all could see the OP tagged as [tag:c++] which make it even more confusing. – Iharob Al Asimi Feb 13 '16 at 01:09

1 Answers1

7

Why is string a bad idea for a type in ?, here you can see an example. You are modifying a string literal and you shouldn't. Doing it invokes undefined behavior. Instead of having a string type you should treat strings as what they are in .

Instead do it like this

char secret_message[] = "ueuag rKJ AGIQ GIAR FEgN";

And the decode function

char *decode(int key, char *message)
{
    int i;

    for (i = 0; message[i] != '\0'; i++)
    {
        if (message[i] >= 'a' && message[i] <= 'z')
        {
            message[i] = ((message[i] - 97 + key) % 26) + 97;
        }
        else if (message[i] >= 'A' && message[i] <= 'Z')
        {
            message[i] = ((message[i] - 65 + key) % 26) + 65;
        }
    }

    return message;
}

As you can see I am treating the string as an array because that's what it is, an array of bytes with a '\0' at the end. If you knew this you would never do something like typedef char * string because it's very misleading.

In cs50.h string is a typedef for a char pointer, and a pointer is not a string, a string is a sequence of bytes and a char * pointer can point to an array of char which could be a string if you define it and initialize it correctly. But a char * pointer could point to a string literal, and you can't alter them which is not clear if you define it as

string string_literal = "Do not attempt to modify me, it's undefined behavior";

When declaring a pointer to a string literal you should use const char * to avoid accidentaly trying to modify it.

Also, typedefing pointers in my opinion has no benefit at all and causes a lot of confusion, a pointer is a pointer and must have a * near it's identifier when declared, if you remove the need for a * you can easily overlook pointers in the code and be confused.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Thanks for your informative comment. I've changed all to and have the same problem – David Maness Feb 13 '16 at 01:05
  • 1
    @DavidManess Please keep reading as I update the answer, see my suggestion -> "*You can't overwrite a string literal*". – Iharob Al Asimi Feb 13 '16 at 01:06
  • 1
    @DavidManess Changing `string` to `char*` won't help, because `string` is a typedef to `char*` already. You need to declare your `secret_message` as a `char[]`, not a `char*` (or `string`), then the program will work. – Paul Feb 13 '16 at 01:09
  • @Paul and adding to your comment, you can initialize an array with a string literal, it would create a copy of the string literal that you can actually modify. – Iharob Al Asimi Feb 13 '16 at 01:11
  • @Paul thanks, that worked. iharob thank you for your time and explanations. – David Maness Feb 13 '16 at 01:14
  • @iharob you were a great help so thanks for teaching me that about chars and strings – David Maness Feb 13 '16 at 01:15
  • @DavidManess Don't try to understand working with C strings (and pointers in general) by example. Read a good book that will explain it fundamentally (like the difference between `char[]` and `char*`, etc.). – Paul Feb 13 '16 at 01:15
  • @Paul I try to do as much googling as possible about new concepts I learn about. I'm taking a CS50x course (free) and unfortunately a book on C is a little bit out of my budget right now. I'll try and read more about it. – David Maness Feb 13 '16 at 01:17