The challenge
Reverse every other word in a given string, then return the string. Throw away any leading or trailing whitespace, while ensuring there is exactly one space between each word. Punctuation marks should be treated as if they are a part of the word in this challenge.
The solution in C
Option 1:
#include <stddef.h>
#include <stdbool.h>
void reverse_alternate(const char *string, char *result)
{
bool is_word = false, is_second = false, not_first = false;
for (const char *s = string; *s; ++s) {
if (*s == ' ' && is_word) {
is_word = false;
is_second = !is_second;
} else if (*s != ' ' && !is_word) {
if (not_first) *result++ = ' ';
is_word = not_first = true;
}
if (is_second && is_word) {
size_t i = 0;
for (const char *ss = s; *ss && *ss != ' '; ++ss, ++i)
;
for (size_t j = 0; j < i; ++j)
result[j] = s[i - j - 1];
s += i - 1;
result += i;
} else if (*s != ' ')
*result++ = *s;
}
*result = '\0';
}
Option 2:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
extern char *strdup (const char *);
char *strrev (char *string)
{
size_t length = strlen(string);
for (size_t i = 0; i < length / 2; i++) {
char tmp = string[i];
string[i] = string[length - 1 - i];
string[length - 1 - i] = tmp;
}
return string;
}
void reverse_alternate(const char *string, char *result)
{
static const char *const whitespace = " \t\n\r\v\f";
*result = '\0';
char *copy = strdup(string);
char *word = strtok(copy, whitespace);
for (int i = 0; word != NULL; word = strtok(NULL, whitespace), i++) {
if (i % 2)
strrev(word);
result += sprintf(result, "%s%s", (i == 0) ? "" : " " , word);
}
free(copy);
}
Option 3:
#include <string.h>
#include <stdlib.h>
void reverse_alternate(const char *string, char *result) {
result[0] = '\0';
size_t length = 0, start = 0, stop = 0, parity = 1, index = 0;
for(size_t i=0; i<=strlen(string); i++) {
char curr = string[i];
if((curr == ' ' || curr == '\0') && length) {
if(parity) {
for(size_t j = start; j < stop; j++) {
result[index++] = string[j];
}
}
else {
for(size_t j = stop - 1; j >= start; j--) {
result[index++] = string[j];
}
}
result[index++] = ' ';
length = 0;
parity ^= 1;
}
if(curr == ' ') {
continue;
}
if(length == 0) {
start = i;
stop = i;
}
length++;
stop++;
}
result[index - 1] = '\0';
}
Test cases to validate our solution
#include <criterion/criterion.h>
#include <stdlib.h>
#include <string.h>
void reverse_alternate(const char *string, char *result);
void tester(const char *string, char *expected);
Test(reverse_alternate, Sample_Tests) {
tester("Did it work?", "Did ti work?");
tester("I really hope it works this time...", "I yllaer hope ti works siht time...");
tester("Reverse this string, please!", "Reverse siht string, !esaelp");
tester("Have a beer", "Have a beer");
tester(" ", "");
}
void tester(const char *string, char *expected) {
size_t length = strlen(string);
char submitted[length + 1];
memset(submitted, '@', length + 1);
reverse_alternate(string, submitted);
cr_assert( !strcmp(submitted, expected),
"< Incorrect Result >\n \nstring = \"%s\"\n \nSubmitted: \"%s\"\nExpected: \"%s\"\n \n",
string, submitted, expected
);
}