C编程字符串、指针和分配

C编程字符串、指针和分配,c,string,parsing,malloc,deep-copy,C,String,Parsing,Malloc,Deep Copy,我认为这个问题仅仅是内存分配不足的问题 (可能跳到底部,阅读最后一个问题以获得一些简单的建议) 我正在编写这个程序,读取用户输入的文件。如果文件“包括”其他文件,则也将读取这些文件。为了检查另一个文件是否包含文件,我解析字符串的第一个单词。为此,我编写了一个函数,返回解析后的单词,并传入一个指针,该指针设置为下一个单词的第一个字母。例如,考虑字符串: “包含foo”注意文件只能包含1个其他文件 firstWord==include,chPtr==f 我的算法通过解析第一个单词来测试字符串是否与“

我认为这个问题仅仅是内存分配不足的问题

(可能跳到底部,阅读最后一个问题以获得一些简单的建议)

我正在编写这个程序,读取用户输入的文件。如果文件“包括”其他文件,则也将读取这些文件。为了检查另一个文件是否包含文件,我解析字符串的第一个单词。为此,我编写了一个函数,返回解析后的单词,并传入一个指针,该指针设置为下一个单词的第一个字母。例如,考虑字符串:

“包含foo”注意文件只能包含1个其他文件

firstWord==include,chPtr==f

我的算法通过解析第一个单词来测试字符串是否与“include”相等,然后解析第二个单词来测试文件的有效性,并查看文件是否已被读取

现在,我的问题是许多文件正在被读取,chPtr被覆盖。因此,当我返回指向下一个单词的指针时。下一个单词有时会包含上一个文件的最后几个字符。考虑名为TestFiel1和Pigs:< /P>的示例文件

让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”时,你会停止解析吗?