Thread: How to pass in an array/struct as argument

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    24

    How to pass in an array/struct as argument

    Hey I'm having trouble understanding my error message

    "incompatible type for argument 1 of ‘makeDateString’"

    The function in question has the declaration

    void makeDateString(const DateTime *dateTime, char *buff)

    and I'm calling it using the output from a function with a return type DateTime(#defined tm struct). Should I only pass a pointer in? It came up with a lot more errors when I tried the "&" operand.

    Also what is the difference between an argument and a parameter?

    Thanks

  2. #2
    C / C++
    Join Date
    Jan 2006
    Location
    The Netherlands
    Posts
    312
    Could you post the code where you call the makeDateString() function?
    Operating Systems:
    - Ubuntu 9.04
    - XP

    Compiler: gcc

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Yes, I'd use a pointer to the struct, sure.

    An argument and a parameter are the same thing.

  4. #4
    Registered User
    Join Date
    Apr 2009
    Posts
    24
    The code in my main function is:

    char *test;
    char *buff;
    DateTime firstTry;
    strcpy(test, "20090312150317");
    firstTry = dateTimeFromString(test);
    makeDateString(firstTry, buff);

    So should it be:
    makeDateString(&firstTry, buff);??

  5. #5
    C / C++
    Join Date
    Jan 2006
    Location
    The Netherlands
    Posts
    312
    Well, you copy the string containing the date to a char *, which hasn't been allocated in memory. So that's a segfault.
    makeDateString(&firstTry, buff); is correct.
    Operating Systems:
    - Ubuntu 9.04
    - XP

    Compiler: gcc

  6. #6
    Registered User
    Join Date
    Apr 2009
    Posts
    24
    Sorry I don't understand why I get a segfault? I've now changed it like:
    char *test = NULL;
    char *buff = NULL;

    But gdb still gives me the KERN_PROTECTION_FAILURE at address: 0x00001ffa.
    How do I make sure the char *'s are allocated?

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Can you post your current code - generally, seg fault is caused by accessing memory that you haven't got - e.g. through a NULL pointer.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Apr 2009
    Posts
    24
    Sorry for the length
    DateTime dateTimeFromString(const char *s)
    {
    DateTime result;

    char year[5];
    char month[3];
    char day[3];
    char hour[3];
    char min[3];

    strncpy(year, s, 4);
    strncpy(month, s + 4, 2);
    strncpy(day, s + 6, 2);
    strncpy(hour, s + 8, 2);
    strncpy(min, s + 10, 2);

    year[4] = '0';
    month[2] = '0';
    day[2] = '0';
    hour[2] = '0';
    min[2] = '0';

    result.tm_year = atoi(year);
    result.tm_mon = atoi(month);
    result.tm_mday = atoi(day);
    result.tm_hour = atoi(hour);
    result.tm_min = atoi(min);
    result.tm_sec = 0;
    result.tm_isdst = -1;

    /* Use mktime to work out day of week and day of year */

    if (mktime(&result) == -1) {
    result.tm_isdst = 0;
    }
    else
    {
    /* Do nothing*/
    }
    return result;
    }

    void makeDateString(const DateTime *dateTime, char *buff)
    {
    if(sizeof(buff) > (sizeof(int) * DATE_TIME_BUFF_SIZE))
    {
    strftime(buff, 30, "%A %d %B, %Y", dateTime);
    }
    else{} /* Do Nothing */
    }

    int main()
    {
    char *test = "a";
    char *buff = "a";
    DateTime firstTry;
    strncpy(test, "20090312150317", 14);
    firstTry = dateTimeFromString(test);
    makeDateString(&firstTry, buff);
    printf("%s", buff);
    return 1;
    }

  9. #9
    Registered User
    Join Date
    Apr 2009
    Posts
    24
    shakes I just read the how to post code note
    Code:
    DateTime dateTimeFromString(const char *s)
    {
    DateTime result;
    
    char year[5];
    char month[3];
    char day[3];
    char hour[3];
    char min[3];
    
    strncpy(year, s, 4);
    strncpy(month, s + 4, 2);
    strncpy(day, s + 6, 2);
    strncpy(hour, s + 8, 2);
    strncpy(min, s + 10, 2);
    
    year[4] = '0';
    month[2] = '0';
    day[2] = '0';
    hour[2] = '0';
    min[2] = '0';
    
    result.tm_year = atoi(year);
    result.tm_mon = atoi(month);
    result.tm_mday = atoi(day);
    result.tm_hour = atoi(hour);
    result.tm_min = atoi(min);
    result.tm_sec = 0;
    result.tm_isdst = -1;
    
    /* Use mktime to work out day of week and day of year */
    
    if (mktime(&result) == -1) {
    result.tm_isdst = 0;
    }
    else 
    {
    /* Do nothing*/
    }
    return result;
    }
    
    void makeDateString(const DateTime *dateTime, char *buff)
    {
    if(sizeof(buff) > (sizeof(int) * DATE_TIME_BUFF_SIZE))
    {
    strftime(buff, 30, "%A %d %B, %Y", dateTime);
    }
    else{} /* Do Nothing */
    }
    
    int main()
    {
    char *test = "a";
    char *buff = "a";
    DateTime firstTry;
    strncpy(test, "20090312150317", 14);
    firstTry = dateTimeFromString(test);
    makeDateString(&firstTry, buff);
    printf("%s", buff);
    return 1;
    }

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    General comments.
    1. Indent your code.
    2. Don't have a load of "else {} // do nothing". If you don't want to have an else, then don't write an else-statement.

    Code:
    year[4] = '0';
    does not terminate the string - that would mean that the string "2009" would be the same as "2". You either want '\0' or 0 (without quotes).

    Code:
    result.tm_year = atoi(year);
    If we assume that year is something like "2009", then tm_year will be out of range - read the documentation for struct tm again.

    Code:
    char *test = "a";
    char *buff = "a";
    DateTime firstTry;
    strncpy(test, "20090312150317", 14);
    You are truing to write a 14-character string to a read-only 2-byte memory location - if it wasn't read-only, you'd overwrite some 12 bytes. This is most likely where your seg-fault happens.

    Code:
    if(sizeof(buff) > (sizeof(int) * DATE_TIME_BUFF_SIZE))
    {
    strftime(buff, 30, "%A %d %B, %Y", dateTime);
    }
    else{} /* Do Nothing */
    }
    Since sizoef(buff) is most likely 4, and sizeof(int) is also [nearly always in modern systems] 4, this will only be true if:
    1. DATE_TIME_BUFF_SIZE is 0.
    2. pointers are 64-bit (making sizeof(buff) = 8) and DATE_TIME_BUFF_SIZE is less than 2.
    Is that the situation (you don't show us what DATE_TIME_BUFF_SIZE is, so there's no way to tell from here)?

    --
    mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Apr 2009
    Posts
    24
    Thanks for all this help mats, all these are things I just wouldn't have picked up on. I've now changed it. Please, any more tips would be great. Also I still can't visualize how to check if the array passed in is large enough. If I use strlen() won't it stop at the first null character, so practically never be true? How do I make sure the array is big enough?
    Also could sscanf() be used in the dateTimeFromString function?

    Code:
    #include "datetime.h"
    
    #include<string.h>
    #include<stdlib.h>
    #include<stdio.h>
    
    #define DATE_TIME_BUFF_SIZE 30
    
    
    	/* Return a DateTime record (i.e., a struct tm record) containing
    	 * the information extracted from the given string, which is assumed
    	 * to be one of the strings specifying date/time within the XML file.
    	 * For example, s might be "20090310150506" (the double-quotes are
    	 * not characters in the string), denoting 2009/03/10 15:05:06. The
    	 * seconds (06 in the example) can be ignored -- they are not used
    	 * by the program.
    	 */
    DateTime dateTimeFromString(const char *s)
    	{
    		DateTime result;
    		
    		char year[5];
    		char month[3];
    		char day[3];
    		char hour[3];
    		char min[3];
    		
    		strncpy(year, s, 4);
    		strncpy(month, s + 4, 2);
    		strncpy(day, s + 6, 2);
    		strncpy(hour, s + 8, 2);
    		strncpy(min, s + 10, 2);
    		
    		year[4] = 0;
    		month[2] = 0;
    		day[2] = 0;
    		hour[2] = 0;
    		min[2] = 0;
    		
    		result.tm_year = atoi(year) - 1900;
    		result.tm_mon = atoi(month);
    		result.tm_mday = atoi(day);
    		result.tm_hour = atoi(hour);
    		result.tm_min = atoi(min);
    		result.tm_sec = 0;
    		result.tm_isdst = -1;
    		
    		/* Use mktime to work out day of week and day of year */
    		
    		mktime(&result);
    		return result;
    	}
    	
    	/* Insert into the given buffer a string representation of the
    	 * date part of the given DateTime record, assumed to have been
    	 * created by a call to dateTimeFromString. The string should be
    	 * of the form:
    	 * Tuesday 10 March, 2009
    	 * with both the day of the week and the month given in full.
    	 * The supplied buffer must be at least DATE_TIME_BUFF_SIZE characters
    	 * in length.
    	 */
    void makeDateString(const DateTime *dateTime, char *buff)
    	{
    		if(sizeof(*buff) > (sizeof(int) * DATE_TIME_BUFF_SIZE))
    		   {
    		   strftime(buff, 30, "%A %d %B, %Y", dateTime);
    		   }
    	}
    		   
    		/* Insert into the given buffer a string representation of the
    		 * time part of the given DateTime record, assumed to have been
    		 * created by a call to dateTimeFromString. The string should be
    		 * four digits plus a terminating null, e.g. 1036 or 0309,
    		 * specifying just the hour and the minute on a 24 hour clock basis.
    		 * The supplied buffer must be at least DATE_TIME_BUFF_SIZE characters
    		 * in length.
    		 */
    void makeTimeString(const DateTime *dateTime, char *buff)
    	{
    		if(sizeof(*buff) > (sizeof(int) * DATE_TIME_BUFF_SIZE)) /* buffer is bigger than a maximum */
    			{
    				strftime(buff, 5, "%H%M", dateTime); 
    			}
    	}
    
    int sameDay(const DateTime *dt1, const DateTime *dt2)
    	{
    		int result;
    		char buff1[30], buff2[30];
    		makeDateString(dt1, buff1);
    		makeDateString(dt2, buff2);
    		if (strcmp(buff1, buff2) == 0)
    		{
    			result = 1;
    		}
    		else
    		{
    			result = 0;
    		}
    		return result;
    	}
    
    	int main()
    	{
    		char test[DATE_TIME_BUFF_SIZE + 1];
    		char buff[DATE_TIME_BUFF_SIZE + 1];
    		DateTime firstTry;
    		strncpy(test, "20090312150317", 14);
    		firstTry = dateTimeFromString(test);
    		makeDateString(&firstTry, buff);
    		printf("%s", buff);
    		return 1;
    	}

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You need to provide the size of the array you're passing as an argument to that function, and use it for loop control / size checking. It's really the only way you can know for sure if the array you're receiving has enough space for what you want.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointer to List Iterator As Function Argument
    By bengreenwood in forum C++ Programming
    Replies: 8
    Last Post: 06-17-2009, 05:30 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. Variable Argument functions
    By dnysveen in forum C++ Programming
    Replies: 13
    Last Post: 06-01-2006, 06:03 PM
  4. Nested loop frustration
    By caroundw5h in forum C Programming
    Replies: 14
    Last Post: 03-15-2004, 09:45 PM
  5. Parameter pass
    By Gades in forum C Programming
    Replies: 28
    Last Post: 11-20-2001, 02:08 PM