[try Beta version]
Not logged in

 
Inefficient code

Nov 25, 2020 at 2:21pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool StripBackslash1(char* buf)
{
    char* tmp = buf;
    bool ret = false;

    for(tmp = buf; *tmp != '\0'; tmp++)
    {
        if(tmp[0] == '\\' && tmp[1] == '\\')
        {
            strcpy(tmp, tmp+1);
            ret = true;
        }
   }

    return ret;
}


the code above strips backslashes but I do not understand how it is done from code, it seems to me that the code increases the address each time in the loop and copies the string from the succeeding address to the current address, how does this strip backslashes?

Last edited on Nov 25, 2020 at 2:21pm
Nov 25, 2020 at 3:26pm
it finds it, on line 8, and when it does (the if statement is true) it copies the back half of the string over the current part.
for example:

blahblah \\ whatever
finds the \ and the \ [0] and [1]
then it copies " whatever" over the first backslash.
if it removed any, it returns true.

this is C code; c++ would use string which has a way to do this for you.
it may be more efficient to use strstr to find the pattern if you are writing C.

its not that bad. It can probably be faster, but its not 'that' inefficient. Change it for strstr and call it good, unless you are absolutely sure it is a bottleneck for performance.
Last edited on Nov 25, 2020 at 3:28pm
Nov 25, 2020 at 3:39pm
http://www.cplusplus.com/reference/cstring/strcpy/ writes:
To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.

Likewise, https://en.cppreference.com/w/c/string/byte/strcpy writes:
The behavior is undefined if the strings overlap.


In other words: your code has undefined behaviour. It does not "work".
Last edited on Nov 25, 2020 at 3:39pm
Nov 25, 2020 at 5:54pm
It replaces all occurrences of \\ with \. Without using strcpy(), consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

bool StripBackslash1(char *buf)
{
	bool ret {};

	for (; *buf; ++buf)
		if (*buf == '\\' && *(buf + 1) == '\\')
			for (char *p = buf + 1; *p; ++p) {
				*p = *(p + 1);
				ret = true;
			}

	return ret;
}

int main()
{
	char data[] = R"(abc\\def\\ghi)";

	std::cout << data << '\n';

	StripBackslash1(data);
	std::cout << data << '\n';
}



abc\\def\\ghi
abc\def\ghi

Last edited on Nov 25, 2020 at 6:40pm
Nov 25, 2020 at 6:38pm
If you want to use strstr(), then:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <cstring>

bool StripBackslash1(char *buf)
{
	bool ret {};

	for (; buf = std::strstr(buf, R"(\\)"); ++buf)
		for (char* p = buf + 1; *p; ++p) {
			*p = *(p + 1);
			ret = true;
		}

	return ret;
}

int main()
{
	char data[] = R"(zxcb\\lk\\g)";

	std::cout << data << '\n';

	StripBackslash1(data);
	std::cout << data << '\n';
}



zxcb\\lk\\g
zxcb\lk\g

Last edited on Nov 25, 2020 at 6:39pm
Nov 25, 2020 at 9:06pm
memmove is safe if you are in C and need to overlap the memory. I think most compilers work if you overlap strcpy but they are correct, it isnt ensured and is unsafe to assume.

The C library function void *memmove(void *str1, const void *str2, size_t n) copies n characters from str2 to str1, but for overlapping memory blocks, memmove() is a safer approach than memcpy().
Last edited on Nov 25, 2020 at 9:07pm
Topic archived. No new replies allowed.