hax
hax

Reputation: 81

Deleting Certain Elements from a Char Array

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

Answers (2)

Manikanta Vedula
Manikanta Vedula

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

paxdiablo
paxdiablo

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. The isalnum function may be more apt but it also depends on your use case. You may need to preserve spaces as well.

Otherwisethingsmaygetverymessyandhardtoread :-)

Upvotes: 3

Related Questions