【问题标题】:Trouble using sprintf()使用 sprintf() 时遇到问题
【发布时间】:2014-01-08 13:29:39
【问题描述】:

我正在使用 sprintf 将 int 转换为字符串。然后我将字符串传递给函数 "enqueue" 。此函数接受字符串并将其插入到 FIFO 链表中。问题是,当我使用显式字符串调用enqueue() 时,它可以完美运行,但是当我使用sprintf 字符串缓冲区调用它时,它会以某种方式覆盖队列中已经存在的元素。

typedef struct
{
    char *movie;
    char *pkt;
} packet ;

struct node
{
    packet page;
    struct node *next;
} *front= NULL, *rear=NULL;

void display_fifo(){
    struct node *t;
    t=front;
    while ((front==NULL)|| (rear==NULL))
            {
            printf("\nempty fifo\n");
            return ;
            }
    while (t!=NULL)
    {
            printf("->%s\t %s\n", t->page.movie, t->page.pkt);
            t= t-> next;
    }
}
void enqueue(char * movie, char *pkt)
{
    packet new;
    new.movie= movie;
    new.pkt=pkt;
    struct node *p;
    p= (struct node*)malloc(sizeof(struct node));
    p->page= new;
    p->next= NULL;

    if (rear== NULL|| front ==NULL)
            front=p;
    else
            rear->next=p;
    rear=p;
}
void main(){
    char buff[10];
    int i;
    for (i=1;i<=5;i++){
            sprintf(buff, "%d", i);
            enqueue("1", buff);
            printf("***\n");
            display_fifo();
    }

}

上面写的代码我得到的输出:

*** ->1 1 *** ->1 2 ->1 2 *** ->1 3 ->1 3 ->1 3 *** ->1 4 ->1 4 ->1 4 ->1 4 *** ->1 5 ->1 5 ->1 5 ->1 5 ->1 5

sprintf 是否有替代方法返回我应该使用的字符指针,或者我的enqueue() 有问题?

【问题讨论】:

    标签: c string linked-list


    【解决方案1】:

    问题是你使用了一个 char* buff 并且在你的 enqueue 函数中你复制了指针!

    new.pkt=pkt;
    

    这是错误的,每次更改 buff 时,所有其他节点值都会更改,因为它们都引用相同的缓冲区。 你必须改变这一行!

    new.pkt = pkt;
    

    new.pkt = malloc(strlen(pkt));
    strcpy(new.pkt,pkt);
    

    【讨论】:

    • enqueue 函数分配内存可能是一个更好的主意,是的。我会建议使用strdup 而不是malloc+strcpy(只是因为它是一个单独的调用)。
    【解决方案2】:

    问题是您一直重复使用同一个缓冲区。你总是通过引用buff 得到相同的指针,所以你不断地覆盖你的字符串。

    您可以使用malloc 来创建新缓冲区,也可以使用非标准GNU 扩展asprintf(至少在Linux 系统和Mac OS X 上可用,但肯定不是Windows)来分配必要的内存。在这两种情况下,您都需要在使用完指针后free

    另外,您应该避免使用sprintf 而使用snprintf 来保护您的程序免受缓冲区溢出。 (如果您不知道缓冲区的大小,我建议您不要使用 sprintf。)

    asprintf 的调用如下所示:

    char* buffer;
    asprintf(&buffer, "%d", i);
    // do stuff with buffer; it now points to a number string
    free(buffer);
    

    malloc+snprintf 稍微复杂一些,因为您需要确定要分配的缓冲区的大小:

    char* buffer;
    int i, allocSize;
    // log10(number) is the digit count in `number` minus one, so
    // we add two to account for the null terminator
    allocSize = log10(i) + 2;
    buffer = malloc(allocSize * sizeof *buffer);
    snprintf(buffer, allocSize, "%d", i);
    // do stuff with buffer; it now points to a number string
    free(buffer);
    

    【讨论】:

    • 我还建议不要使用诸如“new”之类的参数名称,这可能会与 C++ 关键字产生冲突。以防您以后决定在另一个 C++ 项目中重用代码。
    【解决方案3】:

    您的packet 存储的是指向字符的指针,而不是字符本身。并且指针始终指向buff

    要么 malloc 一些内存来保存字符,要么添加使 pkt 成为 char 的数组。

    【讨论】:

      猜你喜欢
      • 2015-01-27
      • 2014-12-05
      • 1970-01-01
      • 2012-02-21
      • 2021-11-08
      • 2011-03-09
      • 2013-01-30
      • 2016-11-13
      • 2016-07-21
      相关资源
      最近更新 更多