Since I don't really understand the overall issue I am having, it's become very difficult to debug.
char *o_key_pad = (char*)malloc(SHA256_DIGEST_LENGTH*sizeof(char));
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++){
o_key_pad[i] = 'a';
}
printf("%s\n", o_key_pad);
char *i_key_pad = (char*)malloc(SHA256_DIGEST_LENGTH*sizeof(char));
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++){
i_key_pad[i] = 'b';
}
printf("%s\n", o_key_pad);
printf("%s\n", i_key_pad);
And i obtain outputs:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Why does the array 'o_key_pad' get extended to include whatever i put in array 'i_key_pad', seems like some sort of memory issue?
Note: I understand that it can be done more effectively but to show my point more clearly I have laid it out like this.
printf doesn't know where to stop unless you properly null-terminate your strings. C-style strings are as follows (the following two lines are equivalent; writing a string in quotes [a "string literal"] automatically creates a null-terminated character array):
char str[] = "hello world";
char str2[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0' };
This is what your code should look like:
int i;
char *o_key_pad = malloc(SHA256_DIGEST_LENGTH * sizeof (char) + 1);
for (i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
o_key_pad[i] = 'a';
}
o_key_pad[i] = '\0';
printf("%s\n", o_key_pad);
char *i_key_pad = malloc(SHA256_DIGEST_LENGTH * sizeof (char) + 1);
for (i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
i_key_pad[i] = 'b';
}
i_key_pad[i] = '\0';
printf("%s\n", o_key_pad);
printf("%s\n", i_key_pad);
/* Don't forget to free when done. */
free(o_key_pad);
free(i_key pad);
You have char arrays, but they do not have room for a string terminator, and in fact you do not append one. The contents are not, therefore, proper C strings. When you lie to printf() about that, anything can happen, but in practice, printing beyond the intended bounds of your data is a likely outcome.
If you do not want to add a terminator, then you could put a maximum field width into your format:
printf("%.32s\n", o_key_pad);
, or alternatively
printf("%.*s\n", SHA256_DIGEST_LENGTH, o_key_pad);
if you don't want to hardcode the field width directly into the format.
Your strings are not NULL-terminated, resulting in undefined behavior when passed to printf. You could either allocate one more byte and add a NULL character, or specify a maximum field width for your string.
Related
I'm a beginner in programming so I've been making some mini projects.
I am trying to make a code that takes a string and returns one in which each character is repeated once and I'm getting an error and these signs (╠╠╠╠╠╠╠╠).
Where am I going wrong?
char str[20], fin[40];
int i, j=0;
gets(str);
while (str[j] != '\0'){
j++;
}
for (i = 0; i < j; i++){
fin[i*2-1] = str[i];
fin[i*2] = str[i];
}
printf("%s\n", fin);
return 0;
C does not have strings. Strings, in C, are a convention used by the compiler and the programmer and the Standard Library (and every library ever written). If you break the convention strings no longer "work" even though your code may be correct C code.
Depending on context, a string is a [part of an] array of char that contains a zero byte, or a pointer to such an array, like
char text[3] = {'h', 'i', '\0'}; // text is an array that contains the string "hi"
char *ptr = text; // ptr points to the string "hi"
When you build your string character-by-character, remember the array elements start as garbage
char fin[20]; // fin is an array of 20 characters.
// It is capable of holding string of up to 19 characters length
// and the respective terminator
fin[0] = 'C'; // fin (the whole array) is not a string
fin[1] = '\0'; // fin now is the string "C" with the proper terminator (and a bunch of unused elements
fin[1] = ' '; // replaced the terminator with a space
// fin is no longer a string
fin[2] = 'i';
fin[3] = 's'; // "C is############garbage########..." not a string
fin[4] = ' ';
fin[5] = 'f';
fin[6] = 'u';
fin[7] = 'n'; // "C is fun########garbage########..." not a string
fin[8] = '.'; // "C is fun.#######garbage########..." not a string
fin[9] = '\0'; // "C is fun." <== definitely a string
That's what you need to do. Add a '\0' at the end.
I am new to C, and I am learning shift operation.
I understand the shift operation if the data is a binary number, but for my code in this case, I want to implement the case that 't', 'h', 'i', 's', ' ', '\0' are all discarded or shifted, and move 'a' to the first element of this string.
Can I do this behavior by using shift operator? If so, why is so?
Really appreciated.
char words[10] = {'t', 'h', 'i', 's', ' ', '\0', 'a', 'b', 'c'};
The shift operator you are talking about is basically bitwise operator. You can't use this to shift array of characters.
To accomplish what you asked, you can write a function. Suppose you want left shift -
int leftShift(char *words, int len)
{
int i;
for(i = 1; i < len; i++)
{
words[i - 1] = words[i];
}
len--;
return len;
}
What this function does? - it takes an array and length of that array as parameter, and perform left shift one time.
So then from your main function you can just call this method any number of times you want -
int main(void) {
char words[10] = {'t', 'h', 'i', 's', ' ', '\0', 'a', 'b', 'c'};
int len = 10;
len = leftShift(words, len); // left shift one time - this will discard 't'
len = leftShift(words, len); // left shift one time - this will discard 'h'
//finally print upto len, because len variable holds the new length after discarding two characters.
int i;
for(i = 0; i < len; i++)
{
printf("'%c', ", words[i]);
}
return 0;
}
This is very trivial idea, surely this approach can be improved in many ways. But I think you got the basic idea.
I am working on a Caesar cipher and I am trying to save the characters of my cipher key in an array based on the ascii of the letter is supposed to represent. So if my cipher char key[] = "codezyxwvutsrqpnmlkjihgfba"
The first char in the array (c) is supposed to represent the letter a, whose ascii num is 97. So I want to store c in the array in the 97th spot. Everytime I try to this the array turns out empty.
char key[] = {"codezyxwvutsrqpnmlkjihgfba"};
char alphabet[] = {"abcdefghijklmnopqrstuvwxyz"};
char answerKey[200] = "";
for (int i = 0; key[i] != '\0'; i++) {
answerKey[(int) alphabet[i]] = key[i];
}
for (int i = 0; answerKey[i] != '\0'; i++) {
printf("%c", answerKey[i]);
}
Since the answerkey array has values only in the range of 97 - 122 assuming you are only using lower alphabet the other elements of the arrays are garbage.
Just change the print for loop to iterate from 97 to 122 and you get what you want.
char key[] = {"codezyxwvutsrqpnmlkjihgfba"};
char alphabet[] = {"abcdefghijklmnopqrstuvwxyz"};
char answerKey[200]="";
for (int i = 0; key[i] != '\0'; i++) {
printf("%c",alphabet[i]);
answerKey[(int) alphabet[i]] = key[i];
printf("%c",answerKey[(int)alphabet[i]]);
}
printf("\n");
int i=0;
for (i = 97;i<=122; i++)
{
printf("%c", answerKey[i]);
}
You are starting your printing of the answerKey[] array at the first element and telling it to stop as soon as it hits '\0'. I don't believe answerKey[0] should ever not be '\0' since none of the printable ascii characters are 0. I would expect your answerKey[] array to be empty except between elements 97-122, so if your cipher will be used only for lowercase alphabetical characters, perhaps only look in that part of the array.
Alternatively, you could make your answerKey[] array only hold enough space to fit your cipher by subtracting 'a' from the element address as you're placing it. Something like this might do the trick:
char answerKey[27] = "";
for (int i = 0; key[i] !='\0'; i++) {
answerKey[(int) alphabet[i] - 'a'] = key[i];
}
In C, you can convert a char to an int by simply preforming a cast.
In the memory, when you have a char 'a', the value 97 is saved. When you use a char, it is just the way you understand what is written in the memory. you can just treat this memory as an int, and get the value which is stored over there.
For example:
char c = 'a';
printf("char is %c, int is %d", c, (int)(c));
// Output would be:
// char is a, int is 97
For further information, read: How are different types stored in memory
I want to create a program that prints every possible string starting with the character 'a' with an arbitrary maximum length. For this example we'll use a maximum length of 4. A recursive function seemed like a good way to handle this however I'm really confused now as to why the recursive function won't print for example "ab"? It seems like the loop doesn't continue after recursive is called again.
int main ()
{
char *str = malloc(5* sizeof(char));
str[0] = 'a';
recursive(str, 1);
}
void recursive(char *string, int index)
{
// Max length of 4
if (index > 3)
return;
for(char c = 'a'; c <= 'j'; c++)
{
string[index] = c;
printf("str: %s\n", string);
recursive(string, index + 1);
}
}
While the result is close to what I want, notice that there's no "ab", "ac", "abc", "acb", basically any string of length 2 or 3 (other than aa/aaa). Every combination of length 4 (maximum) is getting printed though.
Any way to solve this? Thanks!
There's nothing wrong with your algorithm or recursion. The only thing you need is to shorten your string after your recursion step finishes (strings are ASCIIZ in C).
The fix is simple: you need to ensure there are zeroes in your allocated memory block, which is done by clearing its contents using memset (memory block whose pointer is returned by malloc contains garbage).
int main ()
{
size_t size = 5;
char* str = (char*)malloc(size);
memset(str, 0, size);
str[0] = 'a';
recursive(str, 1);
}
And then in your loop:
for (char c = 'a'; c <= 'j'; c++)
{
string[index] = c;
printf("str: %s\n", string);
recursive(string, index + 1);
string[index] = 0; // <-- revert last letter to zero
}
I am currently getting a segfault, and I just can't seem to figure out why...
I am making a code that concatenates string values:
char* concat(char** strs, unsigned int nstrs)
{
char* newstring;
int length = 0;
int j;
int charcount;
int strcount;
int k = 0;
for (j = 0; j <= nstrs - 1; j++) {
length = sizeof(strs[j]) + length;
}
newstring = malloc(length);
for (strcount = 0; strcount <= nstrs - 1; strcount++) {
for (charcount = 0; charcount <= strlen(strs[strcount]) - 1; charcount++) {
newstring[k] = strs[charcount][strcount];
k++;
}
}
return newstring;
And in my main function I have...
char* introname[] = {"My", "name", "is", "Trill-o"};
printf("%s\n", concat(introname, 4));
in your code, you need to change
sizeof(strs[j])
to
strlen(strs[j])
Always remember, sizeof is not a function, it's an operator. It returns the size of the supplied data type. In yor code, strs[j] is of type char *, so sizeof will return a value equal to sizeof(char *).
To get the length of the string, you have to use strlen().
That said, please note, strlen() does not include the count for terminating null. So, you've to add space for one more byte while using length in malloc(), like
newstring = malloc(length + 1); // 1 more byte for storing the terminating null.
Also, you must check the return value of malloc() to ensure the success. In case if malloc() fails, it will return NULL and the subsequent usage of newstring will lead to UB.
As per the logical part, your code should read
newstring[k] = strs[strcount][charcount];
and to properly terminate the string,
newstring[k] = '\0' ;
outside for loop.
sizeof(strs[j])
in the function will give sizeof(pointer) not sizeof(array)
But since you have a string use strlen(strs[j]) to get the length of the string.
Please make a note to allocate memory to the \0 character also.
Don't use sizeof to get the length of a string.
You need to use strlen.
sizeof(strs[j]) ; // bad, will return the sizeof pointer which is 4 or 8 depending on the system
strlen(strs[j]); // this is what you want.
Your main problem is here:
length = sizeof(strs[j]) + length;
sizeof does not give the required length of the string as it is a char *, not an array. What you want is strlen(strs[j])).
Also, when you've done totalling the lengths, add one for the terminating NUL before you malloc.
Finally this:
newstring[k] = strs[charcount][strcount];
should be
newstring[k] = strs[strcount][charcount];
Also C strings are null terminated character arrays. Make sure the concatenated string has a \0 at the end. Here is a working version : string concatenation
Note I also switched the indexes of the arrays. I suppose this is what you want.
newstring = malloc(length + 1); // for '\0' character
...
newstring[k] = strs[strcount][charcount];
...
newstring[length] = '\0' ;