How to read from stdin with fgets()?

后端 未结 5 1131
名媛妹妹
名媛妹妹 2020-11-29 04:44

I\'ve written the following code to read a line from a terminal window, the problem is the code gets stuck in an infinite loop. The line/sentence is of undefined length, th

相关标签:
5条回答
  • 2020-11-29 04:54

    Exits the loop if the line is empty(Improving code).

    #include <stdio.h>
    #include <string.h>
    
    // The value BUFFERSIZE can be changed to customer's taste . Changes the
    // size of the base array (string buffer )    
    #define BUFFERSIZE 10
    
    int main(void)
    {
        char buffer[BUFFERSIZE];
        char cChar;
        printf("Enter a message: \n");
        while(*(fgets(buffer, BUFFERSIZE, stdin)) != '\n')
        {
            // For concatenation
            // fgets reads and adds '\n' in the string , replace '\n' by '\0' to 
            // remove the line break .
    /*      if(buffer[strlen(buffer) - 1] == '\n')
                buffer[strlen(buffer) - 1] = '\0'; */
            printf("%s", buffer);
            // Corrects the error mentioned by Alain BECKER.       
            // Checks if the string buffer is full to check and prevent the 
            // next character read by fgets is '\n' .
            if(strlen(buffer) == (BUFFERSIZE - 1) && (buffer[strlen(buffer) - 1] != '\n'))
            {
                // Prevents end of the line '\n' to be read in the first 
                // character (Loop Exit) in the next loop. Reads
                // the next char in stdin buffer , if '\n' is read and removed, if
                // different is returned to stdin 
                cChar = fgetc(stdin);
                if(cChar != '\n')
                    ungetc(cChar, stdin);
                // To print correctly if '\n' is removed.
                else
                    printf("\n");
            }
        }
        return 0;
    }
    

    Exit when Enter is pressed.

    #include <stdio.h>
    #include <stdbool.h>
    #include <string.h>
    #include <assert.h>
    
    #define BUFFERSIZE 16
    
    int main(void)
    {
        char buffer[BUFFERSIZE];
        printf("Enter a message: \n");
        while(true)
        {
            assert(fgets(buffer, BUFFERSIZE, stdin) != NULL);
            // Verifies that the previous character to the last character in the
            // buffer array is '\n' (The last character is '\0') if the
            // character is '\n' leaves loop.
            if(buffer[strlen(buffer) - 1] == '\n')
            {
                // fgets reads and adds '\n' in the string, replace '\n' by '\0' to 
                // remove the line break .
                buffer[strlen(buffer) - 1] = '\0';
                printf("%s", buffer);
                break;
            }
            printf("%s", buffer);   
        }
        return 0;
    }
    

    Concatenation and dinamic allocation(linked list) to a single string.

    /* Autor : Tiago Portela
       Email : sapitando@gmail.com
       Sobre : Compilado com TDM-GCC 5.10 64-bit e LCC-Win32 64-bit;
       Obs : Apenas tentando aprender algoritimos, sozinho, por hobby. */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    #include <assert.h>
    
    #define BUFFERSIZE 8
    
    typedef struct _Node {
        char *lpBuffer;
        struct _Node *LpProxNode;
    } Node_t, *LpNode_t;
    
    int main(void)
    {
        char acBuffer[BUFFERSIZE] = {0};
        LpNode_t lpNode = (LpNode_t)malloc(sizeof(Node_t));
        assert(lpNode!=NULL);
        LpNode_t lpHeadNode = lpNode;
        char* lpBuffer = (char*)calloc(1,sizeof(char));
        assert(lpBuffer!=NULL);
        char cChar;
    
    
        printf("Enter a message: \n");
        // Exit when Enter is pressed
    /*  while(true)
        {
            assert(fgets(acBuffer, BUFFERSIZE, stdin)!=NULL);
            lpNode->lpBuffer = (char*)malloc((strlen(acBuffer) + 1) * sizeof(char));
            assert(lpNode->lpBuffer!=NULL);
            strcpy(lpNode->lpBuffer, acBuffer);
            if(lpNode->lpBuffer[strlen(acBuffer) - 1] == '\n')
            {
                lpNode->lpBuffer[strlen(acBuffer) - 1] = '\0';
                lpNode->LpProxNode = NULL;
                break;
            }
            lpNode->LpProxNode = (LpNode_t)malloc(sizeof(Node_t));
            lpNode = lpNode->LpProxNode;
            assert(lpNode!=NULL);
        }*/
    
        // Exits the loop if the line is empty(Improving code).
        while(true)
        {
            assert(fgets(acBuffer, BUFFERSIZE, stdin)!=NULL);
            lpNode->lpBuffer = (char*)malloc((strlen(acBuffer) + 1) * sizeof(char));
            assert(lpNode->lpBuffer!=NULL);
            strcpy(lpNode->lpBuffer, acBuffer);
            if(acBuffer[strlen(acBuffer) - 1] == '\n')
                lpNode->lpBuffer[strlen(acBuffer) - 1] = '\0';
            if(strlen(acBuffer) == (BUFFERSIZE - 1) && (acBuffer[strlen(acBuffer) - 1] != '\n'))
            {
                cChar = fgetc(stdin);
                if(cChar != '\n')
                    ungetc(cChar, stdin);
            }
            if(acBuffer[0] == '\n')
            {
                lpNode->LpProxNode = NULL;
                break;
            }
            lpNode->LpProxNode = (LpNode_t)malloc(sizeof(Node_t));
            lpNode = lpNode->LpProxNode;
            assert(lpNode!=NULL);
        }
    
    
        printf("\nPseudo String :\n");
        lpNode = lpHeadNode;
        while(lpNode != NULL)
        {
            printf("%s", lpNode->lpBuffer);
            lpNode = lpNode->LpProxNode;
        }
    
    
        printf("\n\nMemory blocks:\n");
        lpNode = lpHeadNode;
        while(lpNode != NULL)
        {
            printf("Block \"%7s\" size = %lu\n", lpNode->lpBuffer, (long unsigned)(strlen(lpNode->lpBuffer) + 1));
            lpNode = lpNode->LpProxNode;
        }
    
    
        printf("\nConcatenated string:\n");
        lpNode = lpHeadNode;
        while(lpNode != NULL)
        {
            lpBuffer = (char*)realloc(lpBuffer, (strlen(lpBuffer) + strlen(lpNode->lpBuffer)) + 1);
            strcat(lpBuffer, lpNode->lpBuffer);
            lpNode = lpNode->LpProxNode;
        }
        printf("%s", lpBuffer);
        printf("\n\n");
    
        // Deallocate memory
        lpNode = lpHeadNode;
        while(lpNode != NULL)
        {
            lpHeadNode = lpNode->LpProxNode;
            free(lpNode->lpBuffer);
            free(lpNode);
            lpNode = lpHeadNode;
        }
        lpBuffer = (char*)realloc(lpBuffer, 0);
        lpBuffer = NULL;
        if((lpNode == NULL) && (lpBuffer == NULL))
        {
    
            printf("Deallocate memory = %s", (char*)lpNode);
        }
        printf("\n\n");
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-29 04:56

    here a concatenation solution:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define BUFFERSIZE 10
    
    int main() {
      char *text = calloc(1,1), buffer[BUFFERSIZE];
      printf("Enter a message: \n");
      while( fgets(buffer, BUFFERSIZE , stdin) ) /* break with ^D or ^Z */
      {
        text = realloc( text, strlen(text)+1+strlen(buffer) );
        if( !text ) ... /* error handling */
        strcat( text, buffer ); /* note a '\n' is appended here everytime */
        printf("%s\n", buffer);
      }
      printf("\ntext:\n%s",text);
      return 0;
    }
    
    0 讨论(0)
  • 2020-11-29 05:12

    You have a wrong idea of what fgets returns. Take a look at this: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

    It returns null when it finds an EOF character. Try running the program above and pressing CTRL+D (or whatever combination is your EOF character), and the loop will exit succesfully.

    How do you want to detect the end of the input? Newline? Dot (you said sentence xD)?

    0 讨论(0)
  • 2020-11-29 05:14

    If you want to concatenate the input, then replace printf("%s\n", buffer); with strcat(big_buffer, buffer);. Also create and initialize the big buffer at the beginning: char *big_buffer = new char[BIG_BUFFERSIZE]; big_buffer[0] = '\0';. You should also prevent a buffer overrun by verifying the current buffer length plus the new buffer length does not exceed the limit: if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE). The modified program would look like this:

    #include <stdio.h>
    #include <string.h>
    
    #define BUFFERSIZE 10
    #define BIG_BUFFERSIZE 1024
    
    int main (int argc, char *argv[])
    {
        char buffer[BUFFERSIZE];
        char *big_buffer = new char[BIG_BUFFERSIZE];
        big_buffer[0] = '\0';
        printf("Enter a message: \n");
        while(fgets(buffer, BUFFERSIZE , stdin) != NULL)
        {
            if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE)
            {
                strcat(big_buffer, buffer);
            }
        }
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-29 05:16

    Assuming that you only want to read a single line, then use LINE_MAX, which is defined in <limits.h>:

    #include <stdio.h>
    #include <limits.h>
    ...
    char line[LINE_MAX];
    ...
    if (fgets(line, LINE_MAX, stdin) != NULL) {
    ...
    }
    ...
    
    0 讨论(0)
提交回复
热议问题