简体   繁体   中英

Remove redundant whitespace from string (in-place)

Ok so i posted earlier about trying to (without any prebuilt functions) remove additional spaces so

"this is <insert many spaces!> a test" would return

"this is a test"

Remove spaces from a string, but not at the beginning or end

As it was homework i asked for no full solutions and some kind people provided me with the following

"If you need to do it in place, then create two pointers. One pointing to the character being read and one to the character being copied. When you meet an extra space, then adapt the 'write' pointer to point to the next non space character. Copy to the read position the character pointed by the write character. Then advance the read and write pointers to the character after the character being copied."

The problem is i now want to fully smash my computer in to pieces as i am sooooo irritated by it. I didnt realise at the time i couldnt utilise the char array so was using array indexes to do it, i thought i could suss how to get it to work but now i am just using pointers i am finding it very hard. I really need some help, not full solutions. So far this is what i am doing;

1)create a pointer called write, so i no where to write to

2)create a pointer called read so i no where to read from

(both of these pointers will now point to the first element of the char array)

while (read != '\0')
    if read == a space 
        add one to read
        if read equals a space now 
            add one to write
            while read != a space {
                 set write to = read
            }
                 add one to both read and write
    else 
        add one to read and write 
        write = read  

Try just doing this yourself character by character on a piece of paper and work out what it is you are doing first, then translate that into code.

If you are still having trouble, try doing something simpler first, for example just copying a string character for character without worrying about the "remove duplicate spaces" part of it - just to make sure that you haven't made a silly mistake elsewhere.

The advice of trying to do it with pen and paper first is good. And it really doesn't matter if you do it with pointers or array indexing; you can either use a reader and a writer pointer, or a reader and a writer index.

Think about when you want to move the indices forward. You always move the write index forward after you write a character. You move the read index forward when you've read a character.

Perhaps you could start with some code that just moves over the string, but actually doesn't change it. And then you add the logic that skips additional spaces.

char p[] = "this is              a test";
char *readptr = &p[0];
char *writeptr = &p[0];

int inspaces = 0;
while(*readptr) {
 if(isspace(*readptr)) {
   inspaces ++;
 } else {
  inspaces = 0;
 }
 if(inspaces <= 1) {
  *writeptr = *readptr;
   writeptr++;
 }
 readptr++;
}
*writeptr = 0;

Here's a solution that only has a single loop (no inner loop to skip spaces) and no state data:

dm9pZCBTdHJpcFNwYWNlcyAoY2hhciAqdGV4dCkNCnsNCiAgY2hhciAqc3JjID0gdGV4dCwgKmRl
c3QgPSB0ZXh0Ow0KICB3aGlsZSAoKnNyYykNCiAgew0KICAgICpkZXN0ID0gKihzcmMrKyk7DQog
ICAgaWYgKCpzcmMgIT0gJyAnIHx8ICpkZXN0ICE9ICcgJykNCiAgICB7DQogICAgICArK2Rlc3Q7
DQogICAgfQ0KICB9DQogICpkZXN0ID0gMDsNCn0NCg==

The above is Base64 encoded as this is a homework question. To decode, copy the above block and paste into this website to decode it (you'll need to check the "Decode" radio button).

assuming you're trying to write a function like:

void removeSpaces(char * str){

   /* ... stuff that changes the contents of str[] */

}

You want to scan the string for consecutive spaces, so that your write pointer is always trailing your read pointer. Advance your read pointer to a place where you are pointing at a space, but the next character is not a space. If your read and write pointers are not the same, then your write pointer ought to be pointing at the beginning of a sequence of spaces. The difference between your write and read pointer (ie read_pointer - write_pointer) will tell you the number of consecutive spaces that need to be overwritten to close the gap. When there is a difference of greater than zero, (prefix) advance both pointers along by that many positions, copying characters as you go. When you're read pointer is at the end of the string ('\\0'), you should be done.

Can you use regular expressions? If so, it might be really easy. Use a regex to replace \\s{2,}? with a single space. The \\s means any white space (tabs, spaces, carriage feeds...); {2,} means 2 or more; ? means non-greedy. (Disclaimer: my regex might not be the best one you could write, since I'm no regex pro. Also, it's .net syntax, so the regex library for C might have slightly different syntax.)

Why don't you do something like this:

make a second char** that is the same length as the first. As you run through the first array with your pointers keep an extra pointer on the last space you've seen. If the last space you saw was the previous element then you don't copy that char to the second array.

But I would start with something that runs through the char** by each character and prints out each char. If you can make that happen then you can work on actually copying them into a second char**.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM