Trying to get string input using fgets

I am trying to grab string input from a user from the keyboard (addres

Page 1 of 1

9 Replies - 4750 Views - Last Post: 13 February 2008 - 02:51 AM Rate Topic: -----

#1 andymoon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 12-February 08

Trying to get string input using fgets

Post icon  Posted 12 February 2008 - 11:58 AM

For some reason, I have to use two gets statements (I know I'm not supposed to use gets, but it is working and fgets isn't) or fgets statements or they simply pass the first input and go on to the second. The gets instances are about 2/3 of the way down in the CompareStrings function and the fgets instances are very close to the bottom in the StudentStructure function. Everything else seems to work properly, but getting that address string is pi$$ing me off.

Any help would be greatly appreciated.

 
//code for header file, "structDefs.h"

 

typedef struct 
   {
	  int x; 
	  int y; 
	} POINT;  

typedef struct 
   { 
	 POINT begPoint; 
	 POINT endPoint;
   } LINE; 

typedef struct
 {
 char fname[10];
		char lname[16];   
		char std_id[9];
		char phone[10];
		char a_num[20];
	   char a_street[20];
 char address[50];
		char email[20];
 } STUDENT;

 

/* Performs three completely unrelated functions for an instructor

that is at best clueless*/


#include <stdio.h>
#include "structDefs.h"

void compareStrings();
LINE LineStructure(POINT begPoint, POINT endPoint);
STUDENT StudentStructure(void);

int main()
{

int startx;  
int starty; 
int endx;  
int endy; 
POINT begPoint; 
POINT endPoint; 
LINE thisLine;
STUDENT stud1;

int userSelection =0;

do {
printf("\n\tWhich program do you want to run?\n");
	printf("\t1 = Compare two strings\n");
	printf("\t2 = Create a line\n");
	printf("\t3 = Input student information\n");
	printf("\t4 = Exit\n");
scanf("%d",&userSelection);

switch (userSelection)				 
	{
	case 1: userSelection=1; 
		compareStrings();
		break;

	case 2: userSelection=2;
		printf("Enter the starting point coordinates: ");
 scanf ("%d%d", &startx, &starty); 
 printf("\nEnter the ending point coordinates: ");
 scanf ("%d%d", &endx, &endy);  
 begPoint.x=startx;
 begPoint.y=starty;
 endPoint.x=endx;
 endPoint.y=endy;
 thisLine=LineStructure(begPoint, endPoint);
 printf("The first point coordinates are (%d, %d)",thisLine.begPoint.x, thisLine.begPoint.y);
 printf("The second point coordinates are (%d, %d)",thisLine.endPoint.x, thisLine.endPoint.y);
		break;

	case 3: userSelection=3;
		stud1=StudentStructure();
		break;

	case 4: userSelection=4;
		printf("Thank you.\n");
		break; 

	default: printf("Invalid option selected\n");
	} 
} 
while (userSelection != 4);

return 0;
}

void compareStrings (void)
{
// Local Declarations 
 char string1[255];
 char string2[255];
 int strLenStr1;
 int strLenStr2;

// Statements
 printf ("Enter the first string (254 characters max): ");
 gets(string1);
gets(string1);
 printf ("\nEnter the second string (254 characters max): ");
 gets(string2);
 strLenStr1=strlen(string1);
 strLenStr2=strlen(string2);
 if(strLenStr1!=strLenStr2)
  if(strLenStr1>strLenStr2)
   printf("%s > %s",string1, string2);
  else
   printf("%s < %s",string1, string2);
 else
  printf("%s = %s", string1, string2);
}

LINE LineStructure (POINT start, POINT end) 
{ 
LINE MyLine; 
MyLine.begPoint.x= start.x; 
MyLine.begPoint.y= start.y; 
MyLine.endPoint.x= end.x; 
MyLine.endPoint.y= end.y; 
return MyLine; //MUST RETURN STRUCTURE OF TYPE LINE 
} //end line structure 

STUDENT StudentStructure(void)
{
STUDENT stud1;

printf("\nEnter student's first name: ");
scanf ("%s", &stud1.fname);

printf("Enter student's last name: ");
scanf ("%s", &stud1.lname);

printf("Enter student's ID: ");
scanf ("%s", &stud1.std_id);

printf("Enter student's address: ");
fgets(stud1.address,50,stdin);
fgets(stud1.address,50,stdin);

printf("Enter student's phone number (no spaces): ");
scanf ("%s", &stud1.phone);

printf("Enter student's email address: ");
scanf ("%s", &stud1.email);

printf("\nHere is what you entered:\n");
printf("\nFirst Name: %s \n", stud1.fname);
printf("\nLast Name: %s \n", stud1.lname);
printf("\nID #: %s\n", stud1.std_id);
printf("\nAddress: %s \n", stud1.address);
printf("\nPhone: %s \n", stud1.phone);
printf("\nEmail address: %s \n", stud1.email);

return stud1;
}

 

This post has been edited by andymoon: 12 February 2008 - 12:44 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Trying to get string input using fgets

#2 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Trying to get string input using fgets

Posted 12 February 2008 - 12:06 PM

Really, you should be using fgets in place of scanf too - because scanf has the same problems as gets, along with some other hidden "gotcha's" too.

The hidden 'gotcha' which is causing your problem here, is that scanf is leaving a hidden new-line character in the stdin stream - so your first call to fgets only picks up the new-line char, and nothing else.

I strongly recommend you read these C FAQ articles
http://www.c-faq.com...finterlace.html
http://www.c-faq.com...scanfprobs.html
http://www.c-faq.com...etsvsfgets.html
http://www.c-faq.com...tdinflush2.html

This post has been edited by Bench: 12 February 2008 - 12:09 PM

Was This Post Helpful? 0
  • +
  • -

#3 andymoon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 12-February 08

Re: Trying to get string input using fgets

Posted 12 February 2008 - 12:11 PM

Thank you for the reading material. Can you explain why I get no output when I printf the stud1.address variable?
Was This Post Helpful? 0
  • +
  • -

#4 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Trying to get string input using fgets

Posted 12 February 2008 - 12:34 PM

View Postandymoon, on 12 Feb, 2008 - 07:11 PM, said:

Thank you for the reading material. Can you explain why I get no output when I printf the stud1.address variable?

Probably for the same reason as those C FAQ links explain, that your stud1.address array is essentially left empty after the call to fgets.
- When fgets sees the lone '\n' character in the stream, it reads that newline character into your stud1.address array, and ceases to read from stdin (It will also add an invisible '\0' terminating character after the '\n'). Your program continues straight to the next statement. When you output it with printf, it'll look as if stud1.address is empty.

This post has been edited by Bench: 12 February 2008 - 12:42 PM

Was This Post Helpful? 0
  • +
  • -

#5 andymoon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 12-February 08

Re: Trying to get string input using fgets

Posted 12 February 2008 - 12:41 PM

View PostBench, on 12 Feb, 2008 - 12:34 PM, said:

View Postandymoon, on 12 Feb, 2008 - 07:11 PM, said:

Thank you for the reading material. Can you explain why I get no output when I printf the stud1.address variable?

Probably for the same reason as those C FAQ links explain, that your stud1.address array is essentially left empty after the call to fgets.
- When fgets sees the lone '\n' character in the stream, it reads the newline character, and ceases to read from stdin - then it adds the '\n' to your stud1.address array (along with a Nul terminating character), and skips straight to the next statement. When you output it with printf, it'll look as if stud1.address is empty.


Actually, it prompts me for the input, but doesn't output anything. In addition, right before the gets and fgets statements, I am using fflush(stdin) to clear the input buffer (added since the code was posted). But, when it gets to the printf statement to print the address, it prints a blank line.

Would you like me to post the updated code?
Was This Post Helpful? 0
  • +
  • -

#6 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Trying to get string input using fgets

Posted 12 February 2008 - 12:45 PM

View Postandymoon, on 12 Feb, 2008 - 07:41 PM, said:

Actually, it prompts me for the input, but doesn't output anything. In addition, right before the gets and fgets statements, I am using fflush(stdin) to clear the input buffer (added since the code was posted). But, when it gets to the printf statement to print the address, it prints a blank line.

Would you like me to post the updated code?

Sure. Note that fflush(stdin) is undefined behaviour according to the language standard, so that may not be doing what you think it is (From the C language's perspective, you can't "flush" an input stream, though it does work on some platforms).
Was This Post Helpful? 0
  • +
  • -

#7 andymoon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 12-February 08

Re: Trying to get string input using fgets

Posted 12 February 2008 - 01:05 PM

Here is the updated code. The only issue I am having now is that in the StudentStructure function, fgets seems to be getting the input and setting the variable. When I printf immediately after the fgets statement, it prints the address. when I printf the same variable ~10 lines later, I get blank output. Wierd.


#include <stdio.h>
#include "structDefs.h"

void compareStrings();
LINE LineStructure(POINT begPoint, POINT endPoint);
STUDENT StudentStructure(void);

int main()
{

int startx;  
int starty; 
int endx;  
int endy; 
POINT begPoint; 
POINT endPoint; 
LINE thisLine;
STUDENT stud1;

int userSelection =0;

do {
printf("\n\tWhich program do you want to run?\n");
	printf("\t1 = Compare two strings\n");
	printf("\t2 = Create a line\n");
	printf("\t3 = Input student information\n");
	printf("\t4 = Exit\n");
scanf("%d",&userSelection);

switch (userSelection)				 
	{
	case 1: userSelection=1; 
		compareStrings();
		break;

	case 2: userSelection=2;
		printf("Enter the starting point coordinates: ");
 scanf ("%d%d", &startx, &starty); 
 printf("\nEnter the ending point coordinates: ");
 scanf ("%d%d", &endx, &endy);  
 begPoint.x=startx;
 begPoint.y=starty;
 endPoint.x=endx;
 endPoint.y=endy;
 thisLine=LineStructure(begPoint, endPoint);
 printf("The first point coordinates are (%d, %d)",thisLine.begPoint.x, thisLine.begPoint.y);
 printf("The second point coordinates are (%d, %d)",thisLine.endPoint.x, thisLine.endPoint.y);
		break;

	case 3: userSelection=3;
		stud1=StudentStructure();
		break;

	case 4: userSelection=4;
		printf("Thank you.\n");
		break; 

	default: printf("Invalid option selected\n");
	} 
} 
while (userSelection != 4);

return 0;
}

void compareStrings (void)
{
// Local Declarations 
 char string1[255];
 char string2[255];
 int strLenStr1;
 int strLenStr2;

// Statements
 printf ("Enter the first string (254 characters max): ");
 fflush(stdin); 
 gets(string1);
 printf ("\nEnter the second string (254 characters max): ");
 gets(string2);
 strLenStr1=strlen(string1);
 strLenStr2=strlen(string2);
 if(strLenStr1!=strLenStr2)
  if(strLenStr1>strLenStr2)
   printf("%s > %s",string1, string2);
  else
   printf("%s < %s",string1, string2);
 else
  printf("%s = %s", string1, string2);
}

LINE LineStructure (POINT start, POINT end) 
{ 
LINE MyLine; 
MyLine.begPoint.x= start.x; 
MyLine.begPoint.y= start.y; 
MyLine.endPoint.x= end.x; 
MyLine.endPoint.y= end.y; 
return MyLine; //MUST RETURN STRUCTURE OF TYPE LINE 
} //end line structure 

STUDENT StudentStructure(void)
{
STUDENT stud1;

printf("\nEnter student's first name: ");
scanf ("%s", &stud1.fname);

printf("Enter student's last name: ");
scanf ("%s", &stud1.lname);

printf("Enter student's ID: ");
scanf ("%s", &stud1.std_id);

printf("Enter student's address: ");
fflush(stdin);
fgets(&stud1.address,50,stdin);
printf("%s",stud1.address);  //testing the address variable


printf("Enter student's phone number (no spaces): ");
scanf ("%s", &stud1.phone);

printf("Enter student's email address: ");
scanf ("%s", &stud1.email);

printf("\nHere is what you entered:\n");
printf("\nFirst Name: %s", stud1.fname);
printf("\nLast Name: %s", stud1.lname);
printf("\nID #: %s", stud1.std_id);
printf("\nAddress: %s", stud1.address);
printf("\nPhone: %s", stud1.phone);
printf("\nEmail address: %s", stud1.email);

return stud1;
}



This post has been edited by andymoon: 12 February 2008 - 01:06 PM

Was This Post Helpful? 0
  • +
  • -

#8 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Trying to get string input using fgets

Posted 12 February 2008 - 04:15 PM

Whenever you retrieve input from the user into a string, either using scanf, gets, fgets, etc, you shouldn't use the & symbol ("Address of" operator) in front of the string's variable name. (You only do this with "plain old data" types, eg, int, double, etc)

The reason for this, is that arrays in C are always passed "by pointer". C treats arrays as a special case, so that their default behaviour when you refer to the name as a whole, is to return the address of their first element.
- Arrays aren't pointers, but the language doesn't allow you to implicitly copy arrays through assignment - which is how all other data types behave. So instead, the C language always performs an 'implicit cast' from an array type to a pointer data type, when using the = operator, or when passing an array into a function as an argument.

I've made the modification to your StudentStructure below, and having tested it, it would seem to work properly on my system.
STUDENT StudentStructure(void)
{
	STUDENT stud1;

	printf("\nEnter student's first name: ");
	scanf ("%s", stud1.fname);

	printf("Enter student's last name: ");
	scanf ("%s", stud1.lname);

	printf("Enter student's ID: ");
	scanf ("%s", stud1.std_id);

	printf("Enter student's address: ");
	fflush(stdin);
	fgets(stud1.address,50,stdin);
	printf("%s",stud1.address);  //testing the address variable


	printf("Enter student's phone number (no spaces): ");
	scanf ("%s", stud1.phone);

	printf("Enter student's email address: ");
	scanf ("%s", stud1.email);

	printf("\nHere is what you entered:\n");
	printf("\nFirst Name: %s", stud1.fname);
	printf("\nLast Name: %s", stud1.lname);
	printf("\nID #: %s", stud1.std_id);
	printf("\nAddress: %s", stud1.address);
	printf("\nPhone: %s", stud1.phone);
	printf("\nEmail address: %s", stud1.email);

	return stud1;
} 
Note that all of the & symbols are now gone on the scanf/fgets calls.

This post has been edited by Bench: 12 February 2008 - 04:20 PM

Was This Post Helpful? 0
  • +
  • -

#9 andymoon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 12-February 08

Re: Trying to get string input using fgets

Posted 12 February 2008 - 07:19 PM

Thank you so much!

Of course, Murphy caused the instructor to postpone our assignment date, so I spent all day on this for nothing (I even asked for extra credit for turning it in "early").

Who knows, maybe I will get industrious and turn all of the gets into fgets, much like I turned all of the scanf statements to scanf_s statements.

Just because I actually want to learn this stuff, is there anything else about this code that should be done differently?
Was This Post Helpful? 0
  • +
  • -

#10 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Trying to get string input using fgets

Posted 13 February 2008 - 02:51 AM

View Postandymoon, on 13 Feb, 2008 - 02:19 AM, said:

Just because I actually want to learn this stuff, is there anything else about this code that should be done differently?

I can't really suggest anything from the perspective of functionality - since I assume you've written your program according to your tutor's assignment specification (In which case he/she will be the better judge).

Some general comments though
- compareStrings is probably a little unnecessary, because C has a built-in function called strcmp, which returns a zero value when two strings are equal to each other.
- do some work on your code layout and formatting. Unless its just the case that your formatting was lost when you pasted into the forum (That happens sometimes if you use tab characters), your code would look more presentable and readable if different blocks were indented more consistently.
Good code formatting is a real help when it comes to tracking errors - sometimes you can spend half an hour looking for a problem, when its a simple case of a missing bracket, or a statement which appears to be inside a different code block. If you're using a plain text editor, then it takes a bit of self discipline. If you've got an IDE, then you should be able to switch on an auto-indent option.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1