Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Simple Function Problems 2

Status
Not open for further replies.

willz99ta

IS-IT--Management
Sep 15, 2004
132
US
For some reason the damn compiler gives me the errors:
warning C4047: 'function' : 'const char *' differs in levels of indirection from 'char '

and

'strcpy' : different types for formal and actual parameter 2

and

'MoveToHold' : different types for formal and actual parameter 1


Thanks for any help you can give!
Willz99ta

Code:
char MoveToHold(char RealPath)
{
	char   OldName[500] = strcat(                      "/usr/users/tchristo/997Test/" , RealPath );
	char NewName[500] = strcat( "/usr/users/tchristo/997Hold/",RealPath);

	char ErrorLister[500];
	int result;

	result= rename(OldName,NewName);

	if (result != 0 )
	{
	strcpy(ErrorLister,"Error: Cannot Rename file ");
	strcat(ErrorLister,RealPath);
	strcat(ErrorLister,"\n");
	}

	return ErrorLister;
}


 
Hi:

First, I've never seen strcat used that way. It doesn't work with my Solaris 7 compiler. Also, if you're going to return a string like this, the MoveToHold function must be declared a point-to-a-function:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

char *MoveToHold(char *RealPath);

int main (int argc, char *argv[])
{
char *retval;

retval=malloc(700 * (sizeof(char) + 1));
if (retval == NULL)
{
printf("ERROR: Unable to malloc space!!! \n");
exit (-1);
} /* malloc error */
retval=MoveToHold("something");
printf("%s\n", retval);
}

char *MoveToHold(char *RealPath)
{
char OldName[500];
char NewName[500];
char ErrorLister[500];
int result;

strcpy(OldName, "/usr/users/tchristo/997Test/");
strcat(OldName, RealPath);

strcpy(NewName, "/usr/users/tchristo/997Hold/");
strcat(NewName, RealPath);

result= rename(OldName,NewName);

if (result != 0 )
{
strcpy(ErrorLister,"Error: Cannot Rename file ");
strcat(ErrorLister,RealPath);
strcat(ErrorLister,"\n");
}

return ErrorLister;
}
 
Very Useful advice olded. But I still get this error for some reason!:
"returning address of local variable or temporary"

Here is my most current code:

Code:
char *MoveToHold(char *RealPath)
{
	char OldName[500]="/usr/users/tchristo/997Test/";
	char NewName[500]="/usr/users/tchristo/997Hold/";
	char Error[500]="";
	int result=0;

	result= rename(OldName,NewName);

	strcat(OldName,RealPath);
	strcat(NewName,RealPath);

	if (result != 0 )
	{
		strcpy(Error,"Error: Cannot Rename file ");
		strcat(Error,RealPath);
		strcat(Error,"\n");
	}
	else
	{
		strcpy(Error,RealPath);
		strcat(Error," was moved to 997Hold");
	}

	return Error;
}
 
>>returning address of local variable or temporary
You are returning "Error", which a variable local to the MoveToHold function. Once that function completes, the Error variable goes out of scope (and existance!).

Normally, when returning a functions result, you'd pass back a number rather than a string, as it is easier to deal with.

Here's an example of one way it can be done:
Code:
#include <stdio.h>

enum Errors
{
  ERR_NO_ERROR,
  ERR_CANNOT_RENAME,
  ERR_COUNT
};

char *Errors_str[ERR_COUNT] = 
{
  "No error",
  "Cannot rename file"
};

enum Errors foo(void)
{
  enum Errors rc;
  
  /*
   * make up a return code for example's sake
   */
  rc = ERR_CANNOT_RENAME;
  
  return rc;
}

int main(void)
{
  enum Error rc;
  
  rc = foo();
  
  printf ("Return was: %s\n", Errors_str[rc]);
  return(0);
}
 
Hi:

I agree with Hammer; I don't like to return strings like what you're doing. But if you insist on it, this is a problem:

char OldName[500]="/usr/users/tchristo/997Test/";
char NewName[500]="/usr/users/tchristo/997Hold/";

"C" does NOT allow this. It's untested, but this should work:

char *OldName="/usr/users/tchristo/997Test/";
char *NewName="/usr/users/tchristo/997Hold/";

also, I'd use the declaration:

static char Error[500];

 
You cannot return an array regardless of scope.
The end of discussion.
Make Error global or malloc and free
it after each error call.

 
To olded:
Case 1:
Code:
char OldName[500]="/usr/users/tchristo/997Test/";
char NewName[500]="/usr/users/tchristo/997Hold/";
are legal (but slightly suspicious;) constructs.
Case 2:
Code:
char *OldName="/usr/users/tchristo/997Test/";
char *NewName="/usr/users/tchristo/997Hold/";
are legal but dangerous and deprecated constructs. These non-const pointers now refer to constant memory (where text literals placed). It's legacy (backward compatibility) language problem.

You may:
Code:
const char* f() {
...
static char msg[128]; /* It's local but long-lived storage*/
...strcpy(msg,"...");
...strcat(msg,"..."); /* common and dangerous using... */
...
return msg;
}
You don't return an array in that case: you return a pointer. In C (and C++) array name implicitly converts to pointer in all executable contexts except sizeof operator arg.
Apropos, it's not the best style to return messages from a function, but it's a legal case...
 
char OldName[500]="/usr/users/tchristo/997Test/";
char NewName[500]="/usr/users/tchristo/997Hold/";

"C" does NOT allow this. It's untested, but this should work:

char *OldName="/usr/users/tchristo/997Test/";
char *NewName="/usr/users/tchristo/997Hold/";

also, I'd use the declaration:

static char Error[500];
That is perfectly fine... Except that the the memory declared by the array disappears after the function terminates. The later works because the compiler puts all the string literals into memory at the start of the program.

Marsd has the right idea. You need to deal with dynamic memory allocation or make the buffer holding the names global... In which case, you'll also want to follow ArkM's advice and use str functions to load the string literal into the array.
Code:
char directoryOld[500];
void f() 
{
//...
  strcpy(directoryOld,"/usr/users/tchristo/997Test/");
//...
}

This way, if char directoryOld is at the top of your .c then you need not return, as the directoryOld will be in scope everywhere.

[plug=shameless]
[/plug]
 
Thanks for all of the helpful hints above, but I now get two errors and I cannot figure out why.

Errors:
warning C4047: 'return' : 'int *' differs in levels of indirection from 'const int '
warning C4047: '==' : 'int *' differs in levels of indirection from 'const int '

Code:
Code:
//////////////////////////////////////////////////
/*File Moving Function -- This moves files with errors 
to the 997Hold directory*/

int *MoveToHold(char *RealPath)
{
	char OldName[500]="/usr/users/tchristo/997Test/";
	char NewName[500]="/usr/users/tchristo/997Hold/";
	int Error=0;
	int result=0;

	strcat(OldName,RealPath);
	strcat(NewName,RealPath);
	
	result= rename(OldName,NewName);

	if (result != 0 )
	{
		return 1;
//warning C4047: 'return' : 'int *' differs in levels of //indirection from 'const int '
	}
	else
	{
		return 0;
	}

}
	
//////--This is where the function is used in Main--\\\\\\\
						
if (MoveToHold(RealPath) == 1)
//warning C4047: '==' : 'int *' differs in levels of //indirection from 'const int '
{
     strcpy(ErrorLister,"Error: Cannot Rename file ");
     strcat(ErrorLister,RealPath);
     strcat(ErrorLister,"\n");
}

else if (MoveToHold(RealPath) == 0)
{
     strcpy(ErrorLister,RealPath);
     strcat(ErrorLister," was moved to 997Hold\n");
}


Thanks for any help you can give me,
Willz99ta
 
The function no longer a returns a character pointer.

Try changing:

int *MoveToHold(char *RealPath)

to

int MoveToHold(char *RealPath)


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top