0

我有以下代码,但有时我会得到奇怪的字符而不是空格:

char *getWord(const char *string)
{
    char *chars = "-_";
    int len = 0;
    int max = 10;
    char *res = malloc(max + 1);
    for ( ; len<max; string++) {
        if(*string)
        {
            if (!strchr(chars, *string)) {
                res[len] = *string;
                ++ len;
            }
        }
        else
        {
            res[len] = ' ';
            ++ len;
        }
    }
    res[len] = 0;
    return res;
}

例如:char *mystring = "my-str_a"; //我想要的结果:“mystra”,后跟 4 个空格:“mystra”

如何在单词末尾填充空格直到达到最大长度?

4

5 回答 5

2
char *getWord(const char *string)
{
    char *chars = "-_";
    size_t len ,max ;
    char *res ;

    max = 10;
    res = malloc(max + 1);
    if (!res) return 0;

    for (len = 0 ; *string && len < max; string++) {
        if (!strchr(chars, *string)) { res[len++] = *string; }
        }

    if (len < max) memset(res+len, ' ', max-len);
    res[max] = 0;
    return res;
}

使用 strspn() / strcspn() 的第二个版本(如果 chars 大于一个或两个字符,这可能会更快)

char *getWord3(const char *string)
{
    char *chars = "-_";
    size_t dst,src,len ,max ;
    char *res ;

    max = 10;
    res = malloc(max + 1);
    if (!res) return 0;
    for (src=dst = 0 ; string[src] && dst < max; ) {
        len = strcspn( string+src, chars);
        if (len) {
                memcpy(res+dst,  string+src, len);
                src += len, dst += len;
                }
        len = strspn( string+src, chars);
        if (len) {
                src += len;
                }
        }

    if (dst < max) memset(res+dst, ' ', max-dst);
    res[max] = 0;
    return res;
}
于 2013-09-04T16:33:39.353 回答
1

原始答案

一个问题是您缺少elsefor 子句if (*string),该子句需要将字符设置为空白。另一个问题是你读到了字符串的末尾。

char *getWord(const char *string)
{
    char *chars = "-_";
    int max = 10;
    int len;
    char *res = malloc(max + 1);
    if (res == 0)
        return res;
    for (len = 0; len < max; len++)
    {
        if (*string)
        {
            if (!strchr(chars, *string))
                res[len] = *string;
            else
                res[len] = ' ';
            string++;
        }
        else
            res[len] = ' ';
    }
    res[len] = 0;
    return res;
}

这使用常规for (int len = 0; len < max; len++)循环来逐步遍历分配的数组。代码仅string在不指向终端空字节时才会增加。每次迭代都有一个赋值res[len]。该代码还检查内存分配是否成功——这在实际程序中很重要。

修改后的答案

该功能getWord2()可以满足您的要求。注意测试工具。

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

static
char *getWord1(const char *string)
{
    char *chars = "-_";
    int max = 10;
    int len;
    char *res = malloc(max + 1);
    if (res == 0)
        return res;
    for (len = 0; len < max; len++)
    {
        if (*string)
        {
            if (!strchr(chars, *string))
                res[len] = *string;
            else
                res[len] = ' ';
            string++;
        }
        else
            res[len] = ' ';
    }
    res[len] = 0;
    return res;
}

static
char *getWord2(const char *string)
{
    char *chars = "-_";
    int max = 10;
    int len = 0;
    char *res = malloc(max + 1);
    if (res == 0)
        return res;
    while (len < max)
    {
        if (*string)
        {
            if (!strchr(chars, *string))
                res[len++] = *string;
            string++;
        }
        else
            res[len++] = ' ';
    }
    res[len] = 0;
    return res;
}


int main(void)
{
    const char *data[] =
    {
        "my-str_a",
        "--m--__",
        "my str a",
        "AbyssinianElephant",
        "--m--__m--m--m-m-m-m-m-m-m-m-m-m",
    };

    for (size_t i = 0; i < sizeof(data)/sizeof(data[0]); i++)
    {
        char *res1 = getWord1(data[i]);
        char *res2 = getWord2(data[i]);
        char source[30];
        snprintf(source, sizeof(source), "<<%.25s>>", data[i]);
        assert(res1 != 0 && res2 != 0); // Reprehensible!

        printf("%-30.30s --> <<%s>> or <<%s>>\n", source, res1, res2);
        free(res1);
        free(res2);
    }
    return 0;
}

样本输出:

<<my-str_a>>                   --> <<my str a  >> or <<mystra    >>
<<--m--__>>                    --> <<  m       >> or <<m         >>
<<my str a>>                   --> <<my str a  >> or <<my str a  >>
<<AbyssinianElephant>>         --> <<Abyssinian>> or <<Abyssinian>>
<<--m--__m--m--m-m-m-m-m-m->>  --> <<  m    m  >> or <<mmmmmmmmmm>>

如果 'mmmmmmmmmm' 输出不是您想要的,规范需要收紧一点。调整可能并不难,但确实需要指定。

于 2013-09-04T14:31:49.047 回答
0

The problem is that once you pass the terminating null of the variable string, you can't rely on *string to stay null. The result is that when string is less than max chars in length, you pick up whatever is in the bytes after the terminating null.

So, once you reach strlen(string), you need to just pad with blanks until you reach max. I wouldn't advance the 'string' argument, but subscript it with 'len'.

stringlen = strlen(string);
for (; len < max; len++ )
  if (len >= stringlen) {
    res[len] = ' ';
  } else if (*string[len]) {

and so on.

于 2013-09-04T14:23:22.063 回答
0

您必须检查标记字符串结尾的 '\0' 的第一次出现。在您的代码中,for 循环继续迭代并在字符串末尾(即在“\0”之后)复制所有垃圾字符。垃圾字符来自 malloc 保留内存但不清除它(不将内存中的值设置为零)的事实。

于 2013-09-04T14:25:17.683 回答
0

更简单的方法:只需使用“读”和“写”指针沿着字符串爬行:

char *getWord(const char *string) {
    char *res = strdup(string);
    char *rp = res;
    char *wp = res;
    while(*rp) {
        if(*rp != '-' && *rp != '_') {
            *wp++ = *rp;
        }
        rp++;
    }
    while(wp < rp) {
        *wp++ = ' ';
    }
    return res;
}
于 2013-09-04T14:17:01.743 回答