如何在C语言中去除字符串中的所有 \n 和 \t?
#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);
}
为了取悦Chris,这里有一个版本,它将结果放在一个新的malloc
缓冲区中并返回它(因此它适用于文本字面量)。您需要free
结果。
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;
}
如果你想用其他东西替换\n或\t,可以使用函数strstr()。它返回一个指向函数中包含某个字符串的第一个位置的指针。例如:
// Find the first "\n".
char new_char = 't';
char* pFirstN = strstr(szMyString, "\n");
*pFirstN = new_char;
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);
}
memmove()
可惜相对较少人知道。 - Chris Lutz基本上,你有两种方式来做这件事:你可以创建一个原始字符串的副本,去掉所有的'\t'
和'\n'
字符,或者你可以直接在原字符串上进行修改。然而,我敢打赌第一种选择会更快,而且我向你保证它也更安全。
因此,我们将创建一个函数:
char *strip(const char *str, const char *d);
strlen()
和 malloc()
来分配一个与我们的 str
缓冲区大小相同的新的 char *
缓冲区。然后我们逐个字符地遍历 str
。如果该字符不包含在 d
中,我们将其复制到新的缓冲区中。我们可以使用类似 strchr()
的函数来判断每个字符是否在字符串 d
中。完成后,我们就有了一个新的缓冲区,其中包含旧缓冲区中除字符串 d
中的字符之外的所有内容,因此我们只需返回它即可。我不会给你示例代码,因为这可能是作业,但以下是样例用法,以展示它如何解决你的问题:char *string = "some\n text\t to strip";
char *stripped = strip(string, "\t\n");
accept
中的任何字符,并返回该位置的指针,如果未找到,则返回 NULL。#include <string.h>
char *strpbrk(const char *s, const char *accept);
例子:
char search[] = "a string with \t and \n";
char *first_occ = strpbrk( search, "\t\n" );
first_occ
将指向search
中的制表符或第15个字符。您可以替换它并再次调用循环,直到所有内容都被替换。
我喜欢尽可能让标准库去完成更多的工作,因此我会使用类似于 Evan 的方案,但会加入 strspn()
和 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;
}
main()
的第一行更改为char *buf = ...;
会怎样?如果在更复杂的代码中使用,并且编码人员忘记了哪些参数是可写缓冲区,哪些不是呢? - Chris Lutzchar*
或char[]
有什么区别。另外,在strip
函数中存在一个错误:字符串没有以空字符结尾。 - stragerchar *buf = "hello\tworld"
的东西,这是非法的,因为您无法修改指向文字常量的指针。我的strip_copy
解决了这个问题。 - Evan Teran