I've written a program to reverse a char array and also reverse words within that array. The program almost works as intended but I believe this is an off-by-one error. I've tried messing with the math involving the loop counters but have not been able to figure this one out. What tool or techniques can I use to solve this type of problem? I've tried printf statements and also using gdb and placing a watch on the counter variables.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse_arr(char *arr, size_t len);
void print_chars(char *arr, size_t len);
void reverse_words(char *arr, size_t len);
int main(int argc, char **argv)
{
char phrase[] = {'p','e','r','f','e','c','t',' ',
'm','a','k','e','s',' ','p','r',
'a','c','t','i','c','e'};
size_t i;
reverse_arr(phrase, sizeof(phrase));
reverse_words(phrase,sizeof(phrase));
print_chars(phrase, sizeof(phrase));
return EXIT_SUCCESS;
}
void reverse_arr(char *arr, size_t len)
{
size_t front, tail;
tail = len-1;
char tmp;
for(front = 0; front < len/2; front++, tail--)
{
tmp = arr[front];
arr[front] = arr[tail];
arr[tail] = tmp;
}
return;
}
// 1. Search for a space
// 2. When space is found, that space is the place to stop and indicates all between the start and it are a word
// 3. Now call reverse_arr on the word and calculate the length of the word by subtracting tail - start
//
void reverse_words(char *arr, size_t len)
{
size_t tail, start;
for(tail = start = 0; tail < len; tail++)
{
if(arr[tail] == ' ' || tail == len-1)
{
reverse_arr(&arr[start], tail - start);
start = tail+1;
}
}
}
void print_chars(char *arr, size_t len)
{
size_t i;
for(i = 0; i < len; i++)
{
putchar(arr[i]);
}
putchar('\n');
return;
}
This code returns practice makes erfectp. Clearly, this is an off-by-one bug but I've spent some time on this and suffered similar bugs in C in other programs.
The bug is in
reverse_words. Sometimestailindexes the character after the last character of the word, and sometimestailindexes the last character of the word itself.The call to
reverse_arrayfromreverse_wordsis:This works if
startindexes the first character of the word, and if there aretail - startcharacters in the word. Sotailmust index the character after the last character of the word.The condition
arr[tail] == ' 'is consistent with this, but end condition is not: (1) the loop exits too soon, and (2) the testtail == len-1is also off by one.This can be fixed by iterating one more time, and checking the end condition before trying to access
arr[tail](to avoid indexing past the end):Note that the loop exit condition is now
<=rather then<, the in-loop end test has shifted by one, and the order of the checks within the loop is reversed.