[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Strange input skipping when using fgets()

Posted on 2005-04-22
15
Medium Priority
?
860 Views
Last Modified: 2008-03-17
Hello,

I'm writing a simple function that will accept a string from a user and return the string to the calling function.

int findstring(char *theString)
{
        fgets(theString, 81, stdin);
        printf( "The string is %s\n", theString);
        return theString;
}

When I do that, the function will not let the user input the string and skip directly to the printf() statement. I can force the input to stop this by changing the function to this:

int findstring(char *theString)
{
        getchar();
        fgets(theString, 81, stdin);
        printf( "The string is %s\n", theString);
        return theString;
}

And only then will it let the user type out the string, but I don't think that this is the correct solution because no words will match the string when I parse the file in another portion of the program. Also, here's what the call looks like in the parent function:

// Declaration
 char *myString = "not defined";

//Function Call
 myString = malloc(100 * sizeof(char));
 myString = (char*) findstring( (char*) myString);

So I'm allocating space for 100 characters to myString, then passing it to the function. Let me know if you need more information or code.

Thanks,
Igor
0
Comment
Question by:igor92128
  • 8
  • 6
15 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 13845608
Hi igor92128,
The return type is incorrect.
Try changing it to the following:
char * findstring(char *theString)
{
        fgets(theString, 81, stdin);
        printf( "The string is %s\n", theString);
        return theString;
}


David Maisonave :-)
Cheers!
0
 
LVL 30

Expert Comment

by:Axter
ID: 13845624
igor92128,
> >myString = (char*) findstring( (char*) myString);
You should avoid casting.
If the types are correct, you don't need to cast.

myString = findstring(myString);

Moreover, you really don't need to reset the poitner, so you can just modify your code to the following:
findstring(myString);

David Maisonave :-}
0
 

Author Comment

by:igor92128
ID: 13845830
Thanks for the advice.

I have changed my call to this: findstring(myString) and reduced my warnings by 1.

and the function looks like this now:

char * findstring(char *theString)
{
        fgets(theString, 81, stdin);
        printf( "The string is %s\n", theString);
        return theString;
}

But still, every time I call the function, it still stomps over the fgets() statement and doesn't let me enter the string. This function is actually called from a switch statement that is used as a part of a menu system, like this:

// Declaration
 char *myString = "not defined";

start:
        system("clear");
        // Simple Menu
        printf("\t\t- String Finder -\n");
        ... << choices and stuff >> ...
        printf("\tCurrent Search String: %s\n", myString);

the 'goto start' statement in the case statement goes to the start label of the menu after the function has run like this:

 switch(choice)
        {
                case 1:
                {
                        myString = malloc(100 * sizeof(char));
                        findstring(myString);
                        goto start;
                        break;
                }
<< other cases below >>

Igor

So the printf() statement will display "Current Search String: not defined" initially, but then it will display the string that was input from within the function after the user enters the string. Maybe something about the switch statement is causing the fgets() to skip itself?

Igor
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 30

Expert Comment

by:Axter
ID: 13845887
Can you post more of your code?

Can you post the entire function?
0
 
LVL 30

Expert Comment

by:Axter
ID: 13845892
FYI: I would highly recommend against using 'goto' in your code.
0
 

Author Comment

by:igor92128
ID: 13846087
Ok, here it is. I've been stuck on this string problem for days. The program is supposed to find any string in a text file and return the number of times it appears. If I had to accept only single word strings then this program would be much easier to implement because I could just use the scanf() statement but it has problems with whitespaces and all known solutions on the web including scanf("%[^\n]", theString) did not work.  I have not completed it and it still needs brushing up towards the end. Please feel free to criticize/analyze my code ... it will help me. As for the goto's, I could not find a way around them because it seemed that they were the easiest to implement. Also, the inc variable at the end is just supposed to increment whenever there is a match and then output the number of matches.
I used gcc to compile this.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#define LINE 80

// prototypes
int UI();
char * findstring(char *theString);
int fileverify(char *fileName);
int formatfile(char *fileName);
int parsefile(char *theString, char *fileName);

/*      Purpose: This function sets the pointers that are used in the program to
 *      NULL. It calls the UI function after this, passing the pointers to it.
 */

int main()
{
      UI();
}

/*      Purpose: This is the UI Menu function. It is instantiated by using two
 *      pointers. The pointers will then be passed to other functions that will
 *      be used to set them at a later time.
 */

int UI()
{
      // Initial Decalarations
        int choice;
      char *myString = "not defined";
      char *fileName = "not defined";

      start:
      system("clear");

      // Simple Menu
      printf("\t\t- String Finder -\n");
      printf("\t\t--- Main Menu ---\n\n");
      printf("\t  1) Define a search string\n");
      printf("\t  2) Define a file to parse\n");
      printf("\t  3) Run String Finder\n");
      printf("\t  4) Exit String Finder\n");
      printf("\n\n\n\n");
      printf("\tCurrent Declarations (all must be set to run the String Finder)\n\n");
      printf("\tCurrent Search String: %s\n", myString);
      printf("\tCurrent Search File: %s\n", fileName);
      printf("\n\n>>> ");
      scanf("%d", &choice);
      
      switch(choice)
      {
            case 1:
            {
                  myString = malloc(100 * sizeof(char));
                  findstring(myString);
                  goto start;
                  break;
            }
            case 2:
            {
                  fileName = malloc(100 * sizeof(char));
                  fileName = (char*) fileverify ( (char*) fileName);
                  goto start;
                  break;
            }
            case 3:
            {
                  if(myString == "not defined" || fileName == "not defined")
                  {
                        printf("\tCannot run Parser until values are set\n");
                        printf("\tPress any key to continue...\n");
                        getchar();
                        getchar();
                        goto start;
                  } else {
                              parsefile(myString, fileName);
                  }
            }
            case 4:
            {
                  printf("User has exited the program.\n");
                  exit(0);
            }
            default:
            {
                  printf("Invalid Option. Exiting Program...\n");
                  exit(1);
            }
      }
      return 0;
}

char * findstring(char *theString)
{
      fgets(theString, 81, stdin);
        printf( "The string is %s\n", theString);
      return theString;
}

int fileverify(char *fileName)
{
      FILE *fptest;
      char x;
      
      printf("\n\nPlease enter the file to use: ");
      scanf("%s", fileName);

      fptest = fopen(fileName, "r");
            
      if(fptest == NULL)
      {
            printf("\n\tSelected File Does not Exist! Please check your typing.\n");
            printf("\tPress any key to continue...\n");
            getchar();
            getchar();
            
            fileName = "not defined";
      } else fclose(fptest);

      return fileName;

}

int parsefile(char *theString, char *theFile)
{
      formatfile(theFile);

      FILE *fp;
      char *mode = "r";
      char input;
      char line[150];
      char *delimiters = " \t\n";
      char *token;
      
      int inc = 0;

      int x = 0;

      fp = fopen(theFile, mode);

      while(!feof(fp))
      {
            fgets(line, 150, fp);
            
            if(!feof(fp))
            {
                  token = strtok(line, delimiters);
                  while (token != NULL)
                  {
                        if( strcmp(token, theString) == 0)
                        inc++;
                        token = strtok(NULL, delimiters);
                  }
            }
      }

      fclose(fp);      

      printf("\n\nCurrent String: %s", theString);
      printf("\nCurrent File: %s", theFile);
      printf("\nINC: %d\n", inc);
}

int formatfile(char *file)
{
      FILE *copyFile;      
      FILE *sourceFile;

      int ch;
      char* dummyString;
      dummyString = malloc(sizeof(char) * 100);

      strcpy(dummyString, file);
      strcat(dummyString, "_");
      
      printf("THEFILE: %s", dummyString);

      copyFile = fopen(dummyString, "w+t");
      sourceFile = fopen(file, "r");

      while(!feof(sourceFile))
      {
            ch = fgetc(sourceFile);
      
            if(!isalpha(ch))
            {      
                  ch = ' ';
                  fputc(ch, copyFile);
            } else fputc(ch, copyFile);
      }

      fclose(copyFile);
      fclose(sourceFile);

      return dummyString;
}

Thanks,
Igor

0
 
LVL 30

Accepted Solution

by:
Axter earned 2000 total points
ID: 13846185
There are a lot of problems with the return types in above code.
Try changing the return types to the following in both the function forward declaration and the function implementation:

char * findstring(char *theString);
char * fileverify(char *fileName);
char * formatfile(char *fileName);
void parsefile(char *theString, char *fileName);
0
 

Author Comment

by:igor92128
ID: 13846323
Axter,

I have made those modifications and I got rid of the warnings, but the same thing happens and fgets() still skips itself.

Igor
0
 

Author Comment

by:igor92128
ID: 13846444
int main()
{
        char * test;

        fgets(test, 80, stdin);
        puts(test);
}

I've compiled this small program to test fgets() and the function seems to work ok for that program. I've noticed that after the puts() command there is an extra line break before the command prompt. In my other program, there is a line break in the menu between these commands:
printf("\tCurrent Search String: %s\n", myString);
printf("\tCurrent Search File: %s\n", fileName);

myString also becomes blank, so it looks like this:

Current Search String:

Current Search File: not defined

when it should look exactly like this:

Current Search String: whatever string
Current Search File: not defined

Igor
0
 
LVL 22

Expert Comment

by:grg99
ID: 13846546
The problem is that your first input from the user gets the number, but the scanf() only takes the number but leaves the end-of-line .  Then the gets() sees an EOL right away and returns that.   You need to eat the EOL after reading the number.

0
 
LVL 30

Expert Comment

by:Axter
ID: 13846593
I don't think you can mix scanf and fgets.

When I test the code, even if I try to capture the EOL, the code still fails.

I recommend you either stick with scanf, or with sgets, and not try to do both.
0
 

Author Comment

by:igor92128
ID: 13846775
I have changed the scanf("%d", &choice) statement to fgets(choice, 1, stdin) but the same problem as above occurs occurs.
I think the fgets(choice, 1, stdin) statement generates an EOL and passes it to fgets(theString, 81, stdin) because of the extra line break before the command prompt after my simple program finishes.

Thanks,
Igor
0
 

Author Comment

by:igor92128
ID: 13846840
I've gotten the program to work slightly by commenting out the user inputs and assigning 'choice = 1'. I can then set the string, but it won't find the matches when I parse the file.

Igor
0
 

Author Comment

by:igor92128
ID: 13847136
Sorry I just realized that the input wasn't skipping after all. If you press 1 you get exactly the same menu as before but if you then type the input string at the menu prompt, it becomes defined as the string. It was confusing. Now the problem is that the defined string won't match the identical string in the file.

Igor
0
 

Author Comment

by:igor92128
ID: 13847154
char * findstring(char *theString)
{
        char buffer[256];
        puts("Please enter the user string: ");              

        getline(buffer, 256);    
        strcpy(theString, buffer);

        printf("The string is %s\n", theString);
        return theString;
}

I'm now trying to rewrite the function completely by just using getline(), but it keeps seg. faulting.

Igor
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
Suggested Courses

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question