![]() |
| | #1 |
| Registered User Join Date: Nov 2007
Posts: 26
| Anyone know why I'm getting an "incompatible types in return" error for : Code: if (fgets_ptr == NULL) return -1; Even when I remove the line, the function still does not behave as intended. I'm trying to take an entry, clear the buffer, and keep taking entries until the user gets it right (string neither to long nor empty), and finally remove the newline if there is one. Can anyone see what's going on here? Thanks. -SH Code: contact input () /* gets an entry from the user */
{
contact entry = {'\0','\0','\0','\0','\0','\0','\0','\0'}; /* initializes the structure */
char *fgets_ptr;
int length;
do{
printf ("\nEnter a new name.\n\n>");
fgets(entry.name, sizeof(entry.name), stdin);
fgets_ptr = fgets(entry.name , sizeof(entry.name), stdin);
if (fgets_ptr == NULL) return -1;
while((junk = getchar()) != '\n' && junk != EOF);
if ( strchr(entry.name, '\n') == NULL ){ /* if overflow */
printf ("\nYour entry is too long, please try again.");
entry.name[0] = '\0';
}
} while (entry.name[0] == '\0' || entry.name[0] == '\n');
length = strlen (entry.name);
if (entry.name[length - 1] == '\n'){
entry.name[length - 1] == '\0';} /* replace \n */
return entry;
}
|
| SiliconHobo is offline | |
| | #2 |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| That's because your return type is a struct of type contact, but -1 isn't of type contact, is it? |
| Elysia is offline | |
| | #3 |
| Registered User Join Date: Nov 2007
Posts: 26
| Hmmm, so what do I return if I want this to compile and run without crashing if fgets returns NULL? Also, when I remove this line the code compiles but I get prompted for a name and must hit enter 3 times before I get prompted for a name again, regardless of whether my entry was empty or too long. It seems to be an infinite loop. Is there something wrong with my do-while syntax? Thanks for reading. Last edited by SiliconHobo; 11-29-2007 at 08:53 AM. |
| SiliconHobo is offline | |
| | #4 |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| The solution depends on what how you use your function elsewhere. One solution is that you pass in a pointer to a contact, and fill it in (unless it fails), then return a "success/fail" value. Or you could allocate some memory with malloc for a contact, and if you then fail to read in the data, free the memory and return NULL. By the way: Code: fgets(entry.name, sizeof(entry.name), stdin);
fgets_ptr = fgets(entry.name , sizeof(entry.name), stdin);
-- 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. |
| matsp is offline | |
| | #5 |
| Registered User Join Date: Nov 2007
Posts: 26
| Yes, only once in each run through the do-while. Thanks. Now I only have to hit enter twice instead of 3 times :P Could it be something to do with : Code: while((junk = getchar()) != '\n' && junk != EOF); Last edited by SiliconHobo; 11-29-2007 at 09:01 AM. |
| SiliconHobo is offline | |
| | #6 |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| Most certainly - you only need that if you don't have a newline at the end of the entry.name, so you need to swap place between the if-statement checking for newline and the while-loop reading any leftover data. Also, perhaps you may want to indent your code so that your loops are visible [one advantage of learning to program in Python is that indentation is enforced - your code don't work right if you sloppily just put things wherever you feel like.] -- 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. |
| matsp is offline | |
| | #7 |
| Jack of many languages Join Date: Nov 2007 Location: Katy, Texas
Posts: 1,929
| It was working just fine when it looked like this: http://cboard.cprogramming.com/showp...08&postcount=6 Compare any differences. Todd |
| Dino is offline | |
| | #8 |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| The usual way for functions to return success/fail is typically that they take an argument (in this case, a pointer) to a "buffer" where it can store the information and returns bool, int, whatever to indicate success or failure. |
| Elysia is offline | |
| | #9 |
| Registered User Join Date: Nov 2007
Posts: 26
| Thanks for the replies. Todd: I know you gave the exact working code but I wanted to write my own based on what I learned from your example rather than simply copy/paste. I have now got the get_input function working fine on its own. However, when I try to write another function that calls get_input repeatedlly with different prompt and pointer parameters for each field in the contact structure: Code: int get_input (char, contact); Code: contact input () /* gets an entry from the user */
{
contact entry = {'\0','\0','\0','\0','\0','\0','\0','\0'}; /* initializes the structure */
contact *input_ptr;
input_ptr = &entry;
char prompt1[25] = "Please enter a new name.";
get_input (prompt1, &input_ptr->name);
return (entry);
}
int get_input (prompt, *input_ptr)
{
char *fgets_ptr;
char junk = 0;
int length;
do{
printf ("\n%s\n\n>", prompt);
*fgets_ptr = fgets(*input_ptr, sizeof(*input_ptr), stdin);
if (fgets_ptr == NULL) return -1;
if ( strchr(*input_ptr, '\n') == NULL ){ /* if overflow */
printf ("\nYour entry is too long, please try again.\a");
while((junk = getchar()) != '\n' && junk != EOF);
*input_ptr[0] = '\0';
}
} while (*input_ptr[0] == '\0' || *input_ptr[0] == '\n');
length = strlen (*input_ptr);
if (*input_ptr[length - 1] == '\n'){
*input_ptr[length - 1] == '\0';} /* replace \n */
}
Code: Compiler: Default compiler Executing gcc.exe... In function `input': 106: warning: passing arg 1 of `get_input' makes integer from pointer without a cast 106: error: incompatible type for argument 2 of `get_input' At top level: 111: error: syntax error before '*' token In function `get_input': 112: error: number of arguments doesn't match prototype 30: error: prototype declaration 118: error: `prompt' undeclared (first use in this function) 118: error: (Each undeclared identifier is reported only once 118: error: for each function it appears in.) 119: error: `input_ptr' undeclared (first use in this function) 119: warning: assignment makes integer from pointer without a cast Execution terminated -SH Last edited by SiliconHobo; 12-02-2007 at 05:50 AM. |
| SiliconHobo is offline | |
| | #10 |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| No wonder. You're not getting the hang of the syntax. A couple of tutorials might be in place. Especially functions and pointers: Functions: http://www.cprogramming.com/tutorial/c/lesson4.html Pointers: http://www.cprogramming.com/tutorial/c/lesson6.html |
| Elysia is offline | |
| | #11 |
| Registered User Join Date: Nov 2007
Posts: 26
| Okay. I read them but no light bulbs are coming on atm. If I could understand the errors that would probably help. The only one I'm familiar with is the undeclared variables error but I don't see why I'm getting it since the stated variables are declared as parameters in get_input. Last edited by SiliconHobo; 12-02-2007 at 06:04 AM. |
| SiliconHobo is offline | |
| | #12 |
| Jack of many languages Join Date: Nov 2007 Location: Katy, Texas
Posts: 1,929
| OK, let's go over function declarations, function calls and function definitions. The summary of all this will be that they have to match. Your declaration is this: Code: int get_input (char, contact); For function call is this: Code: get_input (prompt1, &input_ptr->name); You've scored 0 for 2 so far. Now, your function definition says this: Code: int get_input (prompt, *input_ptr) 3 strikes - you are out. (Actually, more bugs than that - but I won't dwell on something you don't understand with too critical an eye.) Now, Going back to my first point that the function declaration, function call and function definition have to match. You need to decide if you want pass parms by value or by reference. Here's an example of the differences between the two. Call by value: You tell the compiler to make a copy (essentially) of whatever variable you want to pass to a function. The compiler (well, it's not actually the "compiler", but the code generated BY the compiler - but I'll call it the compiler for discussion purposes) will make a copy of the "value" and place it on the stack. When the function gets control, it uses the copy of the value and cannot touch the original value. Here's a commented example: Code: #include <stdio.h>
int myfunc(char) ; // function declaration
int main() {
char mychar = 'Z' ;
int rc ; // return code
// mychar will be Z
printf("main: before myfunc() call, mychar = %c\n", mychar) ;
// Call myfunc(), using a call be value syntax. A copy of the
// actual value of mychar will be placed on the stack. myfunc() will
// never have access to the original mychar variable.
rc = myfunc(mychar) ; // function call
// Print out the value of mychar. It will still be Z, because
// function myfunc() changed the copy of mychar that was placed
// on the stack. This now proves that function myfunc() did not
// use the original value of mychar - it only changed a temporary
// copy of it that was on the stack.
printf("main: after myfunc() call, mychar = %c\n", mychar) ;
return 0 ;
}
int myfunc(char xxx) { // function definition
// report the incoming value.
printf("xxx should be Z, and it is: %c \n", xxx ) ;
// Change variable xxx to a new value.
xxx = 'H' ;
// This shows that the value was changed.
printf("xxx should be H, and it is: %c \n", xxx) ;
return 0 ;
}
Call by reference: Let's change our example just a little now to a call-by-reference call. We need to use a pointer variable and change our function declaration, call and definition. The primary differences are in red. Code: #include <stdio.h>
int myfunc(char *) ; // function declaration
int main() {
char mychar = 'Z' ;
char * myptr ;
int rc ; // return code
myptr = &mychar ; // Initialize myptr pointer to the address of mychar.
// mychar will be Z
printf("main: before myfunc() call, mychar = %c\n", mychar) ;
printf("main: before myfunc() call, myptr = %p\n", myptr) ;
// Call myfunc(), using a call be reference scheme. The pointer to the
// actual value of mychar will be placed on the stack. myfunc() can
// now access the original mychar variable.
rc = myfunc(myptr) ; // function call
// Print out the value of mychar. We passed a pointer to mychar,
// and function myfunc() changed the value of it through indirection.
printf("main: after myfunc() call, mychar = %c\n", mychar) ;
printf("main: after myfunc() call, myptr = %p\n", myptr) ;
return 0 ;
}
int myfunc(char * xxx) { // function definition
// report the incoming value.
printf("xxx value should be Z, and it is: %c \n", *xxx ) ;
printf("xxx pointer is is: %p \n", xxx ) ;
// Through pointer xxx, variable the value to a new value.
*xxx = 'H' ;
// This shows that the value was changed.
printf("xxx value should be H, and it is: %c \n", *xxx) ;
return 0 ;
}
Here's the first example repeated to focus on the the return type. Code: #include <stdio.h>
int myfunc(char) ; // function declaration
int main() {
char mychar = 'Z' ;
int rc ; // return code
// mychar will be Z
printf("main: before myfunc() call, mychar = %c\n", mychar) ;
// Call myfunc(), using a call be value syntax. A copy of the
// actual value of mychar will be placed on the stack. myfunc() will
// never have access to the original mychar variable.
rc = myfunc(mychar) ; // function call
// Print out the value of mychar. It will still be Z, because
// function myfunc() changed the copy of mychar that was placed
// on the stack. This now proves that function myfunc() did not
// use the original value of mychar - it only changed a temporary
// copy of it that was on the stack.
printf("main: after myfunc() call, mychar = %c\n", mychar) ;
return 0 ;
}
int myfunc(char xxx) { // function definition
// report the incoming value.
printf("xxx should be Z, and it is: %c \n", xxx ) ;
// Change variable xxx to a new value.
xxx = 'H' ;
// This shows that the value was changed.
printf("xxx should be H, and it is: %c \n", xxx) ;
return 0 ;
}
Definition: myfunc() repeats the same "declaration" again in the definition, stating it will return an int value. And, indeed, it issues a return 0 ; before it exits. Call: When called, the call needs to do something with int that is returned from the call to myfunc(). It does this by assigning the value to the variable rc. Again, all threes match. Also, note the green code above. The exact same thing is being done for main() - we just don't have a function declaration for main(). Hope this helps. Todd Last edited by Dino; 12-02-2007 at 04:08 PM. |
| Dino is offline | |
| | #13 |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| Syntax for function are as following (see Todd's example too of course): Declarations: Code: ReturnType FunctionName(ArgumentType ArgumentName, ArgumentType2 ArgumentName2); Function definition is the same: Code: ReturnType FunctionName(ArgumentType ArgumentName, ArgumentType2 ArgumentName2)
{
/* Your code here */
}
This should also help. |
| Elysia is offline | |
| | #14 |
| Registered User Join Date: Nov 2007
Posts: 26
| Okay, thanks Todd and Elysia for the detailed explanation. I've simplified the program and I believe my declaration, call and function now match. Code: char get_input (char[26]); Code: get_input (prompt1); Code: char get_input (char prompt[26]) Code: contact input () /* gets an entry from the user */
{
contact entry = {'\0','\0','\0','\0','\0','\0','\0','\0'}; /* initializes the structure */
char prompt1[26] = "Please enter a new name.";
char prompt2[26] = "Enter a street address.";
char prompt3[26] = "Enter a city.";
char prompt4[26] = "Enter a province.";
char prompt5[26] = "Enter a post code.";
char prompt6[26] = "Enter a country.";
char prompt7[26] = "Enter a date of birth.";
char prompt8[26] = "Enter a phone number.";
char prompt9[26] = "Enter an email address.";
entry.name = get_input (prompt1);
entry.add.street = get_input (prompt2);
entry.add.city = get_input (prompt3);
entry.add.state = get_input (prompt4);
entry.add.post = get_input (prompt5);
entry.add.country = get_input (prompt6);
entry.birth = get_input (prompt7);
entry.phone = get_input (prompt8);
entry.email = get_input (prompt9);
return (entry);
}
char get_input (char prompt[26])
{
char string [50] = {0};
char junk = 0;
int length;
do{
printf ("\n%s\n\n>", prompt);
fgets(string, sizeof(string), stdin);
if ( strchr(string, '\n') == NULL ){ /* if overflow */
printf ("\nYour entry is too long, please try again.\a");
while((junk = getchar()) != '\n' && junk != EOF);
string[0] = '\0';
}
} while (string[0] == '\0' || string[0] == '\n');
length = strlen (string);
if (string[length - 1] == '\n'){
string[length - 1] == '\0';} /* replace \n */
return (string);
}
Code: typedef struct address_tree /* address sub-strcuture */
{
char street[50];
char city[50];
char post[50];
char state[50];
char country[50];
}address;
typedef struct top_tree /* top-level database structure */
{
char name[50];
char email[50];
char birth[50];
char phone[50];
address add;
}contact;
|
| SiliconHobo is offline | |
| | #15 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| There is definetly an advantage - to your program's layout. It would make sense to have your address with all the other information. And making a struct out of that can also be helpful. For your error, you declare return type as char but you return char* (just for reference, returning an array for sort automatically casts it to a pointer, so a char array becomes char*). What is the solution? There are several, but the one that's most recommended is that get_input takes a char* argument to a buffer to fill. And it should take a size argument too, to make sure that it doesn't input more data than space available in the buffer.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Undefined Reference Compiling Error | AlakaAlaki | C++ Programming | 1 | 06-27-2008 11:45 AM |
| dllimport function not allowed | steve1_rm | C++ Programming | 5 | 03-11-2008 03:33 AM |
| airport Log program using 3D linked List : problem reading from file | gemini_shooter | C Programming | 3 | 03-04-2005 02:46 PM |
| c++ linking problem for x11 | kron | Linux Programming | 1 | 11-19-2004 10:18 AM |
| Contest Results - May 27, 2002 | ygfperson | A Brief History of Cprogramming.com | 18 | 06-18-2002 01:27 PM |