2014-10-29 86 views
2

我可能错过了一些明显的东西,但是我的C很生疏,我没有任何运气能够理解这一点。我有一个循环,我想遍历来自libdvdnav的uint64_t值的数组,然后格式化值并将它们插入到字符串中。通过指向数组的指针取消引用数组值

为libdvdnav头定义函数我打电话正是如此:

uint32_t dvdnav_describe_title_chapters(dvdnav_t *self, int32_t title, uint64_t **times, uint64_t *duration); 

这里是我如何定义使用的变量,并在呼叫(dvdnavargs[0]了定义并初始化其他地方):

uint64_t *times; 
uint64_t duration; 
uint32_t times_array_len; 

times_array_len = dvdnav_describe_title_chapters(dvdnav, atoi(args[0]), &times, &duration); 

下面的代码似乎工作,并编译&运行的w/o错误,但当然只是阵列中的第一个值被插入:

int i = 0; 
uint64_t a_time = times[0]; 

while(i < times_array_len){ 

    char time_json[100]; 
    sprintf(time_json, "{\"chapter\":\"%d\",\"time\":\"%u\"},", i, a_time); 
    strcat(payload, time_json); 
    i++; 
} 

如果我修改此选择它仍然编译干净的阵列中的每个值,但在运行时抛出一个段错误:

int i = 0; 

while(i < times_array_len){ 

    char time_json[100]; 
    sprintf(time_json, "{\"chapter\":\"%d\",\"time\":\"%u\"},", i, times[i]); 
    strcat(payload, time_json); 
    i++; 
} 

我想也许有什么东西在,这是数组元素之一一个问题(一个太大的值,意外的,NULL等),但即使我用一个已知合理的元素(比如0)替换变量i它仍然存在段错误。我确信在这里会有无数其他的改进(比如更安全的分配,溢出保护等等),但我努力破译的部分是将这些值从数组中取出并存入我的格式化字符串中。

+0

“在运行时会引发段错误” - 在哪里?启动一个调试器。 – 2014-10-29 15:19:59

+2

'strcat()'调用看起来很可怕... – unwind 2014-10-29 15:20:38

+1

有2个可能的问题。首先,你在计算'times_array_len'时会出现一些错误,'times'就会小些。其次,您的负载太短,无法保存所有这些数据。 – 2014-10-29 15:21:15

回答

1

​​如何定义?如果它太短而不能包含字符串,那么你将会崩溃。 您可以通过多种方式解决这个:

1)既然你现在JSON条目的数量将是times_array_len您可以使用malloc堆与大小分配串100 * times_array_len - 再次,你绝不会超过(,不知道是否使用固定长度的json缓冲区是否智能),那么strcat应该是安全的。您甚至可以直接将sprintf呼叫直接拨入​​缓冲区,因为您现在将通过跟踪sprintf的返回值来确定偏移量。是这样的:

#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char** argv) 
{ 
    __int64 pTimes[] = { 1, 2, 3 ,4}; 
    size_t nTimeCount = sizeof(pTimes)/sizeof(pTimes[0]); 
    size_t nPayloadOffset = 0; 
    char* pPayload = (char*)malloc(100 * nTimeCount); 
    if (pPayload) 
    { 
     for (size_t nTimeIndex = 0; nTimeIndex < nTimeCount; ++nTimeIndex) 
     { 
      nPayloadOffset += sprintf(&pPayload[nPayloadOffset], "{\"chapter\":\"%d\",\"time\":\"%u\"},", nTimeIndex, pTimes[nTimeIndex]); 
     } 
     printf("%s\n", pPayload); 
     free(pPayload); 
    } 
    return EXIT_SUCCESS; 
} 

2)为了避免运行在上一个单一的入口100字符长度你可能是明智的,并与初始大小分配pPlayoad,然后计算每个条目的大小和重新分配pPayload如果它变得太短

3)使用C++和std::stringstream如果C++是一个选项:

#include <sstream> 
#include <iostream> 

int main(int argc, char** argv) 
{ 
    __int64 pTimes[] = { 1, 2, 3 ,4}; 
    size_t nTimeCount = sizeof(pTimes)/sizeof(pTimes[0]); 
    size_t nPayloadOffset = 0; 
    std::stringstream JsonStream; 
    for (size_t nTimeIndex = 0; nTimeIndex < nTimeCount; ++nTimeIndex) 
    { 
     JsonStream << "{\"chapter\":\"" << nTimeIndex << "\",\"time\":\"" << pTimes[nTimeIndex] << "\"},"; 
    } 
    std::cout << JsonStream.str() << std::endl; 
    return EXIT_SUCCESS; 
}