Reputation:
I'm trying to write a function to remove the spaces in a string, I know that my problem is that even after moving the next character into where the space would be, I'm still copying that character in its original place (I'm repeating a character twice). I'm not too sure how to get rid of that repeating character. (i.e. I have "Hello world.", but my function gives me "Hellowworld.")
void deblank(char str1[], char str2[])
{
int i, x;
for (i = 0; str1[i] != '\0'; i++)
{
if (str1[i] == ' ')
{
x = i + 1;
str2[i] = str1[x];
}
else
{
str2[i] = str1[i];
}
}
str2[i] = '\0';
}
Upvotes: 0
Views: 242
Reputation: 22374
Okay this is just to give an alternate approach to the accepted answer, and is primarily to help you approach solving problems in a more generic way.
#include <stdio.h>
/**
* char *remove_needles(char *dest, const char *haystack, const char *needles);
*
* puts in dest, all characters from haystack, that are not found in needles
*/
char *remove_needles(char *dest, const char *haystack, const char *needles)
{
const char *hp; /* this pointer will run through the haystack and is used to sort
* needles and hay
*/
char *dp; /* this pointer will point to the last character in dest */
const char *np; /* runs through the needles with the current */
dp = dest; /* to begin with the tail is the head :-) */
for (hp = haystack; hp != NULL && *hp != '\0'; hp++ ) {
for (np = needles; *np != '\0'; np++ ) {
if ( *hp == *np ) { /* is the current char at hp a needle? */
break; /* yep: let's break out of this loop it's a needle */
}
}
if ( *np == '\0' ) {
/* *np will only be '\0' if we ran through all the needles but
* the character at the pointer hp was not a needle
*/
*dp = *hp; /* so it's hay and we save it at the tail of dest */
dp++; /* and move the tail along */
}
}
return dest; /* we are all done and we return the result */
}
int main()
{
char src[] = "Hello World\n\tare you watching this?";
char dest[256]; /* this should have at least sizeof(src) space */
char white_spaces[] = " \t"; /* these are our needles, notice the space before \t */
remove_needles(dest, src, white_spaces);
printf("src: `%s'\ndest:`%s'\n", src, dest);
return 0;
}
Can you extend this to a split function that put substrings from haystack into an array? Start out by limiting yourself to 10 substrings, declare char dest[128][10];
and try it out.
How can you avoid declaring dest like this? We know that total memory dest can take up is not bigger than haystack, is it possible to keep yourself squeezed close to around that amount without manually calculating it?
Upvotes: 1
Reputation: 201
This should works.
void deblank(char str1[], char str2[])
{
int i, j;
for (i = 0, j = 0; str1[i] != '\0'; i++, j++)
{
if (str1[i] == ' ')
{
i++;
str2[j] = str1[i];
}
else
{
str2[j] = str1[i];
}
}
str2[j] = '\0';
}
Upvotes: 0
Reputation: 153348
[edit] re-write to use only 1 string parameter.
void deblank(char str[]) {
size_t x = 0;
for (size_t i = 0; str[i]; i++) {
if (str[i] != ' ') {
str[x++] = str[i];
}
}
str[x] = '\0';
}
Upvotes: 1
Reputation: 490098
Right now, you have only one index, i
.
You really want two indices, call them i
and j
. i
will be your index into your source string. j
will be your index into your destination string.
You'll start by walking through the source string about like you are now, incrementing i
at each iteration. When you have a non-space character in the source, you'll copy it to the destination, and increment your destination index.
When you have a space in the source, you won't copy it to the destination or increment the destination index.
Typically this will look something like:
size_t j = 0;
for (i=0; input[i]; i++)
if (input[i] != ' ')
output[j++] = input[i];
output[j] = '\0';
And yes, I'd use something like input
and output
or source
and dest
instead of str1
and str2
. The latter gives no indication of which you're copying from/to.
I'd also advise using isspace
from <ctype.h>
instead of comparing directly to the space character, unless you really only want to eliminate the space character, but retain other white space (tabs, carriage returns, new lines, vertical tabs, etc.)
Upvotes: 1
Reputation: 7448
A smarter way would be to have a second counter that is used to keep track of the current position in the output array. You only copy to the output if the current character in the input is not space.
#include <stdio.h>
void deblank(char str1[], char str2[])
{
int i, j = 0; /* j points initially to the first element of str2, we only increment it if i doesn't point to space */
for (i = 0; str1[i] != '\0'; i++)
{
if (str1[i] != ' ') /* i doesn't point to a space char */
{
str2[j] = str1[i]; /* add the current char to str2, for the first iteration this is at position str2[0] */
j++; /* increment j++, so that the next time we encounter a non-space char, it is put in the next posisition */
}
}
str2[i] = '\0';
}
int main()
{
char input[20] = "Hey lo, World!";
char output[20] = "";
deblank(input, output);
printf("%s - %s\n", input, output);
return 0;
}
Prints:
$ ./a.out
Hey lo, World! - Heylo,World!
Upvotes: 0
Reputation: 132
code what ur written won't work when multiple spaces are there in between words.
int i, x=0;
for (i = 0; str1[i] != '\0'; i++)
{
if ((str1[i] == ' ')||(str[i] == '\t'))
{
continue;
}
else
{
str2[x] = str1[i];
x++;
}
}
str2[x] = '\0';
Upvotes: 0
Reputation: 2366
You are just shifting the 1 character and leaving the rest - filling the ' ' with a 'w'.
Moving left to right, you need to shift ALL characters to the left every time you encounter a blank. That's the idea anyway.
It would be easier - and a little faster - to have 2 strings: a source and a destination.
Like so:
char src[128] = "hello world and then some!";
char dest[128];
int destIndex = 0;
for (int i = 0; i < strlen(src); ++i)
{
if (src[i] != ' ')
dest[destIndex++] = src[i];
}
dest[destIndex] = 0; // make sure the new string is terminated
That way you don't have to shift anything - just move the non-blank chars to the new string and you're left with a new string with all of the spaces removed.
Upvotes: 0