Easiest and most efficient don't usually go together…
Here's a possible solution for in-place removal:
void remove_spaces(char* s) {
char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
Answer from Aaron on Stack OverflowEasiest and most efficient don't usually go together…
Here's a possible solution for in-place removal:
void remove_spaces(char* s) {
char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
As we can see from the answers posted, this is surprisingly not a trivial task. When faced with a task like this, it would seem that many programmers choose to throw common sense out the window, in order to produce the most obscure snippet they possibly can come up with.
Things to consider:
- You will want to make a copy of the string, with spaces removed. Modifying the passed string is bad practice, it may be a string literal. Also, there are sometimes benefits of treating strings as immutable objects.
- You cannot assume that the source string is not empty. It may contain nothing but a single null termination character.
- The destination buffer can contain any uninitialized garbage when the function is called. Checking it for null termination doesn't make any sense.
- Source code documentation should state that the destination buffer needs to be large enough to contain the trimmed string. Easiest way to do so is to make it as large as the untrimmed string.
- The destination buffer needs to hold a null terminated string with no spaces when the function is done.
- Consider if you wish to remove all white space characters or just spaces
' '. - C programming isn't a competition over who can squeeze in as many operators on a single line as possible. It is rather the opposite, a good C program contains readable code (always the single-most important quality) without sacrificing program efficiency (somewhat important).
- For this reason, you get no bonus points for hiding the insertion of null termination of the destination string, by letting it be part of the copying code. Instead, make the null termination insertion explicit, to show that you haven't just managed to get it right by accident.
What I would do:
void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed)
{
while (*str_untrimmed != '\0')
{
if(!isspace(*str_untrimmed))
{
*str_trimmed = *str_untrimmed;
str_trimmed++;
}
str_untrimmed++;
}
*str_trimmed = '\0';
}
In this code, the source string "str_untrimmed" is left untouched, which is guaranteed by using proper const correctness. It does not crash if the source string contains nothing but a null termination. It always null terminates the destination string.
Memory allocation is left to the caller. The algorithm should only focus on doing its intended work. It removes all white spaces.
There are no subtle tricks in the code. It does not try to squeeze in as many operators as possible on a single line. It will make a very poor candidate for the IOCCC. Yet it will yield pretty much the same machine code as the more obscure one-liner versions.
When copying something, you can however optimize a bit by declaring both pointers as restrict, which is a contract between the programmer and the compiler, where the programmer guarantees that the destination and source are not the same address. This allows more efficient optimization, since the compiler can then copy straight from source to destination without temporary memory in between.
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
foo is your string:
" ".join(foo.split())
Be warned though this removes "all whitespace characters (space, tab, newline, return, formfeed)" (thanks to hhsaffar, see comments). I.e., "this is \t a test\n" will effectively end up as "this is a test".
It seems to be a common newbie confusion. Printing gets confused with other concepts. If a function prints something, then the function is 'returning' what is printed. This is completely untrue, printing is printing, nothing else.
If you want to write a function that removes spaces from a string, then that is what the function must do. Somehow a new string without the spaces must be created. How that function returns the modified string is a side issue.
Here's a function that removes spaces from a string.
void RemoveSpaces ( string &userString )
{
string temp;
for (size_t i = 0 ; i < userString.size() ; i ++ )
{
if (userString.at(i) != ' ' )
temp.push_back(userString.at(i));
}
userString = temp;
}
This function works by looking for the non-spaces in userString and adding them to a new string temp. This is the string without spaces. Then at the end of the function it assigns this string back to userString. Because userString has been passed by reference this assignment modifies userInputString in main. That's the meaning of pass by reference. Changes to userString actually change the string that is being referred to.
It is possible to write a function that modifies userString directly, but that is more complicated code, so I chose to do it this way with a second string temp.
in the function RemoveSpaces, you are printing the srting without spaces but not updating it. So for example the string is "This is an example" it would just print "Thisisanexample" but the value of the string still remains the same. You will have to update the value of string in the function inorder to update the original string value, pass by reference doesn't automatically do it.
void RemoveSpaces ( string &userString )
{
unsigned int i ;
int count = 0;
for ( i = 0 ; i < userString.size() ; i ++ )
{
if ( userString.at(i) != ' ' )
{
userString.at(count++) = userString.at(i);
cout << userString.at(i) ;
}
}
userString.resize(count);
}
resize(count) is added cause for example orginial string - "This is an example" size - 18 updated string - "Thisisanexampleple" size - 18 This happens because updated string has a size of 15("Thisisanexample") but original has size of 18 so it will take 18-15 = 3 characters from original string and keep it in updated string. hence you need to resize the updated string to 15 i.e. the count variable which tracks size of updated string.