Thread: Passing struct pointers

  1. #1
    Registered User
    Join Date
    May 2007
    Posts
    77

    Passing struct pointers

    OK, so this program is made to read text files, split the lines into types (based on content of the lines), and then, (eventually), create a binary file from selected descriptions and their child code lines. My problem is, in trying to compartmentalize (I can't think of the proper programming term) my code and make more functions, I pass the pointer to a struct I made and proceed to read and modify members of that struct. My question is, in passing the pointer to the struct, if the functionality of the program remains the same, and the end result is the same, why would I get the warning:

    "C:\sources\test\main.c||In function 'main':|
    C:\sources\test\main.c|199|warning: passing argument 1 of 'writeFile' from incompatible pointer type|
    C:\sources\test\main.c|61|note: expected 'struct txtData *' but argument is of type 'struct txtData (*)[(unsigned int)(line + 1)]'|"

    The .c file is here:

    Code:
    #include <ctype.h>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "main.h"
    
    void spaceOut(char ........tr, char *dStr)
    {
    	strncpy(dStr, sStr, 8);
    	dStr[8] = '\0';
    	char *p = strchr(sStr,' ') + 1;
    	strncat(dStr, p, 8);
    	dStr[16] = '\0';
    }
    
    void str2Bin(char *hstr, char *dstr)
    {
        int num = 0;
        char sstr[2];
        hToIkey key[16] = {
            {'0',0},
            {'1',1},
            {'2',2},
            {'3',3},
            {'4',4},
            {'5',5},
            {'6',6},
            {'7',7},
            {'8',8},
            {'9',9},
            {'A',10},
            {'B',11},
            {'C',12},
            {'D',13},
            {'E',14},
            {'F',15}
        };
        int dindex = 0;
        for (int i = 0; i < 16; i++)
        {
            for (int k = 0; k < 16; k++)
            {
                if (hstr[i] == key[k].keyHex)
                {
                    num += key[k].keyDec*pow(16,(i%2)^1);
                    if (i%2 == 1)
                    {
                        dstr[dindex] = num;
                        dindex++;
                        num = 0;
                        break;
                    }
                }
            }
        }
        dstr[dindex] = '\0';
    }
    
    void writeFile(txtData *data, int lines)
    {
    	char fileStart[8] = {
            0,
            208,
            192,
            222,
            0,
            208,
            192,
            222
    	};
    	char fileEnd[8] = {
    	    240,
    	    0,
    	    0,
    	    0,
    	    0,
    	    0,
    	    0,
    	    0
    	};
        char filename[11];
        int printed = 0;
        for(int i = 0; i < 6; i++)
        {
            data[0].lineText[i] = toupper(data[0].lineText[i]);
        }
        sprintf(filename, "%s.gct", data[0].lineText);
        data[5].lineActive = 1;
        FILE *gct = fopen(filename, "w");
        fwrite(&fileStart, 1, 8, gct);
        for(int i = 0; i < lines; i++)
        {
            if (data[i].lineType == LINE_CODE)
            {
                if(data[data[i].parentLine].lineActive)
                {
                    str2Bin(data[i].lineText, data[i].codeValue);
                    fwrite(data[i].codeValue, 1, 8, gct);
                    printed++;
                }
            }
    	}
    	fwrite(&fileEnd, 1, 8, gct);
        fclose(gct);
        if(printed == 0)
        {
            remove(filename);
            printf("Create failed.  No codes selected!");
        }
        fclose(gct);
    }
    
    int main()
    {
        FILE *textFile = fopen("Metroid Prime Trilogy.txt", "r");
    	char text[256];
    	char nospace[9];
    	char match[17] = "0123456789ABCDEF ";
    	char xmatch[18] = "0123456789ABCDEFX ";
    	int line = 0;
    	int parent = 0;
    	while(fgets(text, 255, textFile))
    	{
    	    if(feof(textFile))
                break;
            line++;
        }
        txtData data[line+1];
        rewind(textFile);
        line = 0;
        while(fgets(text, 255, textFile))
    	{
            strncpy(data[line].lineText, text, strlen(text) - 1);
            data[line].lineText[strlen(text) - 1] = '\0';
            data[line].lineNum = line;
            data[line].lineActive = 0;
            data[line].parentLine = 0;
    	    if(feof(textFile))
                break;
            line++;
        }
        for(int i = 0; i < line; i++)
        {
            int span = strspn(data[i].lineText, match);
            int xspan = strspn(data[i].lineText, xmatch);
            if(i == 0)
            {
                data[i].lineType = LINE_ID;
            }
            else if(strlen(data[i].lineText) == 0)
            {
                data[i].lineType = LINE_BLANK;
            }
            else if(data[i-1].lineType == LINE_ID)
            {
                data[i].lineType = LINE_TITLE;
            }
            else if((span == 17) || (xspan == 17))
            {
                data[i].lineType = LINE_CODE;
                data[i].parentLine = parent;
                spaceOut(data[i].lineText, nospace);
                strcpy(data[i].lineText, nospace);
            }
            else if(data[i-1].lineType == LINE_BLANK)
            {
                if(strlen(data[i+1].lineText) == 0)
                {
                    data[i].lineType = LINE_CATEGORY;
                }
                else
                {
                    data[i].lineType = LINE_DESCR;
                    parent = data[i].lineNum;
                }
            }
            else if(data[i-1].lineType == LINE_CODE)
            {
                data[i].lineType = LINE_COMMENT;
                data[i].parentLine = parent;
            }
            else
            {
                data[i].lineType = LINE_UNKNOWN;
            }
        }
        typeStruct types[8] = {
            "ID\0",
            "TITLE\0",
            "CATEGORY\0",
            "DESCR\0",
            "CODE\0",
            "COMMENT\0",
            "BLANK\0",
            "UNKNOWN\0"
        };
        writeFile(&data, line);
    	return 0;
    }
    And the header:

    Code:
    enum {
        LINE_ID,
        LINE_TITLE,
        LINE_CATEGORY,
        LINE_DESCR,
        LINE_CODE,
        LINE_COMMENT,
        LINE_BLANK,
        LINE_UNKNOWN
    };
    
    typedef struct {
        const char keyHex;
        int keyDec;
    } hToIkey;
    
    typedef struct {
        int lineType;
        int lineNum;
        int parentLine;
        char lineText[255];
        char codeValue[9];
        int lineActive;
    } txtData;
    
    typedef struct {
        char typeValue[9];
    } typeStruct;
    I don't need any help on functionality, I just am puzzled by the warning and want to make sure it's resolved (if it needs to be) before moving forward.

    Edit: went back and, for sake of ease, highlighted the two lines mentioned in the warning.
    Last edited by Molokai; 05-20-2010 at 10:19 PM. Reason: color lines in question

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    > writeFile(&data, line);
    Data is already an array, so it would be
    writeFile(data, line);

    However, there are more issues.

    > txtData data[line+1];
    line is zero to begin with, so this is an array with only 1 slot.
    Then you go on to calculate a new value of line, but this does NOT alter your array.

    > strncpy(data[line].lineText, text, strlen(text) - 1);
    > data[line].lineText[strlen(text) - 1] = '\0';
    strncpy() only offers safety if you use the size of the destination, not the size of the source.
    You have written precisely
    strcpy( data[line].lineText, text );

    > if(feof(textFile))
    > break;
    a) it's too late to test this now inside the loop, you've already processed the data
    b) it's unreachable to begin with - the use of fgets() in the while loop sees to that.
    Just delete these two lines.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User NeonBlack's Avatar
    Join Date
    Nov 2007
    Posts
    431
    Code:
    txtData data[line+1];
    ...
    writeFile(&data, line);
    When you use the name "data", it becomes type txtData* (pointer to txtData). &data then would be txtDat........... You should read the FAQ about pointers and arrays.
    I copied it from the last program in which I passed a parameter, which would have been pre-1989 I guess. - esbo

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    77
    Thank you for the hint about data already being an array, as that's all I needed, and the clarification on strncpy was useful, but line is perfectly fine the way it is. Thanks anyway.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    > for(int i = 0; i < line; i++)
    ...
    > data[i].lineType = LINE_ID;
    I wonder how far this overwriting past the end of the array will go before "it's fine" turns into "What's a segfault?"
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    May 2007
    Posts
    77
    Umm, it's not overwriting past the array. Look closer at the code:

    Code:
    	int line = 0;
    	int parent = 0;
    	while(fgets(text, 255, textFile))
    	{
    	    if(feof(textFile))
                break;
            line++;
        }
        txtData data[line+1];
        rewind(textFile);
        line = 0;
        while(fgets(text, 255, textFile))
    	{
            strcpy(data[line].lineText, text);
            data[line].lineText[strlen(text) - 1] = '\0';
            data[line].lineNum = line;
            data[line].lineActive = 0;
            data[line].parentLine = 0;
    	    if(feof(textFile))
                break;
            line++;
        }
    As you can see, there are two loops with fgets. The first one determines how many lines there are in the file (line++) which then is used to create the struct array with proper number of elements before being reset to zero.

    Also, as it turns out, it's not too late, for my purposes, to check feof inside the loop, as without it, I actually get an added garbage slot in my array. True, I could leave it out and do "txtData data[line]" instead of "data[line+1]", but your premise was off.
    Last edited by Molokai; 05-20-2010 at 10:56 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing pointers to functions in seperate source files
    By derekeverett in forum C Programming
    Replies: 12
    Last Post: 10-08-2009, 07:15 AM
  2. Converting from C to C++
    By Taka in forum C++ Programming
    Replies: 5
    Last Post: 04-08-2009, 02:16 AM
  3. Struct question... difference between passing to function...
    By Sparrowhawk in forum C++ Programming
    Replies: 6
    Last Post: 02-23-2009, 03:59 PM
  4. Looking for constructive criticism
    By wd_kendrick in forum C Programming
    Replies: 16
    Last Post: 05-28-2008, 09:42 AM
  5. passing structs & pointers to structs as arguments
    By Markallen85 in forum C Programming
    Replies: 6
    Last Post: 03-16-2004, 07:14 PM