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'
}
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
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.
You can't use a cast to cast from a char array to an int, you have to use functions, such as atoi().
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.
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);
Related
I am trying to add integers to a string. When I debug my code everything works perfectly fine, but when i run it normally two unwanted characters are being printed at the beginning of the string. How do I avoid this?
int number_of_ints = 5;
char s[number_of_ints*2];
char suffix[4];
for(int i = 1; i <= number_of_ints; i++){
snprintf(suffix, number_of_ints, "%d*", i);
strncat(s, suffix, 2);
printf("%s\n", s);
}
This is the output when building and running the code normally.
`û1*
`û1*2*
`û1*2*3*
`û1*2*3*4*
`û1*2*3*4*5*
Strings in C are a sequence of nonzero bytes followed by a terminating byte with a value of zero (the null-terminating byte, '\0').
You must size your buffer to have an additional space, to guarantee room for this null-terminating byte.
You must additionally make sure the contents of the buffer contain a valid string. You can do this by setting the first element of the buffer to the null-terminating byte, creating a zero-length string.
Failing to initialize the contents of your buffer means it will contain indeterminate values, and passing such a buffer to a function expecting a valid string will invoke Undefined Behavior.
The second argument to snprintf should be, at most, the size of the destination buffer.
Finally, consider using size_t when applicable, as it is the appropriate type for dealing with memory sizes (e.g., sizing variable-length arrays; the sizeof operator resolves to this type; snprintf expects this type as its second argument).
#include <stdio.h>
#include <string.h>
int main(void) {
size_t number_of_ints = 5;
char s[number_of_ints * 2 + 1];
char suffix[4];
s[0] = '\0';
for (size_t i = 1; i <= number_of_ints; i++) {
snprintf(suffix, sizeof suffix, "%zu*", i);
strncat(s, suffix, 2);
printf("%s\n", s);
}
}
You have a few issues with initialization and size of your buffers.
The size of your buffer is too short by 1 byte that is needed for 0-termination. Adding the last number causes buffer overrun and undefined behaviour.
In addition the calculated size is only sufficient as long as number_of_ints<10 because it only allows for single digit numbers.
That buffer is not initialized and us very likely not holding an empty string. Accessing it (via strcat etc.) invokes undefined behaviour.
The size you provide to snprintf is not related to the size of the buffer.
You should apply these changes:
#include <stdio.h>
#include <string.h>
int main(void)
{
int number_of_ints = 5;
char s[number_of_ints*2+1];
char suffix[4];
s[0] = 0;
for (int i = 1; i <= number_of_ints; i++)
{
snprintf(suffix, sizeof(suffix), "%d*", i);
strncat(s, suffix, 2);
printf("%s\n", s);
}
}
I am trying to read argv[1] starting from the second character until the end of the string in argv[1] (ignoring the first character, which is a flag). How can I do this?
I tried some library functions and other ways such as storing it in a variable such as
char *variable = strncpy(argv[1][1], strlen(argv[1]))
but it didn't work.
You are running up against two fundamental misconceptions regarding variables and pointers in C.
Let's start with:
char *variable = strncpy(argv[1][1], strlen(argv[1]))
The biggest problem (aside from the improper use of strncpy) is you attempt to assign the return of strncpy to char *variable where char *variable is a pointer-to-char that is uninitialized and points to no valid storage. Your attempt to assign the return fails because the proper prototype for strncpy is:
char *strncpy(char *dest, const char *src, size_t n);
(note: the dest parameter. The destination must have adequate storage to accept n characters. **further note:** if there is nonull byte` among the first n bytes of src, the array of bytes placed in dest will not be a null-terminated string.)
Now either by cleverness or happy-circumstance using the strlen of the complete argv[1] to allocate storage for dest and copying from argv[1] + 1 does provide space for the null byte.
Your next misconception is using argv[1][1] in strncpy. argv[1][1] has type char, not char*. (though your could use &argv[1][1] to use the address of argv[1][1] -- but not as you have it above.
argv[1] is a pointer of type char *. Being a pointer-to-char, if you want to skip one char, you want to read from the address pointer + 1 (or argv[1] + 1 in this case). Now it may make things easier to understand if you declare a separate pointer, e.g. char *p = argv[1]; and then use p + 1, but it is the same thing.
Putting that together, it looks like you intended:
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv) {
if (argc < 2)
return 1;
size_t len = strlen (argv[1]);
char variable[len];
strcpy (variable, argv[1] + 1);
printf ("variable : %s\n", variable);
return 0;
}
Where with your example argument of +name, you would get:
Example Use/Output
$ ./bin/argv1plus1 +name
variable : name
For sake of completeness, if your compiler does not support use of a Variable Length Array (VLA) as used in char variable[len]; above, then your options are to declare variable as a fixed size array and validate that strlen(argv[1]) has no more characters than your fixed size, or, you simply allocate storage for variable dynamically by calling malloc (or calloc or realloc). A short example using malloc would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
if (argc < 2)
return 1;
size_t len = strlen (argv[1]);
char *variable = malloc (len); /* allocate a block of memory len chars long */
if (variable == NULL) { /* always validate malloc succeeded */
perror ("malloc failure");
exit (EXIT_FAILURE);
}
strcpy (variable, argv[1] + 1);
printf ("variable : %s\n", variable);
free (variable); /* don't forget to free the memory you allocate */
return 0;
}
(same example & output)
Look things over and let me know if you have further questions.
I'm writing a program that takes in a string as input e.g. 35x40x12. I want to then store the numbers as separate elements using an int pointer. So far I've managed to do this so that single digit numbers work, i.e. 3x4x6 works, however if I put in two digit numbers such as 35x40x12, the 35 will be stored in the first position, however in the second position it will also store the 5 from 35, it does this for positions 3 and 4 with regard to 40 as well. How do I remove this duplication?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int present(int l, int w, int h);
int *stringC (char *z);
int main(int argc, char *argv[])
{
char *d = "53x23x4";//input
printf("%d", *(stringC(d)+2));//whatever's stored in pointer position
return 0;
}
int *stringC (char *z)
{
int i;
int *k = malloc(sizeof(int)*20);
int j = 0;
for(i=0; z[i] !='\0';i++)
{
if( z[i]!= 'x')
{
k[j]=atoi(&z[i]);
j++;}
}
return k;
}
As others have suggested, learn to debug. It's going to be worth it!
Have a look at strtok. From man strtok:
The strtok() function parses a string into a sequence of tokens.
These tokens are divided by delimiters like "x". So, in order to parse the numbers, use something like this:
char d[] = "53x23x4";
int array[3];
char* it = strtok(d, "x");
for (size_t i = 0; i < sizeof(array) / sizeof(*array) && it; ++i, it = strtok(NULL, "x"))
array[i] = atoi(it);
Note that d points to an automatic and writable string. strtok modifies a string's content and since string literal modification yields undefined behavior, you need to allocate the string at a writable location.
Instead of array use some dynamic memory allocation mechanism and you have it. This spares you from this inconvenient hassle you're currently using.
Notes:
stop using char* to point to string literals. Use const char* instead. This prevents subtle errors where you try to modify string literals (undefined behavior).
I'm currently trying to make a program in c which will return a pointer to an array of 2 strings. The first is the characters of the string s that are in the odd position and the second are the characters in the even position. I'm not experienced in C so I need a bit of help with this program. I've been trying to code using what I know from python and java but it doesn't seem to follow the same principles with pointers. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **parity_strings(const char *s){
char dest[malloc((char)sizeof(s)/2 + 1)][malloc((char)sizeof(s)/2 + 1)]; //trying to allocate memory to an array of size 2 which will hold 2 strings.
int i;
for(i = 0; i < sizeof(s); i+= 2){ //iterating through odd strings
s[0] += dest[i];
}
for(i= 2; i< sizeof(s); i += 2){ //iterating through even strings (I suppose i could have just appended using 1 for loop but oh well
s[1] += dest[i];
}
return dest;
}
int main(int argc, char **argv) {
char **r = parity_strings(argv[1]);
printf("%s %s %s\n", r[0], r[1], argv[1]);
return 0;
}
memory allocation is just a pain too...I have no clue if it's doing what I intend on it doing. I'm trying to allocate the size of the string in bytes + 1 byte into each index of the array Dest.
any ideas on how to fix this? Thanks.
This line will not do anything good:
char dest[malloc((char)sizeof(s)/2 + 1)][malloc((char)sizeof(s)/2 + 1)];
malloc returns a pointer to the newly allocated memory. In your line above, the square brackets in dest[][] need unsigned integers. Pointers can be casted to integers, but that isn’t what you want there at all. It might compile, but it probably won’t run, and certainly won’t do what you want.
Also, sizeof(s) returns the size of the pointer to s, not the length of the string. Strings in C are really just null-terminated arrays of chars, and arrays are passed to functions with a pointer, not their entire contents. To get the length of a string, use strlen(s) instead.
You could do something like this:
char *destodd = malloc((strlen(s)/2 + 2));
char *desteven = malloc((strlen(s)/2 + 2));
char **dest = malloc(sizeof(char *) * 2);
dest[0] = desteven;
dest[1] = destodd;
I changed your + 1 above to +2. A string of length 3 needs 3 characters in destodd: one for character 1, one for character 3, and one for the NUL terminator.
It’s tricky to malloc a multi-dimensional array in C. A one-dimensional array, on the other hand, is easy. Just treat destodd and desteven like they’re arrays, even though they’re really pointers:
for (i = 0; i < strlen(s); i += 2){
desteven[i] = 'a'; // Fix this
destodd[i] = 'b';
}
The code in your for loops didn’t look like it would work. It looks like you may have been trying to use += to concatenate strings, but it only does addition of numbers. I couldn’t quickly figure out what you should set in the for loop, so 'a' and 'b' are just placeholders.
You have a few issues. As your compiler should tell you, char dest[malloc()] requires a pointer-to-unsigned cast, which is legal but is not what you want. More importantly, returning a pointer to an array allocated on the stack results in undefined behavior if you dereference the pointer, because the compiler may have already deallocated the memory. I'm not exactly sure what the intended output of the function is, but in terms of filling two char arrays, in my opinion the easiest way to do it is this:
char **parity_strings(char* buf) //Please avoid single letter variable names for anything but loop control
{
size_t buflen = strlen(buf);
if (NULL == char** dest = malloc(2 * sizeof(*dest)))
;//handle memory allocation error
if (NULL == dest[0] = malloc(buflen * sizeof(*buf)))
;//handle memory allocation error
if (NULL == dest[1] = malloc(buflen * sizeof(*buf)))
;//handle memory allocation error
//Note that you would do the above two lines in a loop for a variable sized multidimensional array
strncpy(dest[0], buf, 500);
strncpy(dest[1], buf, 500); //If you need strings larger than 500 change as necessary, mostly only needed if you are taking input from someone else but it's good practice to use strncpy over strcpy)
return dest;
}
#include <stdio.h>
int main ()
{
char *ptr = "stackoverflow"
}
Is there any way to find the length of stackoverflow pointed by ptr, as sizeof ptr always gives 4
Use strlen to find the length of (number of characters in) a string
const char *ptr = "stackoverflow";
size_t length = strlen(ptr);
Another minor point, note that ptr is a string literal (a pointer to const memory which cannot be modified). Its better practice to declare it as const to show this.
sizeof() returns the size required by the type. Since the type you pass to sizeof in this case is a pointer, it will return size of the pointer.
If you need the size of the data pointed by a pointer you will have to remember it by storing it explicitly.
sizeof() works at compile time. so, sizeof(ptr) will return 4 or 8 bytes typically. Instead use strlen.
The strlen() function provided by string.h gives you how many "real characters" the string pointed by the argument contains. However, this length does not include the terminating null character '\0'; you have to consider it if you need the length to allocate memory.
That 4 bytes is the size of a pointer to char on your platform.
#include<stdio.h>
main()
{
int mystrlen(char *);
char str[100];
char *p;
p=str;
printf("Enter the string..?\n");
scanf("%s",p);
int x=mystrlen(p);
printf("Length of string is=%d\n",x);
}
int mystrlen(char *p)
{
int c=0;
while(*p!='\0')
{
c++;
*p++;
}
return(c);
}
simple code to understand
You are looking for the strlen() function.
You can try using:
char *ptr = "stackoverflow"
size_t len = strlen(ptr);
if ptr length is an argument of a function it's reasonable to use pointers as a strings. we can get string length by following code:
char *ptr = "stackoverflow";
length=strlen((const char *)ptr);
And for more explanation, if string is an input string by user with variable length, we can use following code:
unsigned char *ptr;
ptr=(unsigned char *)calloc(50, sizeof(unsigned char));
scanf("%s",ptr );
length=strlen((const char *)ptr);
Purely using pointers you can use pointer arithmetic:
int strLen(char *s)
{
int *p = s;
while(*p !=’\0’)
{
p++; /* increase the address until the end */
}
Return p – s; /* Subtract the two addresses, end - start */
}
Even though this is a generic C question, it gets pretty high hits when looking this question up for C++. Not only was I in C/C++ territory, I also had to be mindful of Microsoft's Security Development Lifecycle (SDL) Banned Function Calls for a specific project which made strlen a no-go due to,
For critical applications, such as those accepting anonymous Internet connections, strlen must also be replaced...
Anyway, this answer is basically just a twist on the answers from the others but with approved Microsoft C++ alternative function calls and considerations for wide-character handling in respect to C99's updated limit of 65,535 bytes.
#include <iostream>
#include <Windows.h>
int wmain()
{
// 1 byte per char, 65535 byte limit per C99 updated standard
// https://stackoverflow.com/a/5351964/3543437
const size_t ASCII_ARRAY_SAFE_SIZE_LIMIT = 65535;
// Theoretical UTF-8 upper byte limit of 6; can typically use 16383 for 4 bytes per char instead:
// https://stijndewitt.com/2014/08/09/max-bytes-in-a-utf-8-char/
const size_t UNICODE_ARRAY_SAFE_SIZE_LIMIT = 10922;
char ascii_array[] = "ACSCII stuff like ABCD1234.";
wchar_t unicode_array[] = L"Unicode stuff like → ∞ ∑ Σὲ γνωρίζω τὴν ደሀ ᚦᚫᛏ.";
char * ascii_array_ptr = &ascii_array[0];
wchar_t * unicode_array_ptr = &unicode_array[0];
std::cout << "The string length of the char array is: " << strnlen_s(ascii_array_ptr, ASCII_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
std::wcout << L"The string length of the wchar_t array is: " << wcsnlen_s(unicode_array_ptr, UNICODE_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
return 0;
}
Output:
The string length of the char array is: 27
The string length of the wchar_t array is: 47
strlen() gives you the exact length of the string [excluding '\0']
sizeof() gives you the size of the data type used.
// stackoverflow = 13 Characters
const char* ptr = "stackoverflow";
strlen(ptr); // 13 bytes - exact size (NOT includes '\0')
sizeof(ptr); // 4 bytes - Size of integer pointer used by the platform
sizeof(*ptr); // 1 byte - Size of char data type
strlen("stackoverflow"); // 13 bytes - exact size
sizeof("stackoverflow"); // 14 bytes - includes '\0'
#include<stdio.h>
int main() {
char *pt = "String of pointer";
int i = 0;
while (*pt != '\0') {
i++;
pt++;
}
printf("Length of String : %d", i);
return 0;
}
We can also use strlen() function or sizeof() operator which is builtin in C.
We can also take help of pointer arithmetic as above example.