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 文件中
答案 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]]
注意在打印的字符串(和换行符)周围使用 [[
和 ]]
。它可以更轻松地识别尾随空格和嵌入的回车符以及其他各种故障。