-1

Hello I am working on a Caesar encryption program. Right now it takes as an input the file with the message to encrypt, the key

The input is currently in this format:

"text.txt", "ccc"

I need to convert this into taking a number so that it fits my requirements, so something like this:

"text.txt", "3"

Then i need to convert this "3" back into "ccc" so that the program still works. The logic being that 3 translates to the third letter of the alphabet "c", and is repeated 3 times. Another example would be if the key entered is "2", it should return "bb".

This is what i have so far but its giving me a lot of warnings and the function does not work correctly.

#include <stdio.h>
void number_to_alphabet_string(int n) {
 char buffer[n];
 char *str;
 str = malloc(256);
 char arr[8];
 for(int i = 0; i < n; i++) {
 buffer[i] = n + 64;
 //check ASCII table the difference is fixed to 64
 arr[i] = buffer[i];
 strcat(str, arr);
 }
 printf(str);
}
int main(int argc, char *argv[]) {
 const char *pt_path = argv[1]; //text.txt
 char *key = argv[2]; //3
 number_to_alphabet_string((int)key); //should change '3' to 'CCC'
}
Oka
27.1k7 gold badges51 silver badges59 bronze badges
asked Apr 25, 2022 at 23:13
2
  • 1
    "not working" is never a good problem description. Please give the exact input, expected result and actual result. More importantly, now would be a good time to learn to debug your own code. Run your code in a debugger and trace its flow and variable values as it runs. What is a debugger and how can it help me diagnose problems? Commented Apr 25, 2022 at 23:20
  • Ive tried for a few hours to run a debugger, but i cant figure out how in C. Watched a few videos and installed everything but it doesnt work Commented Apr 25, 2022 at 23:44

3 Answers 3

0

Your problem is that you have a function

void number_to_alphabet_string(int n) 

that takes an int but you call it with a char*

char* key = argv[2]; //3
number_to_alphabet_string(key);

My compiler says

1>C:\work\ConsoleApplication3\ConsoleApplication3.cpp(47,34): warning C4047: 'function': 'int' differs in levels of indirection from 'char *'

You need

char* key = argv[2]; //3
number_to_alphabet_string(atoi(key));

to convert that string to a number

Asleepace
3,7652 gold badges28 silver badges40 bronze badges
answered Apr 25, 2022 at 23:27
Sign up to request clarification or add additional context in comments.

1 Comment

Oh yes you are correct, i was trying it with type casting to an int but that works too. Still get a bunch of warning though and an incorrect ouput
0

With char *key = argv[2];, the cast (int) key does not reinterpret the contents of that string as a valid integer. What that cast does is take the pointer value of key, and interprets that as an integer. The result of this is implementation-defined, or undefined if the result cannot be represented in the integer type (a likely outcome if sizeof (int) < sizeof (char *)).

The C standard does not define any meaning for these values.

Here is a test program that, depending on your platform, should give you an idea of what is happening (or failing to happen)

#include <stdio.h>
int main(int argc, char **argv) {
 if (sizeof (long long) >= sizeof (char *))
 printf("Address %p as an integer: %lld (%llx)\n",
 (void *) argv[0],
 (long long) argv[0],
 (long long) argv[0]);
}

As an example of implementation-defined behaviour, on my system this prints something like

Address 0x7ffee6ffdb70 as an integer: 140732773948272 (7ffee6ffdb70)

On my system, casting that same pointer value to (int) results in undefined behaviour.

Note that intptr_t and uintptr_t are the proper types for treating a pointer value as an integer, but these types are optional.


To actually convert a string to an integer, you can use functions such as atoi, strtol, or sscanf. Each of these have their pros and cons, and different ways of handling / reporting bad input.

Examples without error handling:

int three = atoi("3");
long four = strtol("4", NULL, 10);
long long five;
sscanf("5", "%lld", &five);

number_to_alphabet_string has a few problems.

malloc can fail, returning NULL. You should be prepared to handle this event.

In the event malloc succeeds, the contents of its memory are indeterminate. This means that you need to initialize (at least partially) the memory before passing it to a function like strcat, which expects a proper null terminated string. As is, strcat(str, arr); will result in undefined behaviour.

Additionally, memory allocated by malloc should be deallocated with free when you are done using it, otherwise you will create memory leaks.

char *foo = malloc(32);
if (foo) {
 foo[0] = '0円';
 strcat(foo, "bar");
 puts(foo);
 free(foo);
}

In general, strcat and the additional buffers are unnecessary. The use of char arr[8]; in particular is unsafe, as arr[i] = buffer[i]; can easily access the array out-of-bounds if n is large enough.

Additionally, in strcat(str, arr);, arr is also never null terminated (more UB).

Note also that printf(str); is generally unsafe. If str contains format specifiers, you will again invoke undefined behaviour when the matching arguments are not provided. Use printf("%s", str), or perhaps puts(str).


As far as I can tell, you simply want to translate your integer value n into the uppercase character it would be associated with if A=1, B=2, ... and repeat it n times.

To start, there is no need for buffers of any kind.

void number_to_alphabet_string(int n) {
 if (1 > n || n > 26)
 return;
 for (int i = 0; i < n; i++)
 putchar('A' + n - 1);
 putchar('\n');
}

When passed 5, this will print EEEEE.

If you want to create a string, ensure there is an additional byte for the terminating character, and that it is set. calloc can be used to zero out the buffer during allocation, effectively null terminating it.

void number_to_alphabet_string(int n) {
 if (1 > n || n > 26)
 return;
 char *str = calloc(n + 1, 1);
 if (str) {
 for (int i = 0; i < n; i++)
 str[i] = 'A' + n - 1;
 puts(str);
 free(str);
 }
}

Note that dynamic memory is not actually needed. char str[27] = { 0 }; would suffice as a buffer for the duration of the function.

A cursory main for either of these:

#include <stdio.h>
#include <stdlib.h>
void number_to_alphabet_string(int n);
int main(int argc, char *argv[]) {
 if (argc > 1)
 number_to_alphabet_string(atoi(argv[1]));
}

Note that with an invalid string, atoi simply returns 0, which is indistinguishable from a valid "0" - a sometimes unfavourable behaviour.

answered Apr 26, 2022 at 3:10

Comments

0
  1. You can't use a cast to cast from a char array to an int, you have to use functions, such as atoi().
  2. You never free your str after you allocate it. You should use free(str) when you no longer need it. Otherwise, it will cause a memory leak, which means the memory that you malloc() will always be occupied until your process dies. C doesn't have garbage collection, so you have to do it yourself.
  3. Don't write things such as char buffer[n];, it can pass the compile of GCC, but it can't in MSVC. And that isn't the stander way of declaring an array with variable length. use
char* buffer = malloc(n);
//don't forget to free() in order to avoid a memory leak
free(buffer);
answered Apr 26, 2022 at 2:01

1 Comment

In C, it is advisable to not cast the return of malloc. See: Do I cast the result of malloc?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.