存储数据和打印双指针
storing data and printing a double pointer
char** splitInput = malloc(255 * sizeof(char*));
...
while(token != NULL)
{
splitInput[i] = token;
token = strtok(NULL, " ");
i++;
}
我不知道这段代码为什么有效。在我之前的版本中,
while(token != NULL)
{
*splitInput = token;
token = strtok(NULL, " ");
*splitInput++;
}
但是它没有存储任何东西。为什么?这两个代码有什么区别?
我如何打印 splitInput 的内容:
for(; *splitInput != NULL; *splitInput++){
printf("%s\n", *splitInput);
}
我可以在第一个代码中打印 splitInput 的内容,但在第二个代码中失败。为什么?
如果您还没有弄清楚,差异是由于使用数组索引与指针算法的不同。当你使用数组索引时,splitInput
指向的地址永远不会改变。
但是,当使用 post 增量 运算符时,您每次调用 *splitInput++
时都会更改 splitInput
的地址。它与调用 *splitInput = token; splitInput += 1;
相同 因此,当您完成对输入的标记后,splitInput
指向 上次分配后的下一个指针地址 token
.
无论何时分配内存,对于分配的任何内存块,您都有 2 责任:(1) 始终保留指向起始地址的指针 对于内存块,(2) 它可以 访问 ,然后在不再需要时 释放 。您违反了规则 (1),该规则阻止您访问您分配的块的开头(并造成永久内存泄漏)
你怎么处理这个?要么记录分配的令牌数量,然后 reset (备份)到你的块的开头,或者更好,简单地 使用单独的指针和post-increment运算符,从而保留splitInput
.
中内存块的原始地址
一个简短的例子将说明:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 4096
int main (void) {
/* allocate & initialize */
char **splitInput = calloc (255, sizeof *splitInput),
**sp = splitInput, /* create pointer to splitInput */
buf[MAX] = "", *delim = " \n";
int n = 0;
if (!splitInput) { /* validate all allocations */
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
while (fgets (buf, MAX, stdin)) {
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim)) {
*sp++ = p;
if (++n == MAX) /* always protect against writing beyond bounds */
goto full;
}
}
full:
for (int i = 0; i < n; i++)
printf ("splitInput[%3d] : %s\n", i, splitInput[i]);
free (splitInput); /* you allocate it --> you free it */
return 0;
}
示例输入
$ cat dat/fleas
my dog has fleas
例子Use/Output
$ ./bin/ptrinc < dat/fleas
splitInput[ 0] : my
splitInput[ 1] : dog
splitInput[ 2] : has
splitInput[ 3] : fleas
当然,使用数组索引,你完全可以去掉sp
,简单的使用:
while (fgets (buf, MAX, stdin)) {
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim)) {
splitInput[n++] = p;
if (n == MAX)
goto full;
}
}
检查一下,如果您有任何其他问题,请告诉我。
char** splitInput = malloc(255 * sizeof(char*));
...
while(token != NULL)
{
splitInput[i] = token;
token = strtok(NULL, " ");
i++;
}
我不知道这段代码为什么有效。在我之前的版本中,
while(token != NULL)
{
*splitInput = token;
token = strtok(NULL, " ");
*splitInput++;
}
但是它没有存储任何东西。为什么?这两个代码有什么区别?
我如何打印 splitInput 的内容:
for(; *splitInput != NULL; *splitInput++){
printf("%s\n", *splitInput);
}
我可以在第一个代码中打印 splitInput 的内容,但在第二个代码中失败。为什么?
如果您还没有弄清楚,差异是由于使用数组索引与指针算法的不同。当你使用数组索引时,splitInput
指向的地址永远不会改变。
但是,当使用 post 增量 运算符时,您每次调用 *splitInput++
时都会更改 splitInput
的地址。它与调用 *splitInput = token; splitInput += 1;
相同 因此,当您完成对输入的标记后,splitInput
指向 上次分配后的下一个指针地址 token
.
无论何时分配内存,对于分配的任何内存块,您都有 2 责任:(1) 始终保留指向起始地址的指针 对于内存块,(2) 它可以 访问 ,然后在不再需要时 释放 。您违反了规则 (1),该规则阻止您访问您分配的块的开头(并造成永久内存泄漏)
你怎么处理这个?要么记录分配的令牌数量,然后 reset (备份)到你的块的开头,或者更好,简单地 使用单独的指针和post-increment运算符,从而保留splitInput
.
一个简短的例子将说明:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 4096
int main (void) {
/* allocate & initialize */
char **splitInput = calloc (255, sizeof *splitInput),
**sp = splitInput, /* create pointer to splitInput */
buf[MAX] = "", *delim = " \n";
int n = 0;
if (!splitInput) { /* validate all allocations */
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
while (fgets (buf, MAX, stdin)) {
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim)) {
*sp++ = p;
if (++n == MAX) /* always protect against writing beyond bounds */
goto full;
}
}
full:
for (int i = 0; i < n; i++)
printf ("splitInput[%3d] : %s\n", i, splitInput[i]);
free (splitInput); /* you allocate it --> you free it */
return 0;
}
示例输入
$ cat dat/fleas
my dog has fleas
例子Use/Output
$ ./bin/ptrinc < dat/fleas
splitInput[ 0] : my
splitInput[ 1] : dog
splitInput[ 2] : has
splitInput[ 3] : fleas
当然,使用数组索引,你完全可以去掉sp
,简单的使用:
while (fgets (buf, MAX, stdin)) {
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim)) {
splitInput[n++] = p;
if (n == MAX)
goto full;
}
}
检查一下,如果您有任何其他问题,请告诉我。