Как удалить \ n или \ t из заданной строки в C? - PullRequest
8 голосов
/ 04 октября 2009

Как я могу удалить строку со всеми \ n и \ t в C?

Ответы [ 5 ]

14 голосов
/ 04 октября 2009

Это работает в моих быстрых и грязных тестах. Делает это на месте:

#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);
}

И чтобы успокоить Криса, вот версия, которая сначала сделает копию и вернет ее (таким образом, она будет работать с литералами). Вам нужно будет 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;
}
4 голосов
/ 04 октября 2009

Если вы хотите заменить \ n или \ t чем-то другим , вы можете использовать функцию strstr (). Возвращает указатель на первое место в функции с определенной строкой. Например:

// Find the first "\n".
char new_char = 't';
char* pFirstN = strstr(szMyString, "\n");
*pFirstN = new_char;

Вы можете запустить это в цикле, чтобы найти все \ n и \ t.

Если вы хотите «удалить» их, т.е. удалить их из строки , вам нужно будет использовать тот же метод, что и выше, но каждый раз копировать содержимое строки «назад» вы находите \ n или \ t, так что «это тест» становится: «это тест».

Вы можете сделать это с помощью memmove (не memcpy, поскольку src и dst указывают на перекрывающуюся память), например, так:

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); 
}

Вам нужно будет повторить этот цикл снова, чтобы удалить \ t.

Примечание: Оба эти метода работают на месте. Это может быть небезопасно! (Подробности читайте в комментариях Эвана Терана. . Кроме того, эти методы не очень эффективны, хотя они и используют библиотечную функцию для некоторого кода, вместо того, чтобы свернуть свой.

3 голосов
/ 04 октября 2009

По сути, у вас есть два способа сделать это: вы можете создать копию исходной строки, минус все символы '\t' и '\n', или вы можете удалить строку «на месте». Тем не менее, я уверен, что первый вариант будет быстрее, и я обещаю, что он будет безопаснее.

Итак, мы сделаем функцию:

char *strip(const char *str, const char *d);

Мы хотим использовать strlen() и malloc(), чтобы выделить новый буфер char * того же размера, что и наш буфер str. Затем мы проходим str символ за символом. Если символ не содержится в d, мы копируем его в наш новый буфер. Мы можем использовать что-то вроде strchr(), чтобы увидеть, есть ли каждый символ в строке d. Как только мы закончим, у нас будет новый буфер с содержимым нашего старого буфера минус символы в строке d, поэтому мы просто возвращаем его. Я не буду давать вам пример кода, потому что это может быть домашнее задание, но вот пример использования, чтобы показать вам, как он решает вашу проблему:

char *string = "some\n text\t to strip";

char *stripped = strip(string, "\t\n");
1 голос
/ 04 октября 2009

Это функция строки c, которая найдет любой символ в 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 будет указывать на \ t или 15 символов в search. Вы можете заменить, а затем снова позвонить, чтобы выполнить цикл, пока все не будут заменены.

0 голосов
/ 04 октября 2009

Мне нравится, чтобы стандартная библиотека выполняла как можно больше работы, поэтому я бы использовал что-то похожее на решение Эвана, но с 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...