在 C 中将字符串拆分为标记

时间:2020-12-20 11:54:58

标签: c string pointers split

struct string {
    size_t length;
    size_t allocated;
    char* data;
};
    string* strCreate(char* str) {...}
string* strSubstring(string* str, size_t pos, size_t len) {...}
char* strGet(string* str) {
    return str->data;
}
size_t findFrist(string* str, char what, size_t pos) {
    for(size_t i = pos; i < str->length; ++i) {
        if(str->data[i] == what)
            return i;
    }
    return -1;
}
string** strTokenizer(string* str) {
    string** res;
    res = malloc(sizeof(char*)*90); //*90 (token num)
    for(int i=0; i<90; i++) //i<90 (token num)
        res[i] = malloc(sizeof(char)*100); //*100 (a token lenght)
    size_t first = 0;
    size_t i = 0;
    while(first < str->length) {
        int second = findFrist(str,' ',first);
        if(second == - 1)
            second = str->length;
        string* token = strSubstring(str,first, second - first);
        if(*strGet(token) != ' ')
            res[i] = token;
        first = second + 1;
        ++i;
    }
    return res;
}
int main() {
    string* fe = strCreate("A string \ tof");
    string** r = strTokenizer(fe);
    for(int i = 0; i < 4; ++i) {
        printf("%s",strGet(r[i]));
    }
    return 0;
}

我想创建一个字符串标记器。当我想在 main 函数中打印字符串时,它不打印 \。另一件事是如何以正确的方式分配 string** res。当我为 sizeof(char*) 分配时,我看到的唯一方法是遍历字符串,但我只是想知道这是否可以在标记生成器函数中不遍历字符串 2 次进行分配。

我不想使用 strtok

typedef struct string string 在 .h 文件中

1 个答案:

答案 0 :(得分:1)

使用带有选项的 GCC 10.2.0 编译代码时:

gcc -O3 -g -std=c11 -Wall -Wextra -Werror …

我收到消息:

bs83.c:85:44: error: unknown escape sequence: '\040' [-Werror]
   85 |     string *fe = strCreate("A string \ tof");

正如我在评论中所指出的,字符串 "A string \ tof" 的格式不正确 — 您的编译器应该就此警告您。如果您想在字符串中使用反斜杠,请编写(例如)"A string \\ tof"。反斜杠空格没有定义的含义;它可能被解释为单个空格。也许您应该将参数打印到 strCreate() 以验证这一点。

您还需要在代码顶部附近添加 typedef struct string string; 才能使用 C 编译器(和头文件)进行编译。

这是您的代码的固定版本 — 由于我使用的编译选项,函数需要在定义之前进行 static 或声明;我将它们设为 static 是因为使它们成为非 static (IMO) 的唯一原因是如果它们是从另一个源文件访问的,然后它们将在标头中声明。这可能适用于您的代码 - 提到了标题。

这是有效的固定代码:

/* SO 6537-9584 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct string string;

struct string
{
    size_t length;
    size_t allocated;
    char *data;
};

static
string *strCreate(char *str)
{
    string *s = malloc(sizeof(string));
    s->length = strlen(str);
    s->allocated = s->length * 2;
    s->data = (char *)malloc(s->allocated + 1);
    memcpy(s->data, str, s->length);
    s->data[s->length] = '\0';
    return s;
}

static
string *strSubstring(string *str, size_t pos, size_t len)
{
    string *s = malloc(sizeof(string));
    s->length = len;
    s->allocated = s->length * 2;
    s->data = (char *)malloc(s->allocated + 1);
    memcpy(s->data, &str->data[pos], s->length);
    s->data[s->length] = '\0';
    return s;
}

static
char *strGet(string *str)
{
    return str->data;
}

static
size_t findFirst(string *str, char what, size_t pos)
{
    for (size_t i = pos; i < str->length; ++i)
    {
        if (str->data[i] == what)
            return i;
    }
    return -1;
}

static
string **strTokenizer(string *str)
{
    string **res;
    res = malloc(sizeof(char *) * 90); // *90 (token num)
    for (int i = 0; i < 90; i++) // i<90 (token num)
        res[i] = malloc(sizeof(char) * 100); // *100 (a token length)
    size_t first = 0;
    size_t i = 0;
    while (first < str->length)
    {
        int second = findFirst(str, ' ', first);
        if (second == -1)
            second = str->length;
        string *token = strSubstring(str, first, second - first);
        if (*strGet(token) != ' ')
            res[i] = token;
        first = second + 1;
        ++i;
    }
    return res;
}

int main(void)
{
    string *fe = strCreate("A string \\ tof");
    string **r = strTokenizer(fe);
    for (int i = 0; i < 4; ++i)
    {
        printf("[[%s]]\n", strGet(r[i]));
    }
    return 0;
}

输出为:

[[A]]
[[string]]
[[\]]
[[tof]]

注意在打印的字符串(和换行符)周围使用 [[]]。它可以更轻松地识别尾随空格和嵌入的回车符以及其他各种故障。

相关问题