C 将结构数组发送到函数时访问该数组时出现问题

C 将结构数组发送到函数时访问该数组时出现问题,c,arrays,struct,member-access,C,Arrays,Struct,Member Access,我是一个新的C程序员,所以你必须原谅我缺乏知识。慢慢地但肯定地,我正在进步。我想知道为什么在我将结构的成员发送到一个打算修改它们的函数后,我无法访问它们。此问题发生在下面显示的代码中。基本上,我的程序分析XML文档并寻找某些模式来提取文本。在我的主函数中,我使结构:artinfo-artIn[128]={}在我的头文件中定义为: #ifndef FILE_TABLE_H #define FILE_TABLE_H #ifdef __cplusplus extern "C" { #endif

我是一个新的C程序员,所以你必须原谅我缺乏知识。慢慢地但肯定地,我正在进步。我想知道为什么在我将结构的成员发送到一个打算修改它们的函数后,我无法访问它们。此问题发生在下面显示的代码中。基本上,我的程序分析XML文档并寻找某些模式来提取文本。在我的主函数中,我使结构:
artinfo-artIn[128]={}在我的头文件中定义为:

#ifndef FILE_TABLE_H
#define FILE_TABLE_H
#ifdef  __cplusplus
extern "C" {
#endif
    typedef struct article_info {
        char author1[512];
        char author2[512];
        char author3[512];
        char author4[512];
        char author5[512];
        char author6[512];
        char title[2048];
        char version[4];
        char year[4];
        char page[64];
        char abstract[4096];
        char notes[4096];
} artinfo;

#ifdef  __cplusplus
}
#endif
#endif  
在实例化并用memset清除它之后,我继续将它发送给另一个函数,该函数将提取文本并打算将其放回结构中。功能如下所示

bool readerParser(FILE *input, FILE *output, textlbuf *lbuf, artinfo *artIn[]){

int isNewline;             /* Boolean indicating we've read a CR or LF */
long lFileLen;             /* Length of file */
long lIndex;               /* Index into cThisLine array */
long lLineCount;           /* Current line number */
long lLineLen;             /* Current line length */
long lStartPos;            /* Offset of start of current line */
long lTotalChars;          /* Total characters read */
char cThisLine[BUFSIZE];     /* Contents of current line */
char *cFile;                  /* Dynamically allocated buffer (entire file) */
char *cThisPtr;               /* Pointer to current position in cFile */
char cNextLine[BUFSIZE];
char buffer[BUFSIZE];
char title[] = "<text top=\"245\"";
char ending[] = "$";
char author[] = "$</text>";
bool tfound, afound;
char *match, *cNextLinePtr;
long lNextLineCount;
int i, j;

//initialize some values
tfound = false;
afound = false;
fseek(input, 0L, SEEK_END);  /* Position to end of file */
lFileLen = ftell(input);     /* Get file length */
rewind(input);               /* Back to start of file */
memset(&cThisLine,0,sizeof(cThisLine));
memset(&cNextLine,0,sizeof(cNextLine));
memset(&buffer,0,sizeof(buffer));

printf("TEST: Entered read parser\n");
cFile = calloc(lFileLen + 1, sizeof(char));
printf("TEST:\n");
if(cFile == NULL )
{
    printf("\nInsufficient memory to read file.\n");
    return 0;
}

fread(cFile, lFileLen, 1, input); /* Read the entire file into cFile */
printf("TEST: read the file in\n");
lLineCount  = 0L;
lTotalChars = 0L;

cThisPtr    = cFile;              /* Point to beginning of array */
printf("TEST: Got to here.\n");

while (*cThisPtr)                 /* Read until reaching null char */
{
    //printf("TEST: Got to here.\n");
    lIndex    = 0L;                 /* Reset counters and flags */
    isNewline = 0;
    lStartPos = lTotalChars;

    while (*cThisPtr)               /* Read until reaching null char */
    {
        if (!isNewline)               /* Haven't read a CR or LF yet */
        {
            if (*cThisPtr == CR || *cThisPtr == LF) /* This char IS a CR or LF */
            isNewline = 1;                        /* Set flag */
            //printf("Flag was set");
            //exit(0);
        }

        else if (*cThisPtr != CR && *cThisPtr != LF) /* Already found CR or LF */
            break;                                     /* Done with line */

        cThisLine[lIndex++] = *cThisPtr++; /* Add char to output and increment */
        ++lTotalChars;

    } /* end while (*cThisPtr) */

    cThisLine[lIndex] = '\0';     /* Terminate the string */
    ++lLineCount;                 /* Increment the line counter */
    lLineLen = strlen(cThisLine); /* Get length of line */
    /* THIS is where I look for the matches to the patterns for my info. */
//    printf("TEST: Printing 1 line\n%s", cThisLine);
//    exit(0);

    if(strstr(cThisLine,title)!= NULL && tfound == false)
    {
        printf("TEST: Looking for title info.\n");
        match = strstr(cThisLine,">");
        //printf("TEST: match first points to %c\n", *match);
        //exit(0);
        j = 0;
        match++;
        //printf("TEST: match points to %c\n", *match);
        while(*match!='<')
        {
            //pridntf("TEST: match is %c\n", *match);
            //printf("TEST: %c", *match);
            buffer[j] = *match;
            //printf("TEST: %c", buffer);
            j++;
            match++;
        }
        lNextLineCount = lLineCount;
        do
        {
            lNextLineCount = lNextLineCount + 1;
            readaheadone(cFile, lNextLineCount, cNextLinePtr, lbuf);
            strcpy(cNextLine, lbuf->bline);
            cNextLinePtr = cNextLine;
            printf("TEST: the current line is - %s\nthe next line is %s\n",cThisLine,cNextLine);
            //printf("TEST: Before test exit");
            //exit(0);
            if(strstr(cNextLinePtr,ending)!=NULL)
            {
                printf("TEST: Author Info spans more than 1 line.\n");
                match = strstr(cThisLine,">");
                j++; //i DON'T RESET COUNTER SO IT JUST KEEPS FILLING THE BUFFER AFTER LEAVING A SPACE
                match++;
                //printf("TEST: match points to %c\n", *match);
                while(*match!='<')
                {
                    //pridntf("TEST: match is %c\n", *match);
                    //printf("TEST: %c", *match);
                    buffer[j] = *match;
                    //printf("TEST: %c", buffer);
                    j++;
                    match++;
                }
            }

        } while(strstr(cNextLinePtr,ending)!=NULL);

    strcpy((*artIn[0]).title, buffer);
    printf("The title is: %s\n", buffer);//artinfo[0].author);
    printf("The title is: %s\n", (*artIn[0]).title);
    tfound = true;
    }

    if(strstr(cThisLine,author)!= NULL && afound == false)
    {
        printf("TEST: Looking for author info.\n");
        match = strstr(cThisLine,">");

    }

}

使用此函数声明:

bool readerParser(FILE *input, FILE *output, textlbuf *lbuf, artinfo *artIn[])
第四个参数是指向artinfo结构的指针数组,而不是指向artinfo结构数组的指针。当它试图去引用这些假定的指针时,它失败了

相反,它应该是:

bool readerParser(FILE *input, FILE *output, textlbuf *lbuf, artinfo (*artIn)[])
此外,修复这些问题至少会使您的程序更加健壮

  • 似乎没有对溢出的
    缓冲区进行任何检查
  • 您没有在
    缓冲区
    的末尾显式放置空字符。虽然您在进入循环之前对其进行了memset,但如果它确实溢出,那么它不仅可能太长,而且可能不会以null结尾
  • 您应该使用而不是strcpy,否则可能会导致目标字符串中分配的空间溢出。正如Matt所指出的,在调用strncpy之后,应该手动在字符串末尾添加一个空字符

  • 关于如何提高代码的健壮性,已经有很多建议。我将回答你在原始帖子中提到的主要问题

    你说

    在到达以下位置之前,一切似乎都正常工作:
    strcpy((*artIn[0])title,buffer)
    printf(“标题是:%s\n”,(*artIn[0]).title);
    语句。我总是会收到一个错误和一个堆栈转储,即
    1[main]Parst\u Text 7296 open\u stackdumpfile:Dumping stack trace来解析_Text.exe.stackdump
    我不确定我做错了什么

    这个问题的罪魁祸首是你

    bool readerParser(FILE *input, FILE *output, textlbuf *lbuf, artinfo *artIn[])
    
    但在调用函数时,您使用的是:

    readerParser(fp, op, lbuf, artIn);
    
    我很惊讶编译器没有标记警告或错误。
    artIn
    声明为:

    artinfo artIn[128] = {};
    
    在函数调用中使用
    artIn
    时,它会降级为类型为
    artinfo*
    的指针。如果参数的参数类型为
    artinfo*artIn
    artinfo artIn[]
    而不是
    artinfo*artIn[]
    ,则效果会更好

    您应该在声明和定义中更改
    readerParser
    中的
    artIn
    的类型

    bool readerParser(FILE *input, FILE *output, textlbuf *lbuf, artinfo artIn[])
    
    然后将该函数中的
    *artIn
    的所有用法替换为
    artIn


    希望这有帮助。

    FYI:
    printf(“TEST:Got to here%d.\n”);
    缺少一个参数。你的编译器是什么?这应该会在GCC上生成一个带有
    -Wall
    的警告。你能从调用
    readerParser
    的函数中发布代码吗?添加一个
    strlen(buffer)title
    我看不出你在哪里终止空
    缓冲区
    你也不处理
    strstr
    返回空值的情况,也不处理
    后找不到
    的情况。
    while(*匹配!='我怀疑他实际上想要的只是
    artinfo artIn[]
    如果使用
    strncpy
    您还必须手动执行空终止,因为如果使用了整个缓冲区,则
    strncpy
    不会手动执行空终止。另一个选项是执行长度检查,并且只有在成功时才使用
    strcpy
    ;或者使用
    snprintf
    。嘿@harmic-关于溢出问题和空终止的要点-我只是追求功能性,但我肯定看到了由于不检查这些情况而导致的问题。我将添加代码来解决此问题。@MattMcNabb-关于提高健壮性的要点,我将确保实现这些问题improvements@MattMcNabb你清楚地读懂了我的心思。谢谢你的更正。我现在很困惑是否要将结构发送到函数。根据我的教科书和其他一些参考书,我认为您应该将地址发送到函数,然后取消引用以访问数据。是因为我使用的是数组,所以它的名称就是地址吗?再次感谢。@R Sahu它确实有帮助。非常感谢。我仍然有点困惑,尽管之前我尝试了一个数字使用不同的组合,并尝试使用我当前的设置(即
    &artIn
    )将artIn的地址发送到函数。您的版本具体要求什么?是否
    artinfo artIn[]
    请求地址?我想我可以在函数中发送指针和引用。任何澄清都肯定会有助于我的学习过程。再次感谢。@这篇简短的文章可能有助于理解数组并在函数调用中使用它们。
    bool readerParser(FILE *input, FILE *output, textlbuf *lbuf, artinfo artIn[])