user13243126
user13243126

Reputation:

Where did i go wrong with I/O with binary files in C?

I need to encrypt a sentence using the Caesar cipher (its not done yet need to check for xyz and XYZ also), open a binary file and write the encrypted code there. The first argument should be the name of the binary file and choose if i want to add a sentence or show it, also if i input '#' as the first argument it prompts me to input the name of the binary file from which to read the code. It should go like this:

./a.out CODE.DAT >> A >> Kekli kek >> S >> Nhnol nhn >> E.

Now when I do this:

./a.out '#' >> CODE.DAT 

It gives me the correct string up until the last character. Something like

Nhnol nhM�b�U"

Also if there are any bad habits in my code or any suggestions to write cleaner and better code I would be really happy if you would point it out.

Main function:

int main(int argument_count, char **argument_vector) {
    if ((**(argument_vector + 1)) == '#') {
        FILE *stream;
        printf("Name of file: \n");
        char stream_name[15];
        scanf("%s", stream_name);
        if ((stream = fopen(stream_name, "rb")) != NULL) {
            char string[50];
            fread(string, sizeof(char *), 1, stream);
            printf("%s\n", string);
            fclose(stream);
        }
    } else
    if (argument_count == 2) {
        char character;
        do {
            printf("ADD [A], SHOW [S], END [E]\n");
            scanf("\n%c", &character);
            if (character == 'A') {
                FILE *stream;
                char string[50];
                read(string);
                code(string);
                if ((stream = fopen(*(argument_vector + 1), "wb")) != NULL) {
                    fwrite(string, sizeof(char *), 1, stream);
                    fclose(stream);
                }
            } else
            if (character == 'S') {
                FILE *stream;
                if ((stream = fopen(*(argument_vector + 1), "rb")) != NULL) {
                    char string[50];
                    fread(string, sizeof(char *), 1, stream);
                    printf("%s\n", string);
                    fclose(stream);
                }
            }
        } while (character != 'E');
    } else
        return printf("Error"), 1;
}

Code function:

void code(char *string) {
    int i = 0;
    for(; string[i] != '\0'; i++) {
        if ((int)string[i] == 32)
            string[i] = ' ';
        else
            string[i] += 3;
    }
    string[i + 1] = '\0';
}

Read function:

void read(char *string) {
    printf("Input string: \n");
    scanf("\n%[^\n]%*c", string);
}

Upvotes: 1

Views: 72

Answers (1)

Barmar
Barmar

Reputation: 781068

The problem is in this code:

        char string[50];
        fread(string, sizeof(char *), 1, stream);
        printf("%s\n", string);

fread() reads binary data, so it doesn't add a null terminator.

Also, sizeof(char *) is wrong. You're reading a string, not a pointer. But fread() is intended for reading fixed-size data. If you want to read a variable-sized string, you should specify 1 as the size of the object, and up to 49 objects (you need to allow room for the null terminator). fread returns the number of objects that it successfully read, use that to determine where to add the null byte.

        char string[50];
        size_t n = fread(string, 1, 49, stream);
        if (n > 0) {
            string[n] = '\0';
            printf("%s\n", string);
        }

Upvotes: 2

Related Questions