使用C中的字符串修剪删除空格,换行符和制表符

时间:2017-10-08 06:21:58

标签: c string error-handling while-loop trim

我试图从互联网上收集资源,以了解它的工作原理和功能。基本上,每次读取字符串时,我都需要检查空格,换行符和制表符。所以我做了一个处理这种情况的函数:

#include <stdlib.h>
#include <stdio.h>

static int  isspace(char c)
{
    return (c == '\t' || c == '\n' || c == ' ');
}

然后,我使用下面的函数在另一个函数

中实现它
char *my_strtrim(char const *string)
{
    char *i;
    char *s;
    int ready;

    i = s;
    s = (char *)string;
    ready = 0;
    while(*i)
    {
        ++i;
        if(isspace(*i))
        {
            if(!ready)
            {
                continue ;
            }
            ready = 0;
        }
        ready = 1;
        *(s++) = *i;
    }

    *s = 0;
    return ((char *)string);
}

对于我的主要内容,我只是做了一个随机测试案例,它处理空格,制表符和换行符:

int main()
{
    char str[] = "                      hello world\n !";
    printf("%s",my_strtrim(str));
}

my_strtrim函数中i = s出现输出错误,因为s没有NULL的结果。错误说:

my_strtrim.c: error: variable 's' is uninitialized when used here [-Werror,-Wuninitialized]
        i = s;
            ^
my_strtrim.c: note: initialize the variable 's' to silence this warning
        char *s;
               ^
                = NULL

在我修复它所说的内容后(制作s = NULL)我得到了一个分段错误。这个问题变得令人困惑,因为它作为for循环工作正常,但不是while循环。我需要将此问题作为while循环执行。

我的朋友给了我一个小小的提示/经验法则,这使得代码简单易懂。我有一个集群功能在同一个地方做很多事情;因此,我感到困惑。他引导我并告诉我让我把我的整个功能压缩成小块。

第0步:启动变量并声明

自解释

第1步:获取指针字符串的位置

int     step1_getPosition(char const *string)
{
    int i;

    i = 0;
    while(my_iswhitespace(string[i]))
    {
            i++;
            continue;
    }
    return (i);
}

第2步:复制你的字符串

char    *step2_copyString(char const *string, int pos)
{
    char *tmp;
    int     i;

    i = 0;
    tmp = my_strnew(my_strlen(string));
    if(tmp == NULL)
        return (NULL);
    while (string[pos] != '\0')
        tmp[i++] = string[pos++];
    return (tmp);
}

第3步:删除白色空间

char    *step3_removeWhite(char *str)
{
    int i;

    i = my_strlen(str);
    while (str[i] == '\0' || my_iswhitespace(str[i]))
    {
        str[i] = '\0';
        i--;
    }
    return (str);
}

第4步:删除EXTRA NULL-BYTES('\ 0')

char    *step4_removeExtraNulls(char *str)
{
    char *newstring;

    newstring = my_strdup(str);
    if(newstring == NULL)
        return (NULL);
    free(str);
    return (newstring);
}

第5步:主要功能与其他功能相关

char    *my_strtrim(char const *string)
{
    char    *trim;
    int     i;

    i = step1_getPosition(string);
    trim = step2_copyString(string, i);
    if (trim == NULL)
        return (NULL);
    step3_removeWhite(trim);
    trim = step4_removeExtraNulls(trim);
    if (trim == NULL)
        return (NULL);
    return (trim);
}

我得到的输出是: hello world ! 这是正确的

3 个答案:

答案 0 :(得分:3)

&#34; trim&#34;最简单的方法领先的空白字符,就是跳过它们,而不是修改字符串。

这取决于&#34;字符串&#34; in C可以表示为指向以null结尾的字符序列的指针。

以你的字符串

为例
char str[] = "                      hello world\n !";

如果我们让数组str衰减到指向其第一个元素的指针,则它指向第一个空格。如果我们有一个指向'h'的指针怎么办?那将是一个同样有效的&#34;字符串&#34;。

要获得该指针,我们只需循环遍历字符串,只要当前字符是空格(当然不是终结符)。

将此付诸实践,我们得到了

char *my_strtrim(char const *string)
{
    for (/* empty */; *string && my_isspace(*string); ++string)
    {
        // Empty
    }

    return string;
}

在上面函数的循环之后,指针string指向到终结符(如果字符串只是所有空格),或指向第一个非空格字符字符串。

如果我们像

一样使用它
printf("%s\n", my_strtrim(str));

然后会打印

hello world
 !

[嵌入式换行是因为你的字符串中有它。]

应该注意的是,这并没有修剪尾随空格。为了实现这一点,参数string不能指向常量字符。

答案 1 :(得分:0)

问题正在发生,因为当您为binned = pd.cut(in_order.mean, bins) TypeErrorTraceback (most recent call last) <ipython-input-229-3343eeaf99d6> in <module>() ----> 1 binned = pd.cut(in_order.mean, bins) C:\Users\zkrumlinde\AppData\Local\Enthought\Canopy32\edm\envs\User\lib\site-packages\pandas\tools\tile.pyc in cut(x, bins, right, labels, retbins, precision, include_lowest) 117 return _bins_to_cuts(x, bins, right=right, labels=labels, 118 retbins=retbins, precision=precision, --> 119 include_lowest=include_lowest) 120 121 C:\Users\zkrumlinde\AppData\Local\Enthought\Canopy32\edm\envs\User\lib\site-packages\pandas\tools\tile.pyc in _bins_to_cuts(x, bins, right, labels, retbins, precision, name, include_lowest) 222 223 levels = np.asarray(levels, dtype=object) --> 224 np.putmask(ids, na_mask, 0) 225 fac = Categorical(ids - 1, levels, ordered=True, fastpath=True) 226 else: TypeError: putmask() argument 1 must be numpy.ndarray, not numpy.int32 分配i = s变量时,处于未定义的状态。

请考虑以下代码:

s

答案 2 :(得分:0)

Zeid,继续发表评论。效率目标之一应该是限制你对字符串的传递次数(最好是一次)。您还应该考虑传递一个最终数组来保存修剪后的字符串,因为有许多实例需要保留原始字符串,或者,正如某些程序员dude正确指出的那样,您无法修改和指定为const的参数或者驻留在只读内存中的一个(例如字符串文字)。

您可以在呼叫者中使用VLA进行此操作。完全放置并添加一个额外的参数来保存结果'r',您可以执行以下操作。

它只是删除所有前导空格,然后备份,删除所有尾随空格,并检查最终字符是否是alnum字符以外的任何字符(因为大多数句子以某种类型的标点符号结束)。然后检查标点符号和字符串中的最后一个alnum char之间是否有任何额外的空格,通过向前移动结束字符以覆盖找到的任何插入空格来删除任何插入的空格(这将消除您之间的额外'\n ' world'!'

#include <stdio.h>
#include <ctype.h>

/** remove leading and trailing whitespace, original is preserved.
 *  this funciton can be used with or without assigning return.
 *  any intervening whitespace between end punctuation and first
 *  alpha-num character is also removed.
 */
char *strtrimws (char *r, const char *s)
{
    char *p = r;                            /* pointer to result         */
    *r = 0;                                 /* initialize as empty str   */
    if (!s) return NULL;                    /* validaate source str      */
    if (!*s) return r;                      /* empty str - nothing to do */
    while (isspace (*s))  s++;              /* skip leading whitespace   */
    while (*s) *p++ = *s++;                 /* fill r with s to end      */
    *p = 0;                                 /* nul-terminate r           */
    while (p > r && isspace (*--p)) *p = 0; /* overwrite spaces from end */
    while (p > r && !isalnum (*--p)) {      /* continue until 1st alnum  */
        if (isspace (*p)) {                 /* if spaces found           */
            char *rp = p, *wp = p;          /* set read & write pointers */
            while (*rp++) *wp++ = *rp;      /* shuffle end chars forward */
            *wp = 0;                        /* nul-terminate at new end  */
        }
    }
    return r;
}

int main (void) {

    char str[] = "                      hello world\n !",
        result[sizeof str];
    printf ("%s\n", strtrimws (result, str));
    return 0;
}

示例使用/输出

$ ./bin/trimws
hello world!

仔细看看,如果您有任何其他问题,请告诉我。如果没有,祝你的编码好运。