I've been trying to solve this exercise for a week now and my code doesn't work and I can't understand why and how to change it. The exercise is: recieving a length from the user, then recieving a string (str) as long as 'length' and then recieving a number (int n) from the user.Then I need to execute the function 'void ReverseNumWords (char*str, int n).The function reverses the first n words in the string. For example: for 'I am your father StarWars' and n=3: 'your am I father StarWars'. It'll be right to assume that the words are separated by ' '. Thanks for the help!!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
void Reverse()
{
int len,num;
char *str;
printf("Please enter how many chars to allocate:\n");
//Asking from the user the length of a string.
scanf("%d", &len);
//Allocating memory for the string.
str = (char*)calloc(len, sizeof(int));
//Making sure the allocation was successful.
if (!str)
printf("Error: Cannot allocate Memory\n");
printf("Allocated %d chars\n", len);
printf("Please enter your string:\n");
scanf("%s", str);
printf("Please enter how many words to reverse:\n");
scanf("%d", &num);
ReverseNumWords(*str, num, len);
free(str);
}
void ReverseNumWords(char*str, int num,int len)
{
char *sub;
char temp;
//Allocating memory for the string.
sub = (char*)calloc(len, sizeof(int));
//Making sure the allocation was successful.
if (!sub)
printf("Error: Cannot allocate Memory\n");
int i, j,l;
i = j = 0;
for (; i < len, j <= num; i++)
if (str[i] == '\0' || str[i] == 0)
j++;
for (l = 0; l < i; l++)
sub[i] = str[i];
for (j = 0; j < i; j++)
temp = sub[j];
sub[j] = sub[i - (1+j)];
sub[i - (1+j)] = sub[j];
reverseWords(*sub);
}
void reverseWords(char *sub)
{
char *word_begin = sub;
char *temp = sub;
while (*temp)
{
temp++;
if (*temp == '\0')
{
reverse(word_begin, temp - 1);
}
else if (*temp == ' ')
{
reverse(word_begin, temp - 1);
word_begin = temp + 1;
}
}
reverse(sub, temp - 1);
}
void reverse(char *begin, char*sub, char *end)
{
char temp;
while (begin < end)
{
temp = *begin;
*begin++ = *end;
*end-- = temp;
}
printf("%s\n", sub);
}
In this line:
str = (char*)calloc(len, sizeof(int));
This needs to be:
str = (char*)calloc(len, sizeof(char));
I also recommend maybe using malloc
to allocate memory for your strings, as you seem to be having trouble using calloc()
.
You would use it like this:
char *str = malloc(len+1); /* Since sizeof(char) is 1, you don't need to include it */
This is also brings up the fact that you Don't need to cast the result of malloc().
It is good to see that your checking the return value of your allocations, that 's always a good thing.
Instead of using scanf()
to read strings from stdin
, you can use fgets
instead.
char *fgets(char *str, int n, FILE *stream)
reads a line from an input stream, and copies the bytes over tochar *str
, which must be given a size ofn
bytes as a threshold of space it can occupy.
Things to note about fgets:
\n
character at the end of buffer. Can be removed easily if you wish.NULL
. If no characters are read, still returns NULL
at the end.n
.stdin
or FILE *
. Here is an example of how it can be used to read a line of input from stdin
:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
You can also use functions like strtok
and strcat
to reverse and concatenate your strings.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *allocate_chars(int *len);
void number_of_words(int *num);
void read_strings(char *str, int len);
char *reversed_words(char *str, int len, int num);
char *reverse_word(char *word);
int main(void) {
int len, num;
char *str, *result;
str = allocate_chars(&len);
read_strings(str, len);
number_of_words(&num);
result = reversed_words(str, len, num);
printf("Reversed string = %s\n", result);
free(result);
free(str);
return 0;
}
char *allocate_chars(int *len) {
char *str;
printf("Enter how many chars to allocate: ");
if (scanf("%d", len) != 1 || *len < 1) {
printf("Invalid length.\n");
exit(EXIT_FAILURE);
}
getchar();
str = malloc(*len+1);
if (!str) {
printf("Cannot allocate %d bytes for string.\n", *len+1);
exit(EXIT_FAILURE);
}
printf("Allocated %d chars.\n", *len+1);
return str;
}
void number_of_words(int *num) {
printf("Please enter how many words to reverse: ");
if (scanf("%d", num) != 1 || *num < 0) {
printf("Invalid number.\n");
exit(EXIT_FAILURE);
}
}
void read_strings(char *str, int len) {
int slen;
printf("Please enter your string: ");
if (fgets(str, len, stdin) == NULL) {
printf("Cannot create buffer.\n");
exit(EXIT_FAILURE);
}
slen = strlen(str);
if (slen > 0) {
if (str[slen-1] == '\n') {
str[slen-1] = '\0';
} else {
printf("Entered string bigger than buffer size of %d bytes.\n", len);
exit(EXIT_FAILURE);
}
}
if (!*str) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
}
char *reversed_words(char *str, int len, int num) {
char *reversed, *word, *reversed_word;
const char *delim = " ";
int count = 1;
reversed = malloc(len+1);
if (!reversed) {
printf("Cannot allocate %d bytes for string.\n", len+1);
exit(EXIT_FAILURE);
}
*reversed = '\0';
word = strtok(str, delim);
while (word != NULL) {
if (count <= num) {
reversed_word = reverse_word(word);
strcat(reversed, reversed_word);
free(reversed_word);
count++;
} else {
strcat(reversed, word);
}
word = strtok(NULL, delim);
if (word != NULL) {
strcat(reversed, delim);
}
}
return reversed;
}
char *reverse_word(char *word) {
char *reverse;
int slen, str_count = 0, i;
slen = strlen(word);
reverse = malloc(slen+1);
if (!reverse) {
printf("Cannot allocate %d bytes for string.\n", slen+1);
exit(EXIT_FAILURE);
}
for (i = slen-1; i >= 0; i--) {
reverse[str_count++] = word[i];
}
reverse[str_count] = '\0';
return reverse;
}
Sample Input:
Enter how many chars to allocate: 50
Allocated 51 chars.
Please enter your string: Hello what a lovely day
Please enter how many words to reverse: 4
Output:
Reversed string = olleH tahw a ylevol day