How can I strip a string with all \n and \t in C?
This works in my quick and dirty tests. Does it in place:
#include <stdio.h>
void strip(char *s) {
char *p2 = s;
while(*s != '\0') {
if(*s != '\t' && *s != '\n') {
*p2++ = *s++;
} else {
++s;
}
}
*p2 = '\0';
}
int main() {
char buf[] = "this\t is\n a\t test\n test";
strip(buf);
printf("%s\n", buf);
}
And to appease Chris, here is a version which will make a copy first and return it (thus it'll work on literals). You will need to free
the result.
char *strip_copy(const char *s) {
char *p = malloc(strlen(s) + 1);
if(p) {
char *p2 = p;
while(*s != '\0') {
if(*s != '\t' && *s != '\n') {
*p2++ = *s++;
} else {
++s;
}
}
*p2 = '\0';
}
return p;
}
Basically, you have two ways to do this: you can create a copy of the original string, minus all '\t'
and '\n'
characters, or you can strip the string "in-place." However, I bet money that the first option will be faster, and I promise you it will be safer.
So we'll make a function:
char *strip(const char *str, const char *d);
We want to use strlen()
and malloc()
to allocate a new char *
buffer the same size as our str
buffer. Then we go through str
character by character. If the character is not contained in d
, we copy it into our new buffer. We can use something like strchr()
to see if each character is in the string d
. Once we're done, we have a new buffer, with the contents of our old buffer minus characters in the string d
, so we just return that. I won't give you sample code, because this might be homework, but here's the sample usage to show you how it solves your problem:
char *string = "some\n text\t to strip";
char *stripped = strip(string, "\t\n");
If you want to replace \n or \t with something else, you can use the function strstr(). It returns a pointer to the first place in a function that has a certain string. For example:
// Find the first "\n".
char new_char = 't';
char* pFirstN = strstr(szMyString, "\n");
*pFirstN = new_char;
You can run that in a loop to find all \n's and \t's.
If you want to "strip" them, i.e. remove them from the string, you'll need to actually use the same method as above, but copy the contents of the string "back" every time you find a \n or \t, so that "this i\ns a test" becomes: "this is a test".
You can do that with memmove (not memcpy, since the src and dst are pointing to overlapping memory), like so:
char* temp = strstr(str, "\t");
// Remove \n.
while ((temp = strstr(str, "\n")) != NULL) {
// Len is the length of the string, from the ampersand \n, including the \n.
int len = strlen(str);
memmove(temp, temp + 1, len);
}
You'll need to repeat this loop again to remove the \t's.
Note: Both of these methods work in-place. This might not be safe! (read Evan Teran's comments for details.. Also, these methods are not very efficient, although they do utilize a library function for some of the code instead of rolling your own.
This is a c string function that will find any character in accept
and return a pointer to that position or NULL if it is not found.
#include <string.h>
char *strpbrk(const char *s, const char *accept);
Example:
char search[] = "a string with \t and \n";
char *first_occ = strpbrk( search, "\t\n" );
first_occ
will point to the \t, or the 15 character in search
. You can replace then call again to loop through until all have been replaced.
I like to make the standard library do as much of the work as possible, so I would use something similar to Evan's solution but with strspn()
and strcspn()
.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SPACE " \t\r\n"
static void strip(char *s);
static char *strip_copy(char const *s);
int main(int ac, char **av)
{
char s[] = "this\t is\n a\t test\n test";
char *s1 = strip_copy(s);
strip(s);
printf("%s\n%s\n", s, s1);
return 0;
}
static void strip(char *s)
{
char *p = s;
int n;
while (*s)
{
n = strcspn(s, SPACE);
strncpy(p, s, n);
p += n;
s += n + strspn(s+n, SPACE);
}
*p = 0;
}
static char *strip_copy(char const *s)
{
char *buf = malloc(1 + strlen(s));
if (buf)
{
char *p = buf;
char const *q;
int n;
for (q = s; *q; q += n + strspn(q+n, SPACE))
{
n = strcspn(q, SPACE);
strncpy(p, q, n);
p += n;
}
*p++ = '\0';
buf = realloc(buf, p - buf);
}
return buf;
}