如何拆分带有未知分隔符的字符串?
我需要拆分像
这样的字符串' 3.584731 60.739211,3.590472 60.738030,3.592740:60.736220',* *)
在* *之间我想输入一个分隔符,谁会用分隔符分割这个字符串。
例如
If *:*
3.584731 60.739211,3.590472 60.738030,3.592740
60.736220
我知道strtok()拆分了字符串。但我如何使用它代码不知道分隔符和用户必须插入它。这是我的代码。
PG_FUNCTION_INFO_V1(benchmark);
Datum
benchmark(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tupdesc;
AttInMetadata *attinmeta;
//As Counters
int i = 0, j = 0;
//To get the every SingleString from the Table
char *k = text_to_cstring(PG_GETARG_TEXT_P(0));
//The Delimiter
char *c (0);
//the temporary "memory"
char * temp = NULL;
//The final result
//Need as an Array
//From ["x1 y1,x2 y2,...xn yn"] Split on the ','
//to ["x1 y1","x2 y2",..."xn yn"] Split on the ' '
//to the final ["x1","y1","x2","y2"..."xn","yn"]
char**result[a] = {0};
if (SRF_IS_FIRSTCALL())
{
{
MemoryContext oldcontext;
//create a function context for cross-call persistence
funcctx = SRF_FIRSTCALL_INIT();
//reqdim = (PG_NARGS() MAXDIM)
// SRF_RETURN_DONE(funcctx);
// switch to memory context appropriate for multiple function calls
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* total number of tuples to be returned */
funcctx->max_calls = PG_GETARG_UINT32(0);
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
"that cannot accept type record")));
//Still dont know what attinmeta is
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
MemoryContextSwitchTo(oldcontext);
}
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
attinmeta = funcctx->attinmeta;
result[a] = funcctx->result[a];
temp = funcctx->temp;
*k = funcctx->*k;
delim = funcctx->delim;
c = funcctx->c;
//here is the difficult part
if(*k)
{
temp = strtok(k,delim) //the delimiter
while (temp)
{
//palloc or malloc whats the difference ?
result[a] = palloc...
strcpy(result[a],temp)
temp = strtok (NULL,delim)
i++;
}
for (j = 0; j < i; j++)
printf("[%d] sub-string is %s\n", (j+1), result[j]);
for (j = 0; j < i; j++)
SRF_RETURN_NEXT(funcctx,result[a]);
}
else
{
SRF_RETURN_DONE(funcctx);
}
}
这是对的吗? palloc还是malloc?这种情况有什么不同以及如何使用它? 我试着做很多笔记,因为我希望你能理解这个:) 并且不要努力我刚刚开始使用程序:)
答案 0 :(得分:2)
PostgreSQL源代码是采取一些想法和模式的良好开端。当你想编写SETOF函数时,你应该从一些SETOF函数开始。 Google关键字为“SRF_RETURN_NEXT”。 PostgreSQL doc http://www.postgresql.org/docs/9.3/static/xfunc-c.html中有一些例子 - 您可以找到其他一些例子。
几年前我写过数组迭代器:
#include "funcapi.h" typedef struct generate_iterator_fctx { int4 lower; int4 upper; bool reverse; } generate_iterator_fctx; Datum array_subscripts(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(array_subscripts); /* * array_subscripts(array anyarray, dim int, reverse bool) */ Datum array_subscripts(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; MemoryContext oldcontext; generate_iterator_fctx *fctx; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int reqdim; int *lb, *dimv; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); reqdim = (PG_NARGS() MAXDIM) SRF_RETURN_DONE(funcctx); /* Sanity check: was the requested dim valid */ if (reqdim ARR_NDIM(v)) SRF_RETURN_DONE(funcctx); /* * switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); fctx = (generate_iterator_fctx *) palloc(sizeof(generate_iterator_fctx)); lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); fctx->lower = lb[reqdim - 1]; fctx->upper = dimv[reqdim - 1] + lb[reqdim - 1] - 1; fctx->reverse = (PG_NARGS() user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); fctx = funcctx->user_fctx; if (fctx->lower upper) { if (!fctx->reverse) SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->lower++)); else SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->upper--)); } else /* do when there is no more left */ SRF_RETURN_DONE(funcctx); }
注册:
CREATE FUNCTION array_subscripts(anyarray) RETURNS SETOF int AS 'MODULE_PATHNAME' LANGUAGE C STRICT; CREATE FUNCTION array_subscripts(anyarray, integer) RETURNS SETOF int AS 'MODULE_PATHNAME' LANGUAGE C STRICT; CREATE FUNCTION array_subscripts(anyarray, integer, bool) RETURNS SETOF int AS 'MODULE_PATHNAME' LANGUAGE C STRICT;
用法:
CREATE FUNCTION array_expand(anyarray) RETURNS SETOF anyelements AS $$ SELECT $1[i] FROM array_subscripts($1) g(i); $$ LANGUAGE SQL;
答案 1 :(得分:0)
请检查以下代码。希望它不言自明。
如果您在理解方面遇到任何困难,请告诉我们。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZ 128
int main()
{
char *op[SIZ]; //array to hold the o/p
int i = 0, j = 0; //used as counters
char input[] = "3.584731 60.739211, / 3.590472 60.738030,3.592740 / 60.736220"; //the input
char *delim = "/"; //the delimiter
char * temp = NULL;
temp = strtok(input, delim);
while (temp)
{
op[i] = malloc(SIZ);
strcpy(op[i], temp);
temp = strtok(NULL, delim);
i++;
}
for (j = 0; j < i; j++)
printf("[%d] sub-string is %s\n", (j+1), op[j]);
for (j = 0; j < i; j++)
free(op[j]);
return 0;
}
修改
0.5版。希望这个split_string()
函数能解决你的问题。现在,使用fgets()
来询问用户输入。阅读手册页here。它不应该太难。祝你好运。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZ 128
void split_string(char * ip, char * sep);
int main()
{
char input[] = "3.584731 60.739211, / 3.590472 60.738030,3.592740 / 60.736220"; //the input
char *delim = "/"; //the delimiter
split_string(input, delim);
return 0;
}
void split_string(char * ip, char * sep)
{
char * op[SIZ] = {0};
int i = 0, j = 0; //used as counters
char * temp = NULL;
if (ip)
{
temp = strtok(ip, sep);
while (temp)
{
op[i] = malloc(SIZ);
strcpy(op[i], temp);
temp = strtok(NULL, sep);
i++;
}
for (j = 0; j < i; j++)
printf("[%d] sub-string is %s\n", (j+1), op[j]);
for (j = 0; j < i; j++)
free(op[j]);
}
}