C编程字符串、指针和分配
我认为这个问题仅仅是内存分配不足的问题 (可能跳到底部,阅读最后一个问题以获得一些简单的建议) 我正在编写这个程序,读取用户输入的文件。如果文件“包括”其他文件,则也将读取这些文件。为了检查另一个文件是否包含文件,我解析字符串的第一个单词。为此,我编写了一个函数,返回解析后的单词,并传入一个指针,该指针设置为下一个单词的第一个字母。例如,考虑字符串: “包含foo”注意文件只能包含1个其他文件 firstWord==include,chPtr==f 我的算法通过解析第一个单词来测试字符串是否与“include”相等,然后解析第二个单词来测试文件的有效性,并查看文件是否已被读取 现在,我的问题是许多文件正在被读取,chPtr被覆盖。因此,当我返回指向下一个单词的指针时。下一个单词有时会包含上一个文件的最后几个字符。考虑名为TestFiel1和Pigs:< /P>的示例文件C编程字符串、指针和分配,c,string,parsing,malloc,deep-copy,C,String,Parsing,Malloc,Deep Copy,我认为这个问题仅仅是内存分配不足的问题 (可能跳到底部,阅读最后一个问题以获得一些简单的建议) 我正在编写这个程序,读取用户输入的文件。如果文件“包括”其他文件,则也将读取这些文件。为了检查另一个文件是否包含文件,我解析字符串的第一个单词。为此,我编写了一个函数,返回解析后的单词,并传入一个指针,该指针设置为下一个单词的第一个字母。例如,考虑字符串: “包含foo”注意文件只能包含1个其他文件 firstWord==include,chPtr==f 我的算法通过解析第一个单词来测试字符串是否与“
让CHPTR最初等于TestFIL-1,现在考虑对“包含伪”的解析:
提取第一个字将==include,并且chPtr将被覆盖以指向伪造的b。因此,chPtr将等于bogus'\0'l e-1。l e-1是testfile-1的最后几个字符,因为每次调用我的函数时,chPtr都指向相同的内存地址。这对我来说是个问题,因为当我解析伪代码时,chPtr将指向l。以下是我的函数代码:char* extract_word(char** chPtr, char* line, char parseChar)
//POST: word is returned as the first n characters read until parseChar occurs in line
// FCTVAL == a ptr to the next word in line
{
int i = 0;
while(line[i] != parseChar && line[i] != '\0')
{
i++;
}
char* temp = Malloc(i + 1); //I have a malloc wrapper to check validity
for(int j = 0; j < i; j++)
{
temp[j] = line[j];
}
temp[i+1] = '\0';
*chPtr = (line + i + 1);
char* word = Strdup(temp); //I have a wrapper for strdup too
return word;
char*extract\u单词(char**chPtr,char*line,char parseChar)
//POST:word作为读取的前n个字符返回,直到第行出现parseChar
//FCTVAL==行中下一个单词的ptr
{
int i=0;
while(第[i]!=parseChar行和第[i]!='\0'行)
{
i++;
}
char*temp=Malloc(i+1);//我有一个Malloc包装来检查有效性
对于(int j=0;j
那么,我的问题诊断正确吗?如果正确,我是否制作chPtr的深度副本?还有,我如何制作chPtr的深度副本
非常感谢!char*temp=Malloc(i+1);//我有一个Malloc包装来检查有效性
char* temp = Malloc(i + 1); //I have a malloc wrapper to check validity
for(int j = 0; j < i; j++)
{
temp[j] = line[j];
}
temp[i+1] = '\0'; <------- subscript out of range replace with temp[i] = '\0';
对于(int j=0;jtemp[i+1]='\0';不清楚您的问题出在哪里。但是您可以使用工具来帮助查找它
Valgrind就是这样一个(免费)工具。它将检测各种内存访问错误。(它可能不会发现您的临时[i+1]='\0'错误,因为这不是“非常错误”)
我们的工具是另一个工具。它发现Valgrind无法发现的错误(例如,它应该找到您的错误临时任务)。虽然它是商业版,但评估版处理的程序规模较小,可能适合您。(我在家,不记得限制).如果我理解正确,您希望扫描一个文件,当遇到“include”指令时,您希望无限期地扫描“include”指令中指定的文件,等等,以获取任何级别的包含,即读取一个文件,其中可能包含其他文件,而其他文件又可能包含其他文件
如果是这样(如果我错了,请纠正),那么这是一个典型的递归问题。递归的优点是所有变量都是在堆栈上创建的,并且在堆栈展开时自然释放
以下代码不需要malloc或free,也不需要复制任何内容:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INCLUDE "include"
#define INCOFFSET 7
static void
process_record (char *name, char *buf)
{
// process record here
printf ("%s:%s\n", name, buf);
}
// change this to detect your particular include
static int
isinclude (char *buf)
{
//printf ("%s:Record %s INCLUDE=%s INCOFFSET=%d\n", __func__, buf, INCLUDE,
// INCOFFSET);
if (!strncmp (buf, INCLUDE, INCOFFSET))
{
//printf ("%s:Record == include", __func__);
return 1;
}
return 0;
}
static int
read_file (char *name)
{
//printf ("%s:File %s\n", __func__, name);
FILE *fd = fopen (name, "r");
if (!fd)
{
printf ("%s:Cannot open %s\n", __func__, name);
return -1;
}
char buf[1024];
ssize_t n;
while (fgets (buf, sizeof (buf), fd))
{
size_t n = strcspn (buf, "\n");
buf[n] = '\0';
//printf ("%s:Buf %s\n", __func__, buf);
if (isinclude (buf))
{
read_file (buf + (INCOFFSET + 1));
}
else
{
process_record (name, buf);
}
}
fclose (fd);
return 0;
}
int
main (int argc, char *argv[])
{
int ret = read_file (argv[1]);
if (ret < 0)
{
exit (EXIT_FAILURE);
}
exit (EXIT_SUCCESS);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义包含“包含”
#定义收入补偿7
静态空隙
过程记录(字符*名称,字符*buf)
{
//这里有流程记录
printf(“%s:%s\n”,名称,buf);
}
//更改此选项以检测您的特定包含
静态整数
i包括(字符*buf)
{
//printf(“%s:记录%s INCLUDE=%s INCOFFSET=%d\n”),\uu func\uu,buf,INCLUDE,
//收入补偿);
如果(!strncmp(基本计量单位,包括,收入补偿))
{
//printf(“%s:Record==include”,\uuuuu func\uuuuu);
返回1;
}
返回0;
}
静态整数
读取文件(字符*名称)
{
//printf(“%s:文件%s\n”,函数名);
文件*fd=fopen(名称,“r”);
如果(!fd)
{
printf(“%s:无法打开%s\n”,函数名);
返回-1;
}
char-buf[1024];
(三);
while(fgets(buf、sizeof(buf)、fd))
{
尺寸=strcspn(buf,“\n”);
buf[n]='\0';
//printf(“%s:Buf%s\n”,_uuufunc_uuu,Buf);
如果(包括(buf))
{
读取_文件(buf+(INCOFFSET+1));
}
其他的
{
过程记录(名称,buf);
}
}
fclose(fd);
返回0;
}
int
main(int argc,char*argv[])
{
int-ret=read_文件(argv[1]);
如果(ret<0)
{
退出(退出失败);
}
退出(退出成功);
}
感谢您找到此项。但这并不能解决我的问题,因为我的chPtr仍在被覆盖。我在文件中没有看到char*chPtr,您提供的代码中正在覆盖该值。此外,如果字符串遇到空终止符,您将传回指向缓冲区范围外的下一个第二个值,即我将介绍未定义的行为。为什么您Strdup(temp)
然后返回复制副本?如果没有其他内容,您永远不会free(temp)
,因此您正在泄漏内存,而实际上return temp;
也一样好(并为您节省新分配的开销)。您的意思是什么“这对我来说是一个问题,因为当我解析伪代码时,chPtr将指向l”当找到“\0”时,你会停止解析吗?