How should I do this?

This is a discussion on How should I do this? within the C Programming forums, part of the General Programming Boards category; I'm trying to figure out how to feed a string or an int (or whatever) into a function and get ...

  1. #1
    Registered User
    Join Date
    Feb 2011
    Posts
    50

    How should I do this?

    I'm trying to figure out how to feed a string or an int (or whatever) into a function and get the SAME string back, CHANGED.

    What I mean is, every time *I* do it, I just end up changing the pointer to a different var (memory location), which generally goes out of scope when I leave that function (because it's a local automatic var).

    Again, I want to instantiate a var, set its value, then in *different* function change the value of the SAME var, not just repoint a pointer to a different var (probably invalid by the time I get back into the original function).

    I hope this makes sense. I can't find anything on it in any documentation.
    I know that my functions are wrong.

    So, How *should* I do this, using proper C programming?

    Code:
    char *changeString(char *str)
    {
    	str = "12345678910"; //Notice that now txt should be 11 bytes
    	return str;
    }
    int *changeInt(int *ptrX)
    {
    	ptrX = 23;
    	return ptrX;
    }
    int main()
    {
    	int x = 10;
    	char txt[5]; //I did it this way to show that the char is only 5 bytes for sure
    	txt = "12345";
    	x = changeInt(x);	
    	txt = changeString(txt);	
    	return 0;
    }

  2. #2
    a_capitalist_story
    Join Date
    Dec 2007
    Posts
    2,648
    Code:
    char txt[5]; //I did it this way to show that the char is only 5 bytes for sure
    txt = "12345";
    Nope, not enough space. You forgot room for the null terminator.

    If you're changing something in the function by passing a pointer, there's no point (oops) in returning anything.

    Code:
    #include <stdio.h>
    
    void changeInt(int *x)
    {
        /* Dereference the pointer and assign the value at that memory location */
        *x = 23;
    }
    
    int main(void)
    {
        int x = 9;
        printf("x is %d\n", x);
        /* Pass the address of the local variable to the function */
        changeInt(&x);
        printf("x is now %d\n", x);
    
        return 0;
    }

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by MAtkins View Post
    So, How *should* I do this, using proper C programming?
    rags_to_riches has already provided most of the correct information, so this is in addition to what he's saying....

    Code:
    char *changeString(char *str)
    {
    	str = "12345678910"; //Notice that now txt should be 11 bytes
    	return str;
    }
    This fails because you are changing the pointer to indicate a different literal string. It abandons the original 5 character buffer in your main function.

    You can make it work by A) assigning a large enough buffer, B) passing in the buffer size and C) using strncpy() to prevent overflows... You can still pass the original pointer back out...

    Code:
    char * ChangeString(char *str, int length)
      { return strncpy(str,"0123456789",length); )
    next...
    Code:
    int *changeInt(int *ptrX)
    {
    	ptrX = 23;
    	return ptrX;
    }
    This fails because you are changing the pointer not the value held in the memory address. But you can still pass the pointer back out...
    (Note the * added in the first line of the function)
    Code:
    int *changeInt(int *ptrx)
      { *ptrX = 23;
        return ptrx; }

  4. #4
    Registered User
    Join Date
    Feb 2011
    Posts
    50
    Please bear with me. If I can't understand pointers, I can't program C.
    Bunch of stupid questions:
    Code:
    char txt; //Is this a legal dim? If so how would you use it?
    char txt[6];
    txt = "12345"; //This doesn't work because txt is actually a pointer yes?:
    strcpy(txt,"12345"); //this works which indicates that "12345" as seen from strcpy is actually a pointer too, yes?
    Is this illegal? My compile says it is:
    Code:
    	int x=5;
    	int *ptrX;
    	ptrX = x;
    Is the only (or normal) way to do this as suggested: ptrX = &x; ??

    I've got some actual functions that I'm snagged on over pointers.
    I'll write them as best I can and post them.
    I'm hoping you'll show me how you would write them.
    Maybe that will help.
    I'm not just interested in possibles, I'm hoping to learn normal C coding conventions from you experts

  5. #5
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314

  6. #6
    Third Eye Babkockdood's Avatar
    Join Date
    Apr 2010
    Posts
    352
    rags_to_riches' code should work for you. An alternative would be to use a global variable. That is, a variable every function has access to.

    Also, when you declared your txt string, you didn't leave room for a null terminator. Declare it as char txt[6] if you want it to hold five characters.
    Quote Originally Posted by The Jargon File
    Microsoft Windows - A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition.

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,425
    Quote Originally Posted by Babkockdood View Post
    An alternative would be to use a global variable. That is, a variable every function has access to.
    That's not good advice to be giving to people learning to program. MAtkins, please don't use global variables. Here is a great explanation of all the problems they cause.

  8. #8
    Registered User
    Join Date
    Feb 2011
    Posts
    50
    OK, what do you think of this?
    I'm not at all squeemish about criticism as long as it's to help me program better

    Code:
    int indexOf(char *str1, char *str2)
    {					//Is this the best way to do this?
    	char *ptr2;
    	int idx;
             
        ptr2 = strstr(str1,str2);
    	idx = ptr2 - str1;
    	if(idx < 0) idx = -1;	
    	return idx; //will the memory for idx still be allocated once it is returned?
    	//Does 'return' pass the allocation on or kill it even though I've returned it?
    }
    char *strReplaceAll(char *st, char *orig, char *repl) 
    {
    	char *buffer = malloc((strlen(st) - srlen(orig)) + strlen(repl) + 1);
    	char *ch;
    	char *ptrSt = &st;
    	
    	if (!(ch = strstr(st, orig))) return st;
    	strncpy(buffer, st, ch-st);  
    	buffer[ch-st] = 0;
    	
    	//sprintf automatically moves the 0 to the end after putting the string together??
    	sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
    	ptrSt = *buffer;
    	free(buffer); //Did I successfully copy the contents of buffer to the original memory location of txt1
    	//Does ptrSt (that is, txt1) still contain the contents (in the originally allocated memory space for txt1) that was in buffer?
    	if ((ch = strstr(st, orig)))
    	{
    		ptrSt = strReplaceAll(ptrSt, orig, repl);
    	}
    	
    	return ptrSt;	
    }
    int main(int argc, char *argv[])
    {
    	char *txt1 = argv[1];
    	{		
    		char *txt2 = argv[2];
    		char *txt3 = argv[3];
    		int x = indexOf(txt1,txt2); 
    		txt1 = strReplaceAll(txt1, txt2, txt3);
    	}
    	//is the memory for argv[2] & argv[3] still allocated?
    	//Does txt1 still point to the location of the original argv[1] but with a different size & a changed value?
    	return 0;
    }
    Well I compiled it and I see that the whole thing with ptrSt doesn't work.
    I just cannot figure out how to make the original memory argv[1] change in that function.
    All I'm really trying to do is allocate as *little* memory as possible and get that changed value back into main.

    How would you gurus write this stuff?
    Last edited by MAtkins; 02-12-2011 at 10:03 AM.

  9. #9
    Registered User
    Join Date
    Feb 2011
    Posts
    50
    Thanks for the help & suggestions.
    Globals? Sorry no go there for me.
    I'm really not looking for ad-hoc solutions.

    I know some of you guys throw strings & objects into functions to change them and spit them back out every day.


    I'm trying to learn conventions. Surely this isn't some new unique scenario.
    I do this *all the time* except I'm used to 'managed' code. That is, I never have to worry about managing memory.
    This is more difficult but obviously a lot more powerful as well.

    Like:
    string myStr = doSomeStringStuff(MyInString, MyOtherInString);
    <... do some stuff with the changed string ...>

    I'm reading that tut now. I hadn't run into this one. Thanks

  10. #10
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,425
    Quote Originally Posted by MAtkins View Post
    //will the memory for idx still be allocated once it is returned?
    //Does 'return' pass the allocation on or kill it even though I've returned it?
    Just like function parameters, function return values are passed by value. It takes the number inside idx, puts that in a register and returns from the function call, leaving just the data and no "allocation".
    //sprintf automatically moves the 0 to the end after putting the string together??
    Yes, it always null terminates, meaning you always need one more byte than you plan for that null
    //Did I successfully copy the contents of buffer to the original memory location of txt1
    Nope.
    //Does ptrSt (that is, txt1) still contain the contents (in the originally allocated memory space for txt1) that was in buffer?
    ptrSt was set to the first character in buffer, which should have generated a warning. You declared ptrSt as a char *, but *buffer is just a plain char. Even if you did ptrSt = buffer, you are reassigning that pointer to contain just the address of the malloc'ed memory.
    //is the memory for argv[2] & argv[3] still allocated?
    Yes. txt2, txt3 and x however went out of scope when the program hit the } on line 42.
    //Does txt1 still point to the location of the original argv[1] but with a different size & a changed value?
    Nope, it points to what is likely a bogus address, since you assigned ptrSt to *buffer and returned that. There's no way to resize it.

    Well I compiled it and I see that the whole thing with ptrSt doesn't work.
    I just cannot figure out how to make the original memory argv[1] change in that function.
    All I'm really trying to do is allocate as *little* memory as possible and get that changed value back into main.
    So you would have to strcpy/strcat/sprintf directly into st in your strReplaceAll function. This is only going to work if replace is shorter than original, otherwise you would need to grow argv[1], which isn't possible in C. At least it wont happen automatically, you will need to allocating new memory for the string, but then you wont change the contents of argv[1]. You could make argv[1] itself point to the newly allocated memory however.

    How would you gurus write this stuff?
    I will try to whip something up before company arrives in 20 minutes or so.

  11. #11
    a_capitalist_story
    Join Date
    Dec 2007
    Posts
    2,648
    With what IDE are you developing? I would sincerely suggest that best way to learn what is occurring in your program is to step through the code in the debugger, watching the variables you are manipulating through each step.

  12. #12
    Registered User
    Join Date
    Feb 2011
    Posts
    50
    Quote Originally Posted by rags_to_riches View Post
    With what IDE are you developing? I would sincerely suggest that best way to learn what is occurring in your program is to step through the code in the debugger, watching the variables you are manipulating through each step.
    You guys are helping,
    I'm still studying that doc referenced above in this thread.
    It's the most informative I've seen yet.

    Would you believe Notepad++ and a bat file of gcc commands to compile??
    The compile time errors are helping a lot.

    Back to that doc w/ me . . .

  13. #13
    a_capitalist_story
    Join Date
    Dec 2007
    Posts
    2,648
    I guess that gdb (the GNU debugger) would work for you then. Here's one tutorial, and another, and here's a cheatsheet.

  14. #14
    Registered User
    Join Date
    Feb 2011
    Posts
    50
    Bayint Naung: that was a great read, thanks!
    OK, I see a lot more clearly now.

    My challenge is this.
    I'm creating a dll in C that is accessible from C# (which manages its own memory).
    From C# I need to call:
    Code:
    string myPerson[] = getMyPerson();
    string myStr = getOrigString();
    myStr = myCDLL.strReplaceAll(myStr, "FName", myPerson[3]);
    I'm trying to learn the most efficient way to write the dll function strReplaceAll

    If I malloc the memory in strReplaceAll and then pass the memory address to this C# app will the C# app free the memory when it's done using it or did I create a memory leak?
    Also, what happens to 'leaked' memory when the dll is destroyed? Does it remain in limbo until I reboot?

  15. #15
    Registered User
    Join Date
    Feb 2011
    Posts
    50
    Ack! I'm reading this thread:
    Str_replace function

    I'm beginning to think that I can't reasonably do what I'm trying to do at all.
    Is this true?

    Again, I'm trying to create a dll in C having an EXPORTable function:
    strReplaceAll (and I've learned that this is an illegal function name which isn't really a problem)
    that I can access from C#.

    In C# I want to be able to:

    myStr = myCDLL.replaceStrAll(myStr, "FName", sFName);

    The stumper for me is memory allocation that will be safe yet accessible from C#.
    Is this even possible?

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21