我正在c程序中使用两个函数,但是很难让它们合作。我的第一个函数遍历一个csv文件,并使用strtok()来基于“,”定界符来分隔标记。每个令牌都保存到大小为3的字符数组中,如果特定令牌与目标令牌不匹配,则会读取下一行输入并对其进行令牌化,然后用新的输入令牌覆盖字符数组。
以下是使用的全局变量:
def create_train_data():
a_int = np.random.randint(largest_number/2) # int version
return a
np.random.seed(seed=int(time.time()))
for j in range(timesteps):
c = create_train_data()
这是第一个功能的代码:
char * stateCityZip[3];
我的第二个功能只是尝试打印stateCityZip的值。但是,当我打印这些值时,它们显示为空白。解决此问题的唯一方法是取消对
的注释int zipToCity(char * zip)
{
char line[1024];
char * tok = malloc(20 * sizeof(char));
FILE * file = fopen("cityzip.csv", "r");
while (fgets(line, sizeof(line), file))
{
//State
tok = strtok(line, ",");
stateCityZip[0] = tok;
//City
tok = strtok(NULL, ",");
stateCityZip[1] = tok;
//Zip
tok = strtok(NULL, ",");
stateCityZip[2] = tok;
if (strcmp(stateCityZip[2], newZip) == 0) {
//printf("Found %s, %s\n", stateCityZip[0], stateCityZip[1]);
strlen(stateCityZip[1]));
return 1;
}
}
return 0;
}
行。
这是我第二个函数的代码:
//printf("Found %s, %s\n", stateCityZip[0], stateCityZip[1]);
输出:
int main() {
printf("City: [%s]", stateCityZip[1]);
printf("State: [%s]", stateCityZip[0]);
return 0;
}
答案 0 :(得分:1)
strtok
返回指向其输入的子字符串的指针。因此,您所有的tok
值都是指向line
的一部分的指针,这些指针具有自动存储持续时间,因此stateCityZip
中的指针一旦zipToCity
返回就全部失效。
(实际上,如果文件中有多行,tok
指针将在您前进到下一行时立即失效,因为它们现在指向新行中任意行的子字符串缓冲区。)
相反,您应该使用strdup
将令牌的副本分配为新字符串,并将从strdup
返回的指针保存到stateCityZip
中。
重要说明:strdup
需释放free
分配的字符串。如果stateCityZip
是全局的,那么您可以不用释放它们而逃脱(当进程退出时,最后的内存将被释放)。但是,如果再次调用zipToCity
,它将覆盖stateCityZip
中的指针并泄漏相应的字符串。因此,在分配新值之前,首先free()
中stateCityZip
中的任何字符串(如果它们为NULL,则很好,因为free(NULL)
是无操作)可能是最安全的。 / p>
关于内存分配:您的示例代码对malloc
进行了tok
调用,这是完全多余的,并且由于您覆盖了{{1}返回的指针,因此肯定会泄漏},而无需malloc
对其进行编辑。
而且,关于良好的编码实践,free
可能会失败。您需要检查返回的fopen
是否为NULL。 (如果为NULL,FILE *
会告诉您原因。)并且您还需要errno
fclose
,您似乎也没有这样做。
更一般地:此代码似乎根本都没有进行任何错误检查。每次调用任何标准库函数(或与此有关的任何函数!)时,您都需要考虑该函数可能无法完成应做的事情,如何做到告诉您(通常会很好地记录故障行为,因此请务必阅读文档),以及程序失败时要执行的操作。如果文件不存在或无法读取该怎么办?如果它包含没有逗号分隔的行,或者不包含预期的字段数?如果在处理文件的一半时间内存不足,或者FILE *
由于堆内存不足而无法复制字符串,应该怎么办?如果您不考虑这些问题,或者忘记处理这些问题,则可以在一切正常的“快乐案例”中解决它,但迟早它会回来并咬住您-通常在最坏的情况下可能的时间。