C decryption program - Heap corruption detected - c

I'm trying to write a very simple code.
Basically, I get an "encrypted" string from the user, and my code decrypts it with the following rule:
"From the first letter of the string subtract one, from the second subtract 2, from the third subtract 3 and so on. Spaces stay unchanged"
I wrote this code:
char* q4(char* str_in)
{
char* str_out;
int str_out_length,i,temp;
str_out_length=strlen(str_in)+1; //+1 for null terminator
str_out=(char*)malloc(sizeof(char)*str_out_length);
str_out[str_out_length]='\0'; //null terminator at last index
for(i=0;i<str_out_length;i++)
{
if(str_in[i]!=' ')
{
temp=str_in[i];
str_out[i]=(char)(temp-i-1);
}
else
str_out[i]=str_in[i];
}
return str_out;
}
My code seems to return incorrect output, and not only that, I also have an error that reads "Heap Corruption detected".
For example, when the string i input is Btwlzx Dqqes, the output is Arthur <hgZg<= and an error. Basically the first word is correct. The second one is rubbish. And if I enter just Btwlzx, then the output is Arthur- and said error.
What am I doing wrong?

str_out_length=strlen(str_in)+1; //+1 for null terminator
str_out=(char*)malloc(sizeof(char)*str_out_length);
It seems that the terminator is placed one byte behind the allocated buffer. Try
str_out[str_out_length - 1]='\0';
And similarly, perhaps
for(i=0;i<str_out_length;i++)
should be
for(i=0;i<str_out_length-1;i++)
Or, maybe better, change
str_out_length=strlen(str_in)+1; //+1 for null terminator
str_out=(char*)malloc(sizeof(char)*str_out_length);
with
str_out_length=strlen(str_in);
str_out=(char*)malloc(sizeof(char)*(str_out_length+1)); //+1 for null terminator
and then use str_out_length without -1-correction.
Update (after reading the comment)
print_decrypted("Btwlzx Dqqes Eq|pj2 Tjhvqujs Iqoqjy bpg Eqfxtx Xcwwtt");
outputs
Arthur Conan Doyle, Sherlock Holmes and Doctor Watson
void print_decrypted(char* str)
{
int k = 0;
for (int i = 0; str[i] != '\0'; i++)
if (str[i] != ' ')
{
printf("%c", str[i] - k - 1);
k++;
}
else
{
printf(" ");
k = 0;
}
printf("\n");
}

Related

Why is this still counting spaces within a String?

I'm just starting to code and I need help figuring out why this loop counts spaces within a string.
To my understanding, this code should tell the computer to not count a space "/0" and increase count if the loop goes through the string and it's any other character.
int main(void)
{
string t = get_string("Copy & Past Text\n");
int lettercount = 0;
for (int i = 0; t[i] != '\0'; i++)
{
lettercount++;
}
printf("%i", lettercount);
printf("/n");
}
\0 represents the null character, not a space. It is found at the end of strings to indicate their end. To only check for spaces, add a conditional statement inside the loop.
int main(void)
{
string t = get_string("Copy & Past Text\n");
int lettercount = 0;
for (int i = 0; t[i] != '\0'; i++)
{
if (t[i] != ' ')
lettercount++;
}
printf("%i", lettercount);
printf("\n");
}
Space is considered a character, your code goes through the string (an array of characters) and counts the characters until it reaches the string-terminating character which is '\0'.
Edit: set an if condition in the loop if(t[i] != ' ') and you wouldn't count the spaces anymore.
You misunderstand the nature of C strings.
A string is an array of characters with a low value ( '\0') marking the end of the string. Within the string some of the characters could be spaces (' ' or x20).
So the " t[i] != '\0' " condition marks the end of the loop.
A simple change:
if ( t[i] != ' ') {
lettercount++;
}
Will get your program working.
This for loop
for (int i = 0; t[i] != '\0'; i++)
iterates until the current character is the terminating zero character '\0' that is a null character. So the character is not counted.
In C there is the standard function isalpha declared in the header <ctype.h> that determines whether a character represents a letter.
Pay attention to that the user can for example enter punctuation symbols in a string. Or he can use the tab character '\t' instead of the space character ' '. For example his input can look like "~!##$%^&" where there is no any letter.
So it would be more correctly to write the loop the following way
size_t lettercount = 0;
for ( string s = t; *s; ++s )
{
if ( isalpha( ( unsigned char )*s ) ) ++lettercount;
}
printf("%zu\n", lettercount );
This statement
printf("/n");
shall be removed. I think instead you mean
printf("\n");
that is you want to output the new line character '\n'. But this character can be inserted in the previous call of printf as I showed above
printf("%zu\n", lettercount );
A null-terminator is the last leading element in a character array consisting of a string literal (e.g. Hello there!\0). It terminates a loop and prevent further continuation to read the next element.
And remember, a null-terminator isn't a space character. Both could be represented in the following way:
\0 - null terminator | ' ' - a space
If you want to count the letters except the space, try this:
#include <stdio.h>
#define MAX_LENGTH 100
int main(void) {
char string[MAX_LENGTH];
int letters = 0;
printf("Enter a string: ");
fgets(string, MAX_LENGTH, stdin);
// string[i] in the For loop is equivalent to string[i] != '\0'
// or, go until a null-terminator occurs
for (int i = 0; string[i]; i++)
// if the current iterated char is not a space, then count it
if (string[i] != ' ')
letters++;
// the fgets() reads a newline too (enter key)
letters -= 1;
printf("Total letters without space: %d\n", letters);
return 0;
}
You'll get something like:
Enter a string: Hello world, how are you today?
Total letters without space: 26
If a string literal has no any null-terminator, then it can't be stopped from getting read unless the maximum number of elements are manually given to be read till by the programmer.

which code is better ? and how do we understand that ? why is the final print function in the second code sometimes printing random numbers?

I am very new here .. so please excuse me if my question is really unnecessary .. but I think the answer will help me have some faith in myself ..here are two code snippets ..one i got on the website c4learn.com ..
#include<stdio.h>
int main()
{
char s1[100], s2[100];
int i;
printf("\nEnter the string :");
gets(s1);
i = 0;
while (s1[i] != '\0')
{
s2[i] = s1[i];
i++;
}
s2[i] = '\0';
printf("\nCopied String is %s ", s2);
return (0);
}
and the other i wrote myself ..
#include<stdio.h>
int main()
{
char s1[100], s2[100];
int i;
printf("\n Enter the string 1");
gets(s1);
printf("\n Enter the string2");
gets(s2);
for(i=0;i<100;i++)
{
if (s1[i]!='\0')
{
s2[i]=s1[i];
}
}
s2[i]='\0';
printf("\n Copied string is %s ", s2);
return(0);``
}
the problem is while running the code on dev c++ .. the final printf displayed is showing some random characters at the end of the string .. Can anyone help me understand that and which is code is better ? the initial question was ... HOW WILL YOU COPY ONE STRING TO ANOTHER WITHOUT USING ANY INBUILT LIBRARIES ? thank you ..
Your code is not quite right:
Why do you ask for the user input for s2 if you then overwrite it, copying s1?
The for cycle you wrote doesn't stop when s1 is over (I mean the null terminator character '\0') so you are also copying all the chars remaining in s1 after '\0'. If the chars in the array are not initialized (and that's the case for chars after '\0') they of course might result in random characters.
So answering your question, the first code is the right way to do it.
Any way if you want to use a for cycle you could do:
for (i = 0; i < 100; i++) {
s2[i] = s1[i];
if (s1[i] == '\0')
break;
}
You have to break out of the loop when you reach the null terminator character \0. The first code breaks out of the while loop while you're code continues on until i == 100 skipping over the null character. This is why its printing garbage past the original string.
This is what you should do to break out after the null character.
for (i = 0; i < 100; i++) {
s2[i] = s1[i];
if (s1[i] == '\0') break;
}
In the second block of code, after exiting the for loop, i has a value of 100. So you're putting the 0 byte at index 100.
Since an array of size 100 has indexes 0 to 99, you're writing past the end of the array. That causes undefined behavior.
When you're inside of the for loop, you need to break out after you find the null byte.
Also, both programs use gets which is unsafe because it does not perform any bounds checking and may write past the end of the array.

how to make a string empty in C

I'm using C here.
char a[4], b = 'A';
int k = 0, count = 0;
while true {
if count == 26
break;
if k == 4 {
k = 0;
count++;
b++;
//I want the solution code here.
printf("%s", a);
}
a[k] = b;
k++;
}
I need to know that, If a string in C got assigned completely, is it possible to empty that string again? I can show you my desired output.
AAAABBBBCCCC........ZZZZ
Please help me.
A couple of ways come to mind. Given that strings in C are usually terminated by an ASCII zero, the easiest would be to set the first byte to zero.
a[0] = '\0';
Now this doesn't erase all the characters in the string, but since the first character is now a termination character the string looks empty to your program.
If you want to erase all the characters in the string then you need to use a loop.
OR
Another way might be to use memset() to set the whole string to zeros.
memset(a, 0, strlen(a));
but this will only work for zeroing up to the first NULL character.
In your case, it should suffice to do:
a[0] = '\0';
This sets the first char in the string to be the null terminating character, such that when you print the string, it prints an empty string.
You should also assign the null terminating character to after the effective last character:
a[0] = 'a';
a[1] = 'b';
a[2] = '\0';
printf("%s", a); //print "ab"
You can do
a[0] = '\0';
or
strcpy(a, "");
But your code seem to have a general problem with string termination.
In C a string is terminated (i.e. it ends) with the character '\0' and you code fails to add that termination. You could do:
a[k] = b;
a[k+1] = '\0';
or
if k == 4 {
a[k] = '\0';
If you call printf and the string isn't terminates, you program may crash.
Also notice that char a[4]; should be char a[5]; as you need to store things like "AAAA\0", i.e. 5 characters because you need the 4 A plus a termination.
As you are building 4 letters strings, so you need an array of size 5.
A string must be ended with \0, if not it is not a string, see standard:
7.1.1 Definitions of terms
1 A string is a contiguous sequence of characters terminated by and including the first null character.
You don't need to reset the string as you only print it when it will be correctly filled, you just have to fill it while looping as you did it.
char a[5], b = 'A';
int k = 0, count = 0;
a[5] = '\0'; // mark end of string
while true {
if (count == 26)
break;
if (k == 4) {
k = 0;
count++;
b++;
printf("%s", a);
}
a[k] = b;
k++;
}

Code not working as expected in C

I was working on a program in C to count the number of spaces in a sentence. But I haven't managed to get it to work properly. If I enter something like Hello world 1234 how are you the output I'm getting is 3 when the output expected is 5.
My code is :
//Program to count number of words in a given Sentence
#include <stdio.h>
#include <string.h>
int main()
{
char sent[100];
char sentence[] = {' ', '\0'};
printf("\nEnter a sentence :\n");
gets(sent);
strcat(sentence, sent);
int l = strlen(sentence), i = 0, count = 0, countCh = 0;
printf("%d", l);
char ch, ch1;
for (i = 0; i < (l-1); i++)
{
ch = sentence[i];
if (ch == ' ')
{
ch1 = sentence[i+1];
if (((ch1 >= 'A') && (ch1 <= 'Z'))||((ch1 >= 'a') && (ch1 <= 'z')))
count++;
}
}
printf("\nNo of words is : %d", count);
return 0;
}
I used the same logic in Java and it worked fine. Could someone explain whats going wrong?
The problem in your code is with the definition of sentence. When you leave out the array dimension and initialize it, the size of the array will be determined by the length of the initializer.
Quoting the man page of strcat()
The strcat() function appends the src string to the dest string, overwriting the terminating null byte ('\0') at the end of dest, and then adds a terminating null byte. The strings may not overlap, and the dest string must have enough space for the result. If dest is not large enough, program behavior is unpredictable;
That is, the program will invoke undefined behavior.
This way, sentence has certainly way less memory than it it supposed to hold. Moreover, strcat() is not at all required there.
The correct way to do it will be
Define sentence with a proper dimention, like char sentence[MAXSIZE] = {0};, where MAXSIZE will be a MACRO having the size of your choice.
use fgets() to read the user input.
use isspace() (from ctype.h) in a loop to check for presence of space in the input string.
The following
if (((ch1 >= 'A') && (ch1 <= 'Z'))||((ch1 >= 'a') && (ch1 <= 'z')))
count++;
probably should be
if (ch1 != ' ')
count++;
As now " 12345" would not be counted as word.
Also count counts the spaces, so the word count is one more: hence 3 instead of 5.
Your sentence seems to have had the intention of counting the terminatin NUL.
If you want to count real words containing letters, use a bool state whether current and prior state of being in a letter differ.
As mentioned overflow is possible with your code.

Redundant characters in string, c

I'm trying to get selected characters from one string into another. Everything looks okay, except the program keeps adding additional characters to the output. And it seems that it tends to add different number of these "unecessary" characters. Where might the problem be?
int main(void) {
int i,j=0;
char string[256];
char second_arr[256];
scanf("%255s", string);
for(i=0;i<256;i++){
if(string[i]=='('||string[i]=='['||string[i]=='{'){
second_arr[j]=string[i];
j++;
}
}
printf("%s", second_arr);
}
Say,
input: (hello)(}[} --->
Output:(([[H
Problem 1: You're not testing scanf for failure. It can return EOF, or zero to indicate the input didn't match your format string.
Problem 2: You're copying all 256 chars even if the user entered fewer, which means you're copying junk.
Problem 3: You're not adding a null terminator to second_arr.
Just do this:
if (scanf("%255s", string) != 1)
{
printf("scanf failed\n");
return 1;
}
for (i = 0; i < 256 && string[i]; i++) {
if(string[i]=='('||string[i]=='['||string[i]=='{'){
second_arr[j]=string[i];
j++;
}
}
second_arr[j] = '\0';
printf("%s", second_arr);
return 0;
Try this:
for (i=0; string[i]!=0; i++) // iterate the input string until the null-character
{
if (string[i] == '(' || string[i] == '[' || string[i] == '{')
second_arr[j++] = string[i];
}
second_arr[j] = 0; // set a null-character at the end of the output string
There is nothing to terminate the second string. Add
||string[i]=='\0'
to your conditions. Also break out of the loop when you see that null char, but only after you have copied it.
You should add at the end of second string second_arr the char '\n' to indicate its end.

Resources