C++字符相同的输入给出不同的输出
C++ char same input giving different outputs
我有一个cpp类,它实现了Netezza用户定义的函数(此处为文档)。它接受一个参数,该参数将是某种日期格式的字符串,并将其转换为YYYYMMDD格式。如果它不是一个有效的日期,它将返回"99991231"。每当我在一些表上运行代码时,对于相同的输入,每次都会得到不同的输出。我想我没有看到一些记忆问题。
从逻辑上讲,我们将char数组retval设置为等于date命令的输出。如果它给出一个空输出,我们将设置为"99991231"。然后,我们将一个temp-char数组设置为retval的前9个字节(最后一个是null终止符)。然后,我们将其memcpy到ret->data(我们必须返回的结构的字符ptr)中。
#include <stdarg.h>
#include <string.h>
#include "udxinc.h"
#include "udxhelpers.h"
using namespace nz::udx_ver2;
class Dateconvert: public Udf
{
public:
Dateconvert(UdxInit *pInit) : Udf(pInit){}
~Dateconvert(){}
static Udf* instantiate(UdxInit *pInit);
virtual ReturnValue evaluate()
{
StringReturn* ret = stringReturnInfo();
StringArg *str;
str = stringArg(0);
int lengths = str->length;
char *datas = str->data;
string tempData = datas;
string shell_arg = tempData;
shell_arg = "'" + shell_arg + "'";
string cmd="date -d " + shell_arg + " +%Y%m%d 2>/dev/null";
FILE *ls = popen(cmd.c_str(), "r");
char retval[100];
retval[0]='n';
fgets(retval, sizeof(retval), ls);
if(!isdigit(retval[0]))
{
strcpy(retval,"99991231");
}
pclose(ls);
char temp1[9];
memcpy(temp1, retval, 8);
temp1[8]=' ';
ret->size = 9;
memcpy(ret->data, temp1, 9);
NZ_UDX_RETURN_STRING(ret);
}
};
Udf* Dateconvert::instantiate(UdxInit *pInit)
{
return new Dateconvert(pInit);
}
当我在Netezza中对一个不同的值运行UDF时,它会给我预期的输出。然而,当我在多个列上运行它时,输出有时是正确的,有时是错误的,看起来是随机的。我认为这一定是内部内存问题。示例:
input output
1) 8/11/2014 20140811
2) 8/11/2014 20140811
Fri 10/17/14 20141017
3) 8/11/2014 99991231
Fri 10/17/14 20141017
4) 8/11/2014 20140811
Fri 10/17/14 20141017
5) 8/11/2014 20140811
Fri 10/17/14 20141017
9-Nov-12 20121109
6) 8/11/2014 20140811
Fri 10/17/14 20141017
9-Nov-12 01241109 (what?)
7) 8/11/2014 99991231
Fri 10/17/14 20141017
9-Nov-12 20121109
只要函数只有一个调用,它就会返回正确的答案。当它被多次调用时,问题就出现了,我不明白。为什么会有什么遗留下来?在evaluate函数结束时,将返回值大小从9更改为8并不能解决问题。
这是调用函数的格式:
select a.val1, DATECONVERT(a.val1)
from
(
select '8/11/2014' as val1 from calendar
union
select 'Fri 10/17/14' as val1 from calendar
union
select '9-Nov-12' as val1 from calendar
) a
并为UDF:编译命令
nzudxcompile /export/home/nz/dateconvert.cpp -o dateconvert.o --sig "Dateconvert(VARCHAR(200))" --version 2 --return "VARCHAR(200)" --class Dateconvert --user user1 --pw mypw --db mydb
切入正题,这里的问题在于如何分配tempData。
StringReturn* ret = stringReturnInfo();
StringArg *str;
str = stringArg(0);
int lengths = str->length;
char *datas = str->data;
string tempData = datas;
StringArg不存储以NUL结尾的字符串,而是提供长度,并希望您自己管理。
select a.val1, ADMIN.DATECONVERT(a.val1)
from
(
select '09-Nov-12'::varchar(20) as val1
union all
select '9-Nov-12'::varchar(20) as val1
) a;
VAL1 | DATECONVERT
-----------+-------------
09-Nov-12 | 20121109
9-Nov-12 | 01221109
(2 rows)
在本例中,发生的情况是,当第二个较短的字符串被分配给tempData时,较长的第一个字符串仍有一个字符挂在内存中。最后挂着的"2"像这样添加:
09-Nov-12
9-Nov-122
其中每一个都是date的有效输入,这很好地解释了您所看到的输出。
$ date -d 09-Nov-12 +%Y%m%d
20121109
$ date -d 09-Nov-122 +%Y%m%d
01221109
将作业更改为使用该长度,这样就可以避免问题。
//string tempData = datas;
string tempData(datas, datas+lengths);
然后你得到了预期的输出:
select a.val1, ADMIN.DATECONVERT(a.val1)
from
(
select '09-Nov-12'::varchar(20) as val1
union all
select '9-Nov-12'::varchar(20) as val1
) a;
VAL1 | DATECONVERT
-----------+-------------
09-Nov-12 | 20121109
9-Nov-12 | 20121109
(2 rows)
话虽如此,我不知道您在这个UDF中采用的总体方法是否可行。正如我在上面运行的那样,这些行是在主机上生成的,因为它们在SQL中是硬编码的,并且日期在主机上肯定可用。然而,您不能期望在MPP后端(我们通常称之为SPU)上运行的代码具有与主机上相同的linux实用程序可用性,或者如果它们存在,则它们具有相同的功能。
如果我将日期移动到一个实际的表中,UDF将在SPU上对其进行操作,它将给我错误的输出,因为SPU映像上的date命令与主机的命令有很大不同,并且根本不理解这种输入格式。
select a.col1, admin.DATECONVERT(a.col1) from calendar a;
COL1 | DATECONVERT
-----------+-------------
09-Nov-12 | 99991231
9-Nov-12 | 99991231
(2 rows)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- C++,在int数组中输入字符串或字符会输出0,而不是ascii或error
- C++多个输入和输出
- 制定带有输入和输出C++的时间表
- 字符的输入/输出操作
- 如何读取单个字符并在输入两个字符序列时输出? 使用 while 循环和C++
- 遇到此问题时遇到困难:允许用户输入数组的值并使用 for,而循环也输出输入的最大数字
- 在数组中输入 n 个整数的列表,并以类似于钟摆来回移动的方式排列它们. 输入-1 3 2 5 4,输出5 3 1 2 4
- C++ 中的矢量重复输出输入
- 类中的重载函数(Students())是输出输入的信息,但它不起作用
- 函数以相反的顺序输出输入问题,并改进算法以解释相等的数字
- 在输出输入文本时对齐输入的文本
- 将多个文件输出/输入到桌面
- 输出输入c++的最短方式
- 将Crypto++中自动种子PNRG的输出输入一个字符串
- 输出输入的拼接版本