Reputation: 81
I have a function that strips punctuators from a given string, and makes all of it's contents lower-case:
void stripPunctuators(char *str)
{
int i, j, len = strlen(str);
for (i = 0; i < len; i++)
{
if (!isalpha(str[i]))
{
for (j = i; j < len; j++)
{
str[j] = str[j + 1];
}
len--;
}
str[i] = tolower(str[i]);
}
}
But for some reason it runs into trouble when I have two non-alpha characters in a row... Here is my main function:
int main(void)
{
char str[50] = "Hello.";
printf("Before strip: %s\n", str);
stripPunctuators(str);
printf("After strip: %s\n", str);
char str2[50] = "Hello.!";
printf("Before strip: %s\n", str2);
stripPunctuators(str2);
printf("After strip: %s\n", str2);
return 0;
}
Finally, here is my output:
Before strip: Hello.
After strip: hello
Before strip: Hello.!
After strip: hello!
Thanks for any help!
Upvotes: 0
Views: 961
Reputation: 1
You made a mistake in the function stripPunctuators.
In FOR LOOP You used :
str[j] = str[j+1];
The above statement is wrong because, same variable of the loop shouldn't be used in both the sides of the statement while running in a For Loop.
Try changing
str[j] = str[j+1] TO str[i] = str[j+1]
The Code is
void stripPunctuators(char *str){
int i, j, len = strlen(str);
for (i = 0; i < len; i++){
if (!isalpha(str[i]))
{
for (j = i; j < len; j++)
{
str[i] = str[j + 1];
}
len--;
}
str[i] = tolower(str[i]);} }
Try Using the above code, the problem will be solved.
Upvotes: 1
Reputation: 881323
It may to help to think of a short string such as a!@b
. Your index variable will iterate over the values 0..3
inclusive due to your use of the for
loop. Now follow the sequence:
0123 <- indexes
----
a!@b starting point, index = 0
a!@b index 0 was a, no shift, set index to 1
a@b index 1 was !, shift, set index to 2 ***
a@b index 2 was b, no shift, set index to 3, exit loop
From that, you should be able to see that shifting the remainder of the string and increasing the index will cause the next character to be skipped (see the ***
marker for where things went wrong).
You could fix this by using a loop where the index isn't incremented for those times when you do a shift (probably using while
rather than for
would be a good idea). That way, a shift-without-increment would leave you re-checking the same index, which is the next character (due to the shift).
However, doing a full shift of the string remainder every time you want to delete a character is rather inefficient, since there's a good possibility you may need to change those characters again.
You're far better off using a source and destination pointer with something like (pseudo-code):
set src and dst to address of first character
while character at src is not end-of-string:
if character at src is not punctuation:
set character at dst to be character at src
increment dst
increment src
set character at dst to be end-of-string
And, if you wanted that in C, it would be along the lines of:
void stripPunctuators(char *str) {
char *src = str;
char *dst = str;
while (*src != '\0') {
if (isalpha(*src)) {
*dst = *src; // or combine:
dst++; // "*dst++ = *src"
}
src++;
}
*dst = '\0';
}
Note that I've used
isalpha
in my code simply because that's the one you used in your original code. Since that will strip more than punctuation (digits, for example), you may want to re-examine whether it's the right one to use. Theisalnum
function may be more apt but it also depends on your use case. You may need to preserve spaces as well.Otherwisethingsmaygetverymessyandhardtoread :-)
Upvotes: 3