I'm writing a program for project in C, where I have such kind of input:
............xcx............
.........qeztodlea.........
.......ecnedivorpuzy.......
.....bqfjwxqindnrsatrs.....
....ucaamadisonoctoieax....
...ozkttqdxwltstaivcilex...
...ujknnakigzfasxninltxc...
..rabxaa...kohce...oelnyd..
..rithls...momrl...spayvh..
honolulu
oklahomacity
charleston
madison
montgomery
saltlakecity
springfield
First set of data is separated from second data set by empty line, I need on one Enter press process it.
If I copy-past this data in terminal window and press Enter and then Ctr+D ( which means end of input ) it works fine, but if to press only Enter I still need to enter data. I can't understand what to change so only on first Enter I'll finish input and proceed to my program? I know that this question sounds stupid, but in my function for reading line I use fgetc, because I need to check some letters, if to use e.g. fgets then it will stop on first nl, which function to use? Maybe I don't get something, is it possible in general?
I already have rLine function for reading line ( using fgetc ):
char * rLine( int * length, int * ha ){
char *buff = malloc( LMAX ), *old = buff;
int count = 0, maxlen = LMAX, len = maxlen, c;
while ( (c = fgetc( stdin ) ) != '\n' ){
if ( c == EOF ) { *ha = R_EOF; break; }
if ( /* some conditions for c */ ) *ha = R_FALSE;
*buff ++ = c;
count++;
if ( -- len == 0 ){
len = maxlen;
buff = (char *)realloc( old, maxlen *= 2 );
old = buff;
buff += count;
}
}
*length = count;
*buff = '\0';
return old;
}
, where ha some kind of error-message handler. Tnx
NOTE: OK, I've found out that end of input is driven same as CTRL + D combination. so actually the check if ( c == EOF ) ( or c == '\0' ) works fine for me. So actually the question can be closed by now.
Are you familiar with '\n' for a new line and '\r\n' for carriage return?
add this line and handle the new line case:
if ( c == '\n' ) { // that is a new line }
Have you seen this post:
How to read a line from the console in C?
Related
How to accept set of strings as input in C and prompt the user again to re-enter the string if it exceeds certain length. I tried as below
#include<stdio.h>
int main()
{
char arr[10][25]; //maximum 10 strings can be taken as input of max length 25
for(int i=0;i<10;i=i+1)
{
printf("Enter string %d:",i+1);
fgets(arr[i],25,stdin);
}
}
But here fgets accepts the strings greater than that length too.
If the user hits return, the second string must be taken as input. I'm new to C
How to accept string input only if it of certain length
Form a helper function to handle the various edge cases.
Use fgets(), then drop the potential '\n' (which fgets() retains) and detect long inputs.
Some untested code to give OP an idea:
#include <assert.h>
#include <stdio.h>
// Pass in the max string _size_.
// Return NULL on end-of-file without input.
// Return NULL on input error.
// Otherwise return the buffer pointer.
char* getsizedline(size_t sz, char *buf, const char *reprompt) {
assert(sz > 0 && sz <= INT_MAX && buf != NULL); // #1
while (fgets(buf, (int) sz, stdin)) {
size_t len = strlen(buf);
// Lop off potential \n
if (len > 0 && buf[--len] == '\n') { // #2
buf[len] = '\0';
return buf;
}
// OK if next ends the line
int ch = fgetc(stdin);
if (ch == '\n' || feof(stdin)) { // #3
return buf;
}
// Consume rest of line;
while (ch != '\n' && ch != EOF) { // #4
ch = fgetc(stdin);
}
if (ch == EOF) { // #5
return NULL;
}
if (reprompt) {
fputs(reprompt, stdout);
}
}
return NULL;
}
Uncommon: reading null characters remains a TBD issue.
Details for OP who is a learner.
Some tests for sane input parameters. A size of zero does not allow for any input saved as a null character terminated string. Buffers could be larger than INT_MAX, but fgets() cannot directly handle that. Code could be amended to handle 0 and huge buffers, yet leave that for another day.
fgets() does not always read a '\n'. The buffer might get full first or the last line before end-of-file might lack a '\n'. Uncommonly a null character might be read - even the first character hence the len > 0 test, rendering strlen() insufficient to determine length of characters read. Code would need significant changes to accommodate determining the size if null character input needs detailed support.
If the prior fgets() filled its buffer and the next read character attempt resulted in an end-of-file or '\n', this test is true and is OK, so return success.
If the prior fgetc() resulted in an input error, this loops exits immediately. Otherwise, we need to consume the rest of the line looking for a '\n' or EOF (which might be due to an end-of-file or input error.)
If EOF returned (due to an end-of-file or input error), no reason to continue. Return NULL.
Usage
// fgets(arr[i],25,stdin);
if (getsizedline(arr[i], sizeof(arr[i]), "Too long, try again.\n") == NULL) {
break;
}
This code uses a buffer slightly larger than the required max length. If a text line and the newline can't be read into the buffer, it reads the rest of the line and discards it. If it can, it again discards if too long (or too short).
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define INPUTS 10
#define STRMAX 25
int main(void) {
char arr[INPUTS][STRMAX+1];
char buf[STRMAX+4];
for(int i = 0; i < INPUTS; i++) {
bool success = false;
while(!success) {
printf("Enter string %d: ", i + 1);
if(fgets(buf, sizeof buf, stdin) == NULL) {
exit(1); // or sth better
}
size_t index = strcspn(buf, "\n");
if(buf[index] == '\0') { // no newline found
// keep reading until end of line
while(fgets(buf, sizeof buf, stdin) != NULL) {
if(strchr(buf, '\n') != NULL) {
break;
}
}
if(feof(stdin)) {
exit(1); // or sth better
}
continue;
}
if(index < 1 || index > STRMAX) {
continue; // string is empty or too long
}
buf[index] = '\0'; // truncate newline
strcpy(arr[i], buf); // keep this OK string
success = true;
}
}
printf("Results:\n");
for(int i = 0; i < INPUTS; i++) {
printf("%s\n", arr[i]);
}
return 0;
}
The nice thing about fgets() is that it will place the line-terminating newline character ('\n') in the input buffer. All you have to do is look for it. If it is there, you got an entire line of input. If not, there is more to read.
The strategy then, is:
fgets( s, size_of_s, stdin );
char * p = strpbrk( s, "\r\n" );
if (p)
{
// end of line was found.
*p = '\0';
return s; (the complete line of input)
}
If p is NULL, then there is more work to do. Since you wish to simply ignore lines that are too long, that is the same as throwing away input. Do so with a simple loop:
int c;
do c = getchar(); while ((c != EOF) && (c != '\n'));
Streams are typically buffered behind the scenes, either by the C Library or by the OS (or both), but even if they aren’t this is not that much of an overhead. (Use a profiler before playing “I’m an optimizing compiler”. Don’t assume bad things about the C Library.)
Once you have tossed everything you didn’t want (to EOL), make sure your input isn’t at EOF and loop to ask the user to try again.
Putting it all together
char * prompt( const char * message, char * s, size_t n )
{
while (!feof( stdin ))
{
// Ask for input
printf( "%s", message );
fflush( stdout ); // This line _may_ be necessary.
// Attempt to get an entire line of input
if (!fgets( s, n, stdin )) break;
char * p = strpbrk( s, "\r\n" );
// Success: return that line (sans newline character(s)) to the user
if (p)
{
*p = '\0';
return s;
}
// Failure: discard the remainder of the line before trying again
int c;
do c = getchar(); while ((c != EOF) && (c != '\n'));
}
// If we get this far it is because we have
// reached EOF or some other input error occurred.
return NULL;
}
Now you can use this utility function easily enough:
char user_name[20]; // artificially small
if (!prompt( "What is your name (maximum 19 characters)? ", user_name, sizeof(user_name) ))
{
complain_and_quit();
// ...because input is dead in a way you likely cannot fix.
// Feel free to check ferror(stdin) and feof(stdin) for more info.
}
This little prompt function is just an example of the kinds of helper utility functions you can write. You can do things like have an additional prompt for when the user does not obey you:
What is your name? John Jacob Jingleheimer Schmidt
Alas, I am limited to 19 characters. Please try again:
What is your name? John Schmidt
Hello John Schmidt.
I am trying to do the exercise about the line folding in the K&R C-book, but I can't go much forward.
In particular, I do not knwo how to handle blank spaces inside the line i have to cut. The exercise is the following:
"Write a program to ''fold'' long input lines into two or more shorter lines after the last non-blank character that occurs before the n-th column of input. Make sure your program does something intelligent with very long lines, and if there are no blanks or tabs before the specified column."
The code i have implemented is the following:
#include <stdio.h>
#define CUT 6
int main()
{
int c, i = 0;
while ((c = getchar()) != EOF) {
if (i == CUT) {
printf(",");
putchar(c);
i = 1;
} else {
putchar(c);
i++;
}
if (c == '\n')
i = 0;
}
}
The code check the character in input while using a counter to check once it arrives to the line it needs to cut. For instance, for the line LoremIpsumissimplydummytex it will give LoremI,psumis,simply,dummyt,ext.
The condition if (c=='\n'{ i=0;} at the end of the main is used to reinitialize the counter i, used for the CUT, at every newline.
The problem is with the blank space handling: for instance i think that for the line
Lorem Ipsum (with many blank spaces), the progam should be implemented in order to print Lorem,Ipsum. But I do not understand how to write the necessary code to implement this solution.
Sorry for the length of the post and thanks in advance.
EDIT:______________________________________________________
I added some conditions to the code in order to handle the multiple blank spaces. Wanted to ask if this could be considered the right solution:
#include <stdio.h>
#define CUT 6
int main()
{
int c,i=0;
while ((c=getchar()) !=EOF){
if (i==CUT){
if (c!=' '){
putchar(c);
} else {
printf("\n");
i=1;}
} else{
putchar(c);
i++;
}
}
}
With this code, once reached the treshold CUT, if a normal character [non blank] is encounterd it is simply added to the new line to print, otherwise "\n" is printed and the counter is re-initialized to 1.
If you to split long lines into several lines, as stated in the task description, then you must print '\n' instead of ',' when encountering the cut treshold.
You should not print the character on the output stream until you know whether it should be printed on the current line or the next line. Therefore, you must store all characters until you know which line it must be printed on.
You may want to use the function isblank to determine whether a character is a space or a tab character.
In accordance with the community guidelines on homework questions, I will not provide a full solution to the problem at this time. However, if required, I will provide further hints.
UPDATE 1:
The code in your most recend edit is not correct. According to the task description, you are supposed to split the line at the last blank before the treshold, not at the first blank after the threshold.
Most of the time when you encounter a new character, you cannot know whether it belongs in the current line or in a new line. Therefore, as already stated in my answer, you must remember all characters until you know which line they belong on. You should not print a character before you know whether it belongs on the current line or the next line.
You may find it easier to solve this problem if you use fgets instead of getchar. However, the problem can also be solved with getchar.
UPDATE 2:
Since you appear to be struggling with the problem for several days, I am now providing my solutions to the problem:
Here is my solution which uses getchar:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <assert.h>
#define CUT 10
int main( void )
{
//this memory buffer will hold the remembered
//line contents
char line[CUT+1];
//current index
int i = 0;
//whether a blank character has been encountered in
//the current line
bool found_blank = false;
//index of the last encountered blank character
int blank_index;
//this will store the current character
int c;
//this loop will read one character per loop iteration
while ( (c=getchar()) != EOF )
{
//if we encounter the end of the line, flush the
//buffer and start a new line
if ( c == '\n' )
{
line[i] = '\0';
puts( line );
i = 0;
found_blank = false;
continue;
}
//check if new character is blank and, if it is, then
//remember the index
if ( isblank(c) )
{
blank_index = i;
found_blank = true;
}
//write new character into array
line[i] = c;
if ( i == CUT - 1 )
{
if ( !found_blank )
{
//flush buffer
line[CUT] = '\0';
puts( line );
//reset line
i = 0;
found_blank = false;
continue;
}
else // found_blank == true
{
//remember character that is going to be overwritten
char temp = line[blank_index+1];
//output everything up to and including the last blank
line[blank_index+1] = '\0';
puts( line );
//move unwritten characters to start of next line
i = CUT - 1 - blank_index;
line[0] = temp;
memmove( line + 1, line+blank_index+2, i );
found_blank = false;
continue;
}
}
i++;
}
//check stream for error
if ( ferror(stdin) )
{
fprintf( stderr, "error reading input!\n" );
exit( EXIT_FAILURE );
}
//if we reach this, then we must have encountered
//end-of-file
assert( feof( stdin ) );
//flush buffer
line[i] = '\0';
puts( line );
}
Here is my solution which uses fgets:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <assert.h>
#define CUT 10
int main( void )
{
char line[CUT+2];
size_t leftovers = 0;
//in every iteration of the loop, we write one line of output
for (;;)
{
size_t blank_index;
bool found_blank = false;
if ( fgets( line + leftovers, sizeof line - leftovers, stdin ) == NULL )
{
//print all leftovers
line[leftovers] = '\0';
printf( "%s\n", line );
break;
}
size_t len = strlen( line );
//this check is probably not necessary
assert( len != 0 );
if ( line[len-1] == '\n' )
{
//we read a complete line, so print it
printf( "%s", line );
leftovers = 0;
continue;
}
//if we reach this, then input line was not read in
//completely, or we are dealing with the last line before
//end-of-file or input failure
//find last blank
for ( size_t i = 0; line[i] != '\0'; i++ )
{
if ( isblank( (unsigned char)line[i] ) )
{
found_blank = true;
blank_index = i;
}
}
if ( !found_blank )
{
if ( len <= CUT )
{
if ( ferror(stdin) )
{
fprintf( stderr, "error reading input!\n" );
exit( EXIT_FAILURE );
}
//we should only reach this if end-of-file was
//encountered in the middle of a line
assert( feof(stdin) );
printf( "%s\n", line );
break;
}
//remember last character
char temp = line[len-1];
line[len-1] = '\n';
printf( "%s", line );
line[0] = temp;
leftovers = 1;
}
else
{
//remember character after last blank
char temp = line[blank_index+1];
//replace character after last blank with terminator
line[blank_index+1] = '\0';
//print line up to and including last blank
printf( "%s\n", line );
if ( temp != '\0' )
{
//move unprinted characters to start of next line
line[0] = temp;
leftovers = len - blank_index - 1;
memmove( line + 1, line + blank_index + 2, leftovers - 1);
}
else
{
leftovers = 0;
}
}
}
}
It appears that my initial advice of using fgets instead of getchar was not very good, as the fgets solution turned out to be slightly more complicated than the getchar solution.
Here is some sample input and output of both programs (both programs behave the same way):
Sample input:
This is a line with several words.
Thisisalinewithonelongword.
Sample output:
This is a
line with
several
words.
Thisisalin
ewithonelo
ngword.
My assignment is to redirect a text file and do all sorts of operations on it , everything is working except I have a little problem :
so the main function that reads input is getline1():
char* getline1(){
char *LinePtr = (char*)malloc(sizeof(char*)*LINE);
int i = 0;
for ( ; (*(LinePtr+i) = getc(stdin)) != '\n' ; i++){}
*(LinePtr+i) = '\0';
return LinePtr;
}
it returns a pointer to char array of a single line,
so we know that a new line saparates with '\n' char,
previous problem I had is when I wrote the getline1() function like this :
for (int i = 0 ; Line[i] != '\n' ; i++){
Line[i] = getc(stdin);
}
as it logically it may be authentic the getc() is a streaming function and I saw online answers that this will not work didn't quite understand why.
anyway the big issue is that I need to know how many lines there are in the text so I can stop reading values , or to know from getline1() function that there is no next line left and Im done.
things we need to take for account :
1.only <stdio.h> <stdlib.h> need to be used
2.Im using Linux Ubuntu and gcc compiler
3.the ridirection goes like ./Run<input.txt
also I understand that stdin is a file pointer , didn't found a way that this can help me.
Thank you ,
Denis
You should check for the EOF signal in addition to the newline character, you should also check for that your index-1 is always smaller than LINE to avoid overflow and also save space for the NULL terminator.
#define LINE 100
char *my_getline(void)
{
size_t i = 0;
char *str = NULL;
int c = 0;
if ((str = malloc(LINE)) == NULL)
{
fprintf(stderr,"Malloc failed");
exit(EXIT_FAILURE);
}
while (i+1 < LINE && (c = getchar()) != EOF && c != '\n') /* Saving space for \0 */
{
str[i++] = c;
}
str[i] = '\0';
return str;
}
Thanks for everybody , I just made another function to count line this was the only lazy option available :)
static void linecounter(){
FILE *fileptr;
int count = 0;
char chr;
fileptr = fopen("input.txt", "r");
chr = getc(fileptr);
while (chr != EOF){
if (chr == '\n'){count = count + 1;}
chr = getc(fileptr);}
fclose(fileptr);
count_lines = count;}
I have a problem, they gave me a task. They told us that we must use a pointer to put the value from the keyboard to array and then print that array.
I try to create that, but I don't know why this is wrong. I define my array then I get value and put that value into an array.
#include <stdio.h>
#include <stdlib.h>
#define N 10000 // Maximum array size
int main ()
{
char keyboardArray[N];
char *r;
r = keyboardArray;
while( (*r++ = getchar()) != EOF );
printf("You write %s", r);
return 0;
}
You have several problems:
At the end of the loop, r points to the end of the string, not the beginning. So printing r won't print the string that was entered. You should print the keyboardArray rather than r.
You're never adding a null terminator to the string, so you can't use the %s format operator.
getchar() returns int, not char -- this is needed to be able to distinguish EOF from ordinary characters. So you need to read into a different variable before storing into the array.
int main ()
{
char keyboardArray[N];
char *r;
int c;
r = keyboardArray;
while( (c = getchar()) != EOF ) {
*r++ = c;
}
*r = '\0'; // Add null terminator
printf("You write %s\n", keyboardArray);
}
Note that this will read until EOF, so the user will have to type a special character like Control-d (on Unix) or Control-z (on Windows) to end the input. You might want to check for newline as well, so they can enter a single line:
while ((c = getchar()) != EOF && c != '\n') {
I think that in any case you need an intermediate variable that will accept a read character.
Also you need to append the entered sequence of characters with the terminating zero.
For example
#include <stdio.h>
#define N 10000 // Maximum array size
int main( void )
{
char keyboardArray[N];
char *r = keyboardArray;
for ( int c;
r + 1 < keyboardArray + N && ( c = getchar() ) != EOF && c != '\n';
++r )
{
*r = c;
}
*r = '\0';
printf( "You write %s\n", keyboardArray );
}
I want to put the text into my string and process it in an infinite loop, but I want to break the loop if the first character of the input is an ESCAPE key, but getchar returns 10 when I press ESCAPE followed by ENTER.
printf correctly prints the inputted character, but if I press ESCAPE nothing happens. I also don't want to use _getch() nor getche() which actually would solve my problem, but they also remove c from the buffer and doesn't display it properly.
What can I do?
int c;
while( 1 )
{
c = getchar();
printf( "c = %d\n", c ); // just for debug
if( c == 27 ) break;
else ungetc( c, stdin );
fgets( StrIn, BUF_SIZE - 1, stdin );
// REST OF CODE ********
}
EDIT I've just found Microsoft function
if( GetAsyncKeyState( VK_ESCAPE ) )
break;
that works fine for me. Thanks for reading and for your time, my problem is solved.
Pressing the ESCAPE key on a keyboard does not usually send an ESCAPE character to a console, the application or OS will often process the character and not pass it on. I'd use a different character to represent the fact that you want to break, for example a '~'.
When you say it doesn't display right if you remove c from the buffer, perhaps you can just add the first character the buffer manually.
Add a macro for the break character
#define BREAK_CHAR '~'
The code spinet could then look like this:
int c;
while(1)
{
c = getchar();
/* check if we should break */
if(c == BREAK_CHAR)
break;
/* assign the first character that was already read in */
StrIn[0] = c;
/* get the rest of the string */
fgets( StrIn + 1, BUF_SIZE - 2, stdin );
}
if you use windows - use windows specific functions as well. In my function ESC cancels the input.
char *wingetsn(char *str, size_t maxlen)
{
size_t len = 0;
int ch;
int exit = 0;
while (len < maxlen - 1 && !exit)
{
while(!_kbhit());
switch((ch = _getch()))
{
case 27:
str[0] = 0;
exit = 1;
break;
case '\r':
exit = 1;
break;
case '\n':
break;
default:
printf("%c", ch);
str[len++] = ch;
break;
}
}
str[len++] = 0;
return str;
}