Как читать из stdin с помощью fgets ()?

Я написал следующий код для чтения строки из windows терминала, проблема в том, что код застревает в бесконечном цикле. Строка / предложение имеет неопределенную длину, поэтому я планирую прочитать ее по частям в буфер, а затем объединить ее в другую строку, которая может быть расширена через realloc соответственно. Пожалуйста, кто-нибудь может заметить мою ошибку или предложить лучший способ добиться этого?

 #include  #include  #define BUFFERSIZE 10 int main (int argc, char *argv[]) { char buffer[BUFFERSIZE]; printf("Enter a message: \n"); while(fgets(buffer, BUFFERSIZE , stdin) != NULL) { printf("%s\n", buffer); } return 0; } 

здесь решение конкатенации:

 #include  #include  #include  #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; } 

У вас неправильное представление о том, что возвращает fgets. Взгляните на это: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

Он возвращает значение null, когда находит символ EOF. Попробуйте запустить программу выше и нажав CTRL + D (или любую комбинацию – ваш EOF-символ), и цикл будет успешно завершен.

Как вы хотите определить конец ввода? Новая линия? Точка (вы сказали предложение xD)?

Предполагая, что вы хотите прочитать только одну строку, используйте LINE_MAX , который определен в :

 #include  ... char line[LINE_MAX]; ... if (fgets(line, LINE_MAX, stdin) != NULL) { ... } ... 

Выход из цикла, если строка пуста (Улучшение кода).

 #include  #include  // 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; } 

Выход при нажатии Enter.

 #include  #include  #include  #include  #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; } в #include  #include  #include  #include  #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; } 

Конкатенация и динамическое распределение (связанный список) с одной строкой.

 /* Autor : Tiago Portela Email : [email protected] Sobre : Compilado com TDM-GCC 5.10 64-bit e LCC-Win32 64-bit; Obs : Apenas tentando aprender algoritimos, sozinho, por hobby. */ #include  #include  #include  #include  #include  #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; } в /* Autor : Tiago Portela Email : [email protected] Sobre : Compilado com TDM-GCC 5.10 64-bit e LCC-Win32 64-bit; Obs : Apenas tentando aprender algoritimos, sozinho, por hobby. */ #include  #include  #include  #include  #include  #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; } 

Если вы хотите объединить вход, затем замените printf("%s\n", buffer); с strcat(big_buffer, buffer); , Также создайте и инициализируйте большой буфер в начале: char *big_buffer = new char[BIG_BUFFERSIZE]; big_buffer[0] = '\0'; , Вы также должны предотвратить переполнение буфера путем проверки текущей длины буфера плюс длина нового буфера не превышает предел: if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE) . Измененная программа будет выглядеть так:

 #include  #include  #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; } 
  • Сравнить два дерева каталогов
  • Чтение Eclipse stdin (System.in) из файла
  • Почему я получаю «Необработанный тип исключения IOException»?
  • Предоставить пароль SU в сценарии bash, в скрипте?
  • Как отправить ввод на консоль, как если бы пользователь печатал?
  • Как читать строку с консоли в C?
  • Обманите приложение, думая, что его выступление - это терминал, а не труба
  • Я не могу сбросить stdin
  • Как читать из файла или stdin в Bash?
  • Почему мы не можем читать один символ за раз из System.in?
  • Очистить stdin перед чтением
  • Давайте будем гением компьютера.