1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Development C functions help!!

Discussion in 'Software' started by Evil The Cat, 8 Mar 2004.

  1. Evil The Cat

    Evil The Cat What's a Dremel?

    Joined:
    30 Jan 2004
    Posts:
    6
    Likes Received:
    1
    Hey, Im not very sure on how to use functions in C. Basically Im making a roman numeral calculator. Iv writen the code for converting from roman numeral to decimal.
    How can I make this into a function and what would I need to do to use this function, given that that roman characters are stored in "inchararray1". Things that the function needs are the lenght of the string (length) and the char array "chararray". The only value its to return is "input"

    Pretty please help.



    for (i=0;i == length; i++)
    {
    switch chararray(i)
    {

    CASE M: decimal(i) = 1000;
    break;

    CASE D: decimal(i) = 500;
    break;

    CASE C: decimal(i) = 100;
    break;

    CASE L: decimal(i) = 50;
    break;

    CASE x: decimal(i) = 10;
    break;

    CASE V: decimal(i) = 5;
    break;

    CASE I: decimal(i) = 1;
    break;

    default: printf("non roman numeral conversion attempted");
    break;
    }

    for (i=0;i == length; i++)
    {
    IF (decimal(i) == 1) && (decimal(i+1) == 5) || (decimal(i+1) == 10))
    {decimal(i) = -(decimal(i));}

    IF ((decimal(i) == 10) && (decimal(i+1) == 50) || (decimal(i+1) == 100))
    {decimal(i) = -(decimal(i));}

    IF ((decimal(i) == 100) && (decimal(i+1) == 1000))
    {decimal(i) = -(decimal(i));}

    input = input + decimal(i);
     
  2. Ardentfrost

    Ardentfrost What's a Dremel?

    Joined:
    22 Jan 2004
    Posts:
    292
    Likes Received:
    1
    ummm... man, I'm sure you'll get plenty of responses better than me since it's been 2 years since C.. let's see

    #include <stdio.h>

    WonderTwinPowersActivate(char [] chararray, int length) { //that might be char inchararray1[]... I can't remember

    for (i=0;i == length; i++)
    {
    switch chararray(i)
    {

    CASE M: decimal(i) = 1000;
    break;

    CASE D: decimal(i) = 500;
    break;

    CASE C: decimal(i) = 100;
    break;

    CASE L: decimal(i) = 50;
    break;

    CASE x: decimal(i) = 10;
    break;

    CASE V: decimal(i) = 5;
    break;

    CASE I: decimal(i) = 1;
    break;

    default: printf("non roman numeral conversion attempted");
    break;
    }

    for (i=0;i == length; i++)
    {
    IF (decimal(i) == 1) && (decimal(i+1) == 5) || (decimal(i+1) == 10))
    {decimal(i) = -(decimal(i));}

    IF ((decimal(i) == 10) && (decimal(i+1) == 50) || (decimal(i+1) == 100))
    {decimal(i) = -(decimal(i));}

    IF ((decimal(i) == 100) && (decimal(i+1) == 1000))
    {decimal(i) = -(decimal(i));}

    input = input + decimal(i);
    }

    main() {

    WonderTwinPowersActivate("iv", 2);

    }


    **********

    on a side note, when you reference a point in an array like your line :

    switch chararray(i)

    those ()'s need to be []'s I'm pretty sure.

    Sorry if I'm wrong on some parts or maybe was thinking of java or C++, but I'm no programmer, I'm more into hardware... but I do have to program sometimes :)

    Oh, also you can do all that in the main function and use argv and argc[] to pass in the char array. I could tell you how, but then I'd have to kill you (and I"m too lazy to pull out my old C programs from 2 years ago :) )
     
  3. JazzXP

    JazzXP Eh! Steve

    Joined:
    30 Apr 2002
    Posts:
    1,669
    Likes Received:
    13
    yes, they have to be []... so your switch statement would be switch (chararray)

    Also, your function can be WonderTwinPowersActivate(char *chararray, int length) as well, as array's are just pointers (if you are just starting out, you'll learn these soon).
     
  4. Ardentfrost

    Ardentfrost What's a Dremel?

    Joined:
    22 Jan 2004
    Posts:
    292
    Likes Received:
    1
    I knew they were pass by reference, but couldn't remember the syntax :)
     
  5. micb

    micb Minimodder

    Joined:
    4 Sep 2002
    Posts:
    1,949
    Likes Received:
    2
  6. Ardentfrost

    Ardentfrost What's a Dremel?

    Joined:
    22 Jan 2004
    Posts:
    292
    Likes Received:
    1
    Just a note, C and C++ are different in some ways. For instance, printing to screen is a big one :) So if you use those guides and are learning C (not C++) you won't be able to use everything.

    To be honest, I don't recall using malloc in C++, so I think that's another big difference. Of course, as always with programming things, I could be wrong :) (but I know for a fact there are many differences)

    edit: just looked up dynamic memory allocation in those tutorials, and it's just like I thought I remembered... new/delete for C++, malloc and.... I can't remember how to unallocate memory in C, but whatever. It might be delete as well /shrug

    Sorry I'm so scatter-brained with programming. I got too many languages from too long ago floating around in my head :)
     
  7. JazzXP

    JazzXP Eh! Steve

    Joined:
    30 Apr 2002
    Posts:
    1,669
    Likes Received:
    13
    I think it's free to deallocate... from memory... haven't done C for about 5 years.
     
  8. Hargle

    Hargle What's a Dremel?

    Joined:
    13 Oct 2001
    Posts:
    404
    Likes Received:
    1
    The operator new and delete are C++ not C as you point out. You can of course use malloc/free (and the other associated memory allocation calls, realloc, etc.) in C++ but they do differ from new and delete. new and delete deal with memory allocation as do malloc/free but they also call the relevant class constructors/destructors. As both new and delete are operators in C++ they can be overloaded, which makes adding in custom memory managers significantly easier too.

    There seems to be quite a lot of 'bugs' in that first lot of code you posted. Keywords should be lowercase (case not CASE, if not IF, etc). As already pointed out array deferencing should be with brackets not parentheses. Your for loop looks dodgy too, you probably want the looping condition to be i < length. One thing that's not a bug, but should really be changed is the postincremenet 'i++' in the loop. That section of code is always executed at the end of each loop iteration so you can use ++i (preincrement) instead, which is faster (a temporary value doesn't need to be stored to be returned from the operator). It won't make much of a difference in your case but in large loops it will speed things up slightly.
     
  9. sk8o

    sk8o What's a Dremel?

    Joined:
    22 Jan 2002
    Posts:
    138
    Likes Received:
    1
    thats becuase u dont :) you use new to allocate space for objects and delete to destroy objects in C++

    In C, malloc is to allocate space, realloc is to allocate, adjust or free space (depending on the parameters) and free is to free space, all of which is referenced by a pointer.

    + C++ is very different to C becuase it uses encapsulation, polmorphism around objects, it is true that in C you can use structures to provide a similar structure but not to the same level....
     
  10. Hepath

    Hepath Minimodder

    Joined:
    20 Oct 2003
    Posts:
    730
    Likes Received:
    0
    Oh crikey memory allocation under the hood....

    There are a number of functions here


    void *malloc( size_t size );
    malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. To return a pointer to a type other than void, use a type cast on the return value. The storage space pointed to by the return value is guaranteed to be suitably aligned for storage of any type of object. If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item. Always check the return from malloc, even if the amount of memory requested is small.


    .....which can also resolve to malloc_dbg when _DEBUG is specified

    void *_malloc_dbg(size_t size, int blockType, const char *filename, int linenumber );
    _malloc_dbg is a debug version of the malloc function. When _DEBUG is not defined, each call to _malloc_dbg is reduced to a call to malloc. Both malloc and _malloc_dbg allocate a block of memory in the base heap, but _malloc_dbg offers several debugging features: buffers on either side of the user portion of the block to test for leaks, a block type parameter to track specific allocation types, and filename/linenumber information to determine the origin of allocation requests.

    _malloc_dbg allocates the memory block with slightly more space than the requested size. The additional space is used by the debug heap manager to link the debug memory blocks together and to provide the application with debug header information and overwrite buffers. When the block is allocated, the user portion of the block is filled with the value 0xCD and each of the overwrite buffers are filled with 0xFD.



    void *calloc( size_t num, size_t size );
    The calloc function allocates storage space for an array of num elements, each of length size bytes. Each element is initialized to 0.

    calloc calls malloc in order to use the C++ _set_new_mode function to set the new handler mode. The new handler mode indicates whether, on failure, malloc is to call the new handler routine as set by _set_new_handler. By default, malloc does not call the new handler routine on failure to allocate memory. You can override this default behavior so that, when calloc fails to allocate memory, malloc calls the new handler routine in the same way that the new operator does when it fails for the same reason.


    void *realloc( void *memblock, size_t size );
    The realloc function changes the size of an allocated memory block. The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes. If memblock is not NULL, it should be a pointer returned by a previous call to malloc, or realloc.

    The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes, although the new block can be in a different location. Because the new block can be in a new memory location, the pointer returned by realloc is not guaranteed to be the pointer passed through the memblock argument.

    Note: realloc calls malloc

    void free(void *memblock );
    The free function deallocates a memory block (memblock) that was previously allocated by a call to calloc, malloc, or realloc. The number of freed bytes is equivalent to the number of bytes requested when the block was allocated (or reallocated, in the case of realloc). If memblock is NULL, the pointer is ignored and free immediately returns. Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.


    New and, Delete operators
    The new and delete operators are C++ operators only. In reality though they call through to (iirc) malloc (for new) and (free) for delete. However, Hargle is exactly right - although they allocate the memory; they also call the constructor of the class before returning, or destructor before the memory free.

    One interesting point is that new cannot be used to allocate memory for a function, only a function pointer!
     
  11. Ardentfrost

    Ardentfrost What's a Dremel?

    Joined:
    22 Jan 2004
    Posts:
    292
    Likes Received:
    1
    Well, I really don't think all this memory allocation talk went along with the original post since he won't really need to do it. I was just mentioning differences between C and C++ so he doesn't get the two confused and said that was one of the differences. I think it's really funny this turned into a malloc discussion :)
     
  12. Hepath

    Hepath Minimodder

    Joined:
    20 Oct 2003
    Posts:
    730
    Likes Received:
    0
    Oops! Yeah - I did go on a bit :duh:
    Sorry!
    Stu
     
  13. tkwsn

    tkwsn What's a Dremel?

    Joined:
    27 Aug 2003
    Posts:
    146
    Likes Received:
    0
    C++ or not, this code will work and will be faster and cheaper.
    Evil the Cat, it looks good for a beginner, but remember to keep it simple and you'll have an easier time of it.

    Code:
    #include <stdio.h>
    int fromromannumeral(char *);
    
    int fromromannumeral(char *chararray) 
    	{
    	int input=0;
    	for (i=0;chararray[i];i++)
    		{
    		chararray[i] |= 0x20; //Make it lower case
    		switch (chararray[i])
    			{
    			CASE 'm':
    				input += 1000;
    				break;
    			CASE 'd':
    				input += 500;
    				break;
    			CASE 'c':
    				input += 100;
    				break;
    			CASE 'l':
    				input += 50;
    				break;
    			CASE 'x':
    				input += 10;
    				break;
    			CASE 'v':
    				input += 5;
    				break;
    			CASE 'i':
    				input += 1;
    				break;
    			default: printf("non roman numeral conversion attempted");
    				break;
    			}
    		}
    	return input;
    	}
    
    void main()
    	{
    	printf ("IV in decimal: %i", fromromannumeral("iv"));
    	}
    
    Try it out.
     
  14. Hepath

    Hepath Minimodder

    Joined:
    20 Oct 2003
    Posts:
    730
    Likes Received:
    0
    Not tried this (I'm going to to though...) cos I dont think it will work!

    Your parsing the string left to right adding the numbers found - but Roman numerals dont work like that. "IV" is not the same as "VI" which is what I think your routine would do - the first is decimal 4 the other is decimal 6.

    Effectively none of the routines take into consideration the rule that if the numeral to the left of the next is worth less, its subtracted not added. I noticed this before but got competley sidetracked by the memory blag......
     
  15. tkwsn

    tkwsn What's a Dremel?

    Joined:
    27 Aug 2003
    Posts:
    146
    Likes Received:
    0
    Yeah, I noticed that. It'll take a bit of code to fix that. If you're going to work on it, I won't.
     
  16. Hepath

    Hepath Minimodder

    Joined:
    20 Oct 2003
    Posts:
    730
    Likes Received:
    0
    Wibble - ;)

    Self explanatory I hope --- Was this still required. Not fully tested - but seems to work for XIV XVI etc...

    Code:
    // RomanNumeral.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    
    int GetDecValue(char roman)
    {
    	int nVal = 0;
    	
    	switch (roman |= 0x20)
    	{
    	case'm':
    		nVal = 1000;
    		break;
    	case'd':
    		nVal = 500;
    		break;
    	case'c':
    		nVal = 100;
    		break;
    	case'l':
    		nVal = 50;
    		break;
    	case'x':
    		nVal = 10;
    		break;
    	case'v':
    		nVal = 5;
    		break;
    	case'i':
    		nVal = 1;
    		break;
    	default: 
    		printf("non roman numeral conversion attempted");
    		nVal = -1;
    		break;
    	}
    
    	return nVal;
    }
    
    int DecodeNumeral(char* pNumerals) 
    {
    	int lastVal = 0;
    	int thisVal = 0;
    	int nTotal = 0;
    	
    	// loop through roman numeral array
    	for (int i = 0; pNumerals[i]; i++)
    	{	
    		// remember last when adding on
    		lastVal = thisVal;		
    		thisVal = GetDecValue(pNumerals[i]);
    		
    		// if no error....
    		if (thisVal > 0)
    		{
    			// add decimalised value to total
    			nTotal += thisVal;
    
    			// if previous was less than current need to subtract twice its amount
    			if (lastVal < thisVal)
    				nTotal = nTotal - (2*lastVal);
    		}
    		else
    		{
    			// error in translation - bug out
    			nTotal = -1;
    			break;
    		}
    	}
    
    	return nTotal;
    }
    
    int _tmain(int argc, char* argv[])
    {
    	if (argc == 2)
    	{
    		return = DecodeNumeral(argv[1]);
    	}
    	else
    	{
    		printf("\nUsage: RN.EXE {xx}");
    		printf("\nxx = Roman Numeral to be converted to decimal.");
    		return -1;
    	}
    }
    
    
     
  17. tkwsn

    tkwsn What's a Dremel?

    Joined:
    27 Aug 2003
    Posts:
    146
    Likes Received:
    0
    Should work.
     

Share This Page