How do I add space char to string/char array? - c

Here's the overview: I have to make a cipher that can decrypt and encrypt messages(I have completed that), but the reason we have these ciphers are to encrypt/decrypt messages that are sentences which have whitespaces. Basically, I just need to know when there is whitespace, and when there is, to add that whitespace to the final output.
#TL;DR:# How to add whitespace to a String - char output[] ~~~~~~~~~~ that's the String
for(int j = 0; input[j] != '\0'; j++){
int at_index = 0;
int i = 0;
//need to check at this point for whitespace
if(input[j] == ' '){
output[j] = ' ';
}
//gives garbage value
for(i; alphabet[i] != input[j]; i++){
++at_index;
}
output[j] = alphabet[at_index + shift];
}

The error you made is that you don't stop the handling of the character after recognizing the whitespace.
This is one possible solution, derived from your source:
for (int j = 0; input[j] != '\0'; j++) {
if (isspace(input[j])) {
output[j] = input[j];
} else {
for (int i = 0; alphabet[i] != input[j]; i++) {
}
output[j] = alphabet[i + shift];
}
}
Some notes:
at_index is always the same value as i so it's not needed.
You need to add some logic if the input character is not in the alphabet. Since I don't know how your alphabet is defined, I can't show it here.
The for-loop can be replaced by some appropriate string function.
You need some logic to prevent an out-of-bounds access to alphabet when reading the shifted character.

I would call a helper function in order to achieve this,
white_spaces(char *dest, int size, int num_of_spaces) {
int len = strlen(dest);
// for the check i still assume dest tto contain a valid '\0' terminated string, so len will be smaller than size
if( len + num_of_spaces >= size ) {
num_of_spaces = size - len - 1;
}
memset( dest+len, ' ', num_of_spaces );
dest[len + num_of_spaces] = '\0';
}

Related

The program returns some weird and incomplete string

I am trying to write a function that delete whitespaces from a string but the output is not reasonable at all. I need help fam!
Code:
char* deleteSpace(char *String, int n) {
int i;
char* withoutSpaces;
withoutSpaces = calloc(n, sizeof (char));
for (i = 0; i < n - 1; i++) {
if (String[i] == ' ')
withoutSpaces[i] = String[++i];
else
withoutSpaces[i] = String[i];
}
return withoutSpaces;
}
You need to have to indices a "read" index for the source string and a "write" index for the destination.
Also, for better debugability and readability, put the index increment, ++i on a separate line. Oh - it looks like you are incrementing i twice. Once implicitly by the loop and again with the ++i.
Also unclear if n represents the length of the string with or without the null terminator. So let's just let the function deal with figuring that out via strlen.
Don't forget to null terminate the output string.
Several other bugs as well. Here's a version that's improved:
char* deleteSpace(const char *String) {
int j = 0;
const char* ptr = String;
size_t n = 0;
size_t spaces = 0;
char* withoutSpaces = NULL;
// count how many characters we expect to copy over
while (*ptr) {
n += (*ptr == ' ') ? 0 : 1;
ptr++;
}
withoutSpaces = (char*)malloc(n+1); // +1 for null char
for (i = 0; i < n; i++) {
if (String[i] != ' ') {
withoutSpaces[j] = String[i];
j++;
}
}
withoutSpaces[j] = '\0';
return withoutSpaces;
}
Also, if you just want to compact the string in place without allocating a new string.
void deleteSpace(char *String) {
char* ptrWrite = String;
while (*String) {
if (*String != ' ') {
*ptrWrite = *String;
ptrWrite++;
}
String++;
}
*ptrWrite = '\0';
}

Reversing an input string

I am trying to capture a user input string, then display that string in reverse order next to the initial string. My code is as follows:
char str[300], revstring[300];
int i, strlen;
int main(void) {
printf("Enter a string: "); //Prompt user for input string
gets(str);
for (i = 0; str[i] != NULL; i++) { //Get length of string
strlen += 1;
}
for (i = 0; i <= strlen; i++) {
revstring[i] = str[strlen - i];
}
printf("\n\nThe palindrome of your input is %s%s\n\n\n", str, revstring);
return 0;
}
When I run the program however, I see nothing after the initial string. I come from a python background so maybe I am thinking about this in too much of a python mindset, but I feel like this should work.
After this loop
for (i = 0; str[i] != NULL; i++) { //Get length of string
strlen += 1;
}
str[strlen] is equal to the terminating zero '\0'. And the next loop starts from writing this zero in the first element of the array revstring when i is equal to 0.
for (i = 0; i <= strlen; i++) {
revstring[i] = str[strlen - i];
}
As result nothing is displayed.
Also you should not forget to append the result string with the terminating zero.
Take into account that the function gets is unsafe and is not supported any more by the C Standard. It is better to use the standard function fgets. But using it you should remove the appended new line character.
The program can be written the
#include <stdio.h>
#define N 300
int main( void )
{
char str[N], revstring[N];
printf( "Enter a string: " );
fgets( str, N, stdin );
size_t length = 0;
while ( str[length] != '\0' && str[length] != '\n' ) ++length;
if ( str[length] == '\n' ) str[length] = '\0';
size_t i = 0;
for ( ; i != length; i++ ) revstring[i] = str[length - i - 1];
revstring[i] = '\0';
printf("\n\nThe palindrome of your input is %s%s\n\n\n", str, revstring);
return 0;
}
Its output might look like
Enter a string: Hello, Froobyflake
The palindrome of your input is Hello, FroobyflakeekalfyboorF ,olleH
The string is a null-terminated string. You are copying the null character to the beginning of the reversed string. This tells the system that they string is terminated at the first character.
You could use this code instead.
for (i = 0; i < strlen; i++)
{
revstring[i] = str[(strlen - 1) - i];
}
revstring[strlen] = 0;
Here only the characters before the null character are copied and then the null character is added at the end.

Print the longest word of a string

I wrote the following code
#include<stdio.h>
int main(void)
{
int i, max = 0, count = 0, j;
char str[] = "I'm a programmer";
for(i = 0; i < str[i]; i++)
{
if (str[i] != ' ')
count++;
else
{
if (max < count)
{
j = i - count;
max = count;
}
count = 0;
}
}
for(i = j; i < j + max; i++)
printf("%c", str[i]);
return 0;
}
With the intention to find and print the longest word, but does not work when the longest word this in the last as I'm a programmer I printed I'm instead of programmer
How to solve this problem, someone gives me a hand
The terminating condition of your for loop is wrong. It should be:
for(i = 0; i < strlen(str) + 1; i++)
and also, since at the end of string you don't have a ' ', but you have a '\0', you should change:
if (str[i] != ' ')
to:
if (str[i] != ' ' && str[i] != '\0')
The issue should be rather obvious. You only update your longest found word when the character you are inspecting is a space. But there is no space after the longest word in your test string, thus updating code is never exeuted for it.
You can just plop this code after the loop and that should do the trick.
Note however you could have trivially found this by adding mere printfs showing progress of this function.

How do I allocate memory to my char pointer?

My assignment is to allow the user to enter any input and print the occurrences of letters and words, we also have to print out how many one letter, two, three, etc.. letter words are in the string. I have gotten the letter part of my code to work and have revised my word function several times, but still can't get the word finding function to even begin to work. The compiler says the char pointer word is undeclared when it clearly is. Do I have to allocate memory to it and the array of characters?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void findLetters(char *ptr);
void findWords(char *point);
int main()
{
char textStream[100]; //up to 98 characters and '\n\ and '\0'
printf("enter some text\n");
if (fgets(textStream, sizeof (textStream), stdin)) //input up to 99 characters
{
findLetters(textStream);
findWords(textStream);
}
else
{
printf("fgets failed\n");
}
return 0;
}
void findLetters(char *ptr) //find occurences of all letters
{
int upLetters[26];
int loLetters[26];
int i;
int index;
for (i = 0; i < 26; i++) // set array to all zero
{
upLetters[i] = 0;
loLetters[i] = 0;
}
i = 0;
while (ptr[i] != '\0') // loop until prt[i] is '\0'
{
if (ptr[i] >= 'A' && ptr[i] <= 'Z') //stores occurrences of uppercase letters
{
index = ptr[i] - 'A';// subtract 'A' to get index 0-25
upLetters[index]++;//add one
}
if (ptr[i] >= 'a' && ptr[i] <= 'z') //stores occurrences of lowercase letters
{
index = ptr[i] - 'a';//subtract 'a' to get index 0-25
loLetters[index]++;//add one
}
i++;//next character in ptr
}
printf("Number of Occurrences of Uppercase letters\n\n");
for (i = 0; i < 26; i++)//loop through 0 to 25
{
if (upLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'A'), upLetters[i]);
// add 'A' to go from an index back to a character
}
}
printf("\n");
printf("Number of Occurrences of Lowercase letters\n\n");
for (i = 0; i < 26; i++)
{
if (loLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'a'), loLetters[i]);
// add 'a' to go back from an index to a character
}
}
printf("\n");
}
void findWords(char *point)
{
int i = 0;
int k = 0;
int count = 0;
int j = 0;
int space = 0;
int c = 0;
char *word[50];
char word1[50][100];
char* delim = "{ } . , ( ) ";
for (i = 0; i< sizeof(point); i++) //counts # of spaces between words
{
if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
{
space++;
}
}
char *words = strtok(point, delim);
for(;k <= space; k++)
{
word[k] = malloc((words+1) * sizeof(*words));
}
while (words != NULL)
{
printf("%s\n",words);
strcpy(words, word[j++]);
words = strtok(NULL, delim);
}
free(words);
}
This is because you are trying to multiply the pointer position+1 by the size of pointer. Change line 100 to:
word[k] = malloc(strlen(words)+1);
This will solve your compilation problem, but you still have other problems.
You've got a couple of problems in function findWords:
Here,
for (i = 0; i< sizeof(point); i++)
sizeof(point) is the same as sizeof(char*) as point in a char* in the function fincdWords. This is not what you want. Use
for (i = 0; i < strlen(point); i++)
instead. But this might be slow as strlen will be called in every iteration. So I suggest
int len = strlen(point);
for (i = 0; i < len; i++)
The same problem lies here too:
word[k] = malloc((words+1) * sizeof(*words));
It doesn't makes sense what you are trying with (words+1). I think you want
word[k] = malloc( strlen(words) + 1 ); //+1 for the NUL-terminator
You got the arguments all mixed up:
strcpy(words, word[j++]);
You actually wanted
strcpy(word[j++], words);
which copies the contents of words to word[j++].
Here:
free(words);
words was never allocated memory. Since you free a pointer that has not been returned by malloc/calloc/realloc, the code exhibits Undefined Behavior. So, remove that.
You allocated memory for each element of word. So free it using
for(k = 0; k <= space; k++)
{
free(word[k]);
}
Your calculation of the pointer position+1 is wrong. If you want the compilation problem will go away change line 100 to:
word[k] = malloc( 1 + strlen(words));

Displaying wrong character in C

I'm testing deciphering strings using a key in standard C. I'm inputting a string, inputting my replacements and constructing a cipher based on the history of my replacements. For example, if I replace c with h in a string, I will store it in the string cipher as "ch ", where " denotes the start and end of my string.
My problem is, as I'm trying to run back through my string and revert characters back to their originals, my characters are messing up and showing as heart signs instead. Any insight on this would be much appreciated, I'm sure I'm going wrong somewhere very simple.
char from[] = "";
char to[] = "";
for (int i = 0; i <= strlen(cipher); i++){
if (i == 0){
from[strlen(from)] = cipher[i];
}
else if(cipher[i-1] == ' '){
from[strlen(from)] = cipher[i];
}
else{
to[strlen(to)] = cipher[i];
}
}
for (int i = 0; i <= strlen(str); i++){
for(int j = 0; j <= strlen(to); j++){
if(str[i] == to[j]){
str[i] = from[j];
}
}
}
printf("\nUNSCRAMBLED STRING IS: %s" ,str);
cipher is the char array holding my cipher key. to[] hold the second value in the cipher key. from[] holds my first. str is the char array of the string that is to be deciphered.
You have a number of problems.
(1) One big problem is that you don't have enough storage allocated for from and to - change:
char from[] = ""; // this is equivalent to char from[1] = "";
char to[] = "";
to e.g.:
char from[256] = "";
char to[256] = "";
(where 256 is just some arbitrary size that should be greater than the size of your data set).
(2) You need to terminate your strings properly when you append a character, e.g.
if (i == 0){
from[strlen(from)] = cipher[i];
}
should be:
if (i == 0){
int len = strlen(from);
from[len] = cipher[i];
from[len + 1] = '\0';
}
(3) You're indexing by one too many characters when you iterate through a string, so e.g.
for (int i = 0; i <= strlen(cipher); i++){
should be:
for (int i = 0; i < strlen(cipher); i++){

Resources