this is my code below. What it does is not the issue. The issue is that once it is run, I put in my input and if its too small it will ask for input again on the second line which appears to have no affect the flow of my program. If I fill the buffer (which I'm assuming 100 or more) then I am not asked for a second prompt.
#include <stdio.h>
#include <string.h>
int main()
{
int ch;
char x[3];
char *word, string1[100];
x[0]='y';
while(x[0]=='y'||x[0]=='Y')
{
fgets(string1, 100, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
printf("The string is: %s", string1);
word = strtok(string1, " ");
while(word != NULL)
{
printf("%s\n", word);
word = strtok(NULL, " ");
}
printf("Run Again?(y/n):");
fgets(x, 2, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
}
return 0;
}
EDIT:
I have replaced,
fgets(string1, 100, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
With,
fgets(string1, 100, stdin);
if (string1[98] != '\n' && string1[99] == '\0')
{
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
}
From the man page:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops
after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the
last character in the buffer.
fgets will place all input, up to 99 chars, into string1. If you input 98 characters and hit enter (creating a 99th \n), then all 100 will be used as the last one is a \0 terminator.
Then you fall into that small while loop which does nothing but consume another line of input. If you input less than the max for your string, then input is halted while that loop waits for a \n.
If you input >98 characters, then the first 99 are saved to your input string, and the remainder along with that final \n are immediately run through that while loop, causing it to exit quickly enough that it may seem to be skipped.
I hope that helps. Unfortunately I can't comment and ask for clarification, so I'll say here that it's a little difficult to tell what exactly you want fixed or made clear.
The answer to your question is right here: man fgets
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
To know if fgets used the whole buffer, write some non-NUL byte into the end of the buffer. If, after calling fgets, that byte has been overwritten with a NUL, it means the buffer is full. If the character directly before it is not a newline, then there's more input still to be read.
buffer[size - 1] = 'a'; // any character that's not '\0'
fgets(buffer, size, stdin);
if (buffer[size - 1] == '\0' && buffer[size - 2] == '\n') {
// handle extra input
}
Alternatively, you could just read bytes one at a time using getchar.
I think you need this:
Note: x must be int if you want to compare it against EOF
int main()
{
int x;
char *word, string1[100];
do
{
fgets(string1, 100, stdin);
printf("The string is: %s", string1);
word = strtok(string1, " ");
while(word != NULL)
{
printf("%s\n", word);
word = strtok(NULL, " ");
}
printf("Run Again?(y/n):");
x = fgetc(stdin);
fgetc(stdin); // absorb `\n`
}
while( (x=='y'||x=='Y') && x != EOF) ;
return 0;
}
Related
I've been working on a problem. I need to scan for a \n to end the cycle and delete it to not remain in a variable with other text. So far I have this:
do {
scanf("%[^\n]", userinput); //loads stdin to char[] variable
end = userinput[0]; //loads one char to char variable
scanf("%*c"); //should remove \n
strcpy(inputstorage[i], userinput); //copies userinput into 2d array of
i++; //string with \n removed
} while (end != '\n'); //should end cycle when I hit enter
What this does is, when I press enter it keeps the last char in the variable end.
For example I enter: 'Hello'
In userinput is: 'Hello'
In end is 'H'
When I hit enter afterwards the end variable should contain \n but it contains 'H' for some reason. I appreciate all the help you can provide
end = userinput[0]; saves the first character of input. scanf("%[^\n]", userinput); does not put a '\n' in userinput[], so testing if end is an end-of-line is not useful.
Use fgets() to read a line
char userinput[100];
if (fgets(userinput, sizeof userinput, stdin)) {
Then lop off the potential '\n' via various means.
size_t len = strlen(userinput);
if (len > 0 && userinput[len-1] == '\n') userinput[--len] = '\0';
If code is obliged to use scanf(),
int count;
do {
char userinput[100];
// Use a width limiter and record its conversion count : 1, 0, EOF
// scanf("%[^\n]", userinput);
count = scanf("%99[^\n]", userinput);
// Consume the next character only if it is `'\n'`.
// scanf("%*c");
scanf("%*1[\n]");
// Only save data if a non-empty line was read
if (count == 1) {
strcpy(inputstorage[i], userinput);
i++;
}
} while (count == 1);
// Input that begins with '\n' will have count == 0
A re-formed loop could use
char userinput[100];
int count;
while ((count = scanf("%99[^\n]", userinput)) == 1) {
scanf("%*1[\n]");
strcpy(inputstorage[i++], userinput);
}
scanf("%*1[\n]");
Note OP's code use '/n' in while (end != '/n');. This is not the end of line character '\n' but a rarely used multi-character constant. Certainly not what OP wanted. It also implied that warnings were not fully enabled. Save time enable all warnings. #aschepler.
You can use use scanf, getline or fgets to get the line and then strcspn to remove the "\n".
eg. userInfo[strcspn(userInfo, "\n")] = 0;
I am facing some problems while understanding the following code.
It is a program to read Strings from keyboard if the length of the String is lesser than the specified size (i.e 'n' here).
If the length of a string is larger than the specified size, the remaining characters on the line will be discarded.
More specifically, I want to know what is happening inside the buffer and how getchar() is reading the data and not storing it in the buffer.
char * s_gets(char * st, int n)
{
char * ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if (ret_val) // i.e., ret_val != NULL
{
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
st[i] = '\0';
else // must have words[i] == '\0'
while (getchar() != '\n')
continue;
}
return ret_val;
}
The code is slightly flawed, but does more or less the job outlined. It uses fgets() to do a lot of the work. That reads up to n - 1 characters from standard input. When it returns, there are a few possibilities:
(EOF) Nothing was available to be read. Nothing has been put in the buffer, but fgets() returned NULL.
(Normal) A line has been read and fitted into the buffer st. The buffer includes the newline.
(Overlong) Part of a line has been read, but the input did not find a newline.
(EOF without newline) Some data was read, but there wasn't a newline before EOF was detected.
Case 1 is simplest: the code returns NULL. Case 2 is handled by scanning the string that's read to find the newline. If the newline is found, it is overwritten with a null byte. Case 3 is handled at the same time; if the value found isn't a newline, it must be the null byte. The code drops into a loop that reads more characters until a newline is read. Case 4 is similar to case 3 in effect, but the code in the loop mishandles this — it doesn't detect and handle EOF, so the code would fall into an indefinite loop. That's a bug that needs to be fixed.
The getchar() loop doesn't assign anything to the buffer st — it makes no changes to st. That continues to contain a null terminated string as read by fgets(). The getchar() loop reads and discards any characters left on the line that was read that did not fit into the buffer.
The code should be:
char *s_gets(char *st, int n)
{
assert(n > 1 && st != NULL);
char *ret_val = fgets(st, n, stdin);
if (ret_val != NULL)
{
int i = 0;
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
st[i] = '\0';
else
{
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
}
}
return ret_val;
}
The return value of NULL or the original string is the same as fgets() uses, but it isn't the most useful return value. It would be more useful, most often, if the code returned the length of the string that it read, or returned EOF if it encountered EOF (or a read error). The information is readily available — in the variable i.
I am trying to switching my use of getchar to fgets but, when using getchar, the entire code does not work.
//fgets(line, sizeof(line), stdin);
while(fgets(line, sizeof(line), stdin))
{
portNum[sizeof(line)] = (char)line;
}
while((c = getchar()) != '\n')
{
portNum[num++] = c;
}
portNum[num] = '\0';
How can I make equal for those two functions to work properly?
You usage of fgets is wrong.
fgets Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
In your case fgets will read all the characters until newline is encountered.
Also, the parameters usage is wrong.
char * fgets ( char * str, int num, FILE * stream );
str => Pointer to an array of chars where the string read is copied.
num => Maximum number of characters to be copied into str (including the
terminating null-character).
stream => Pointer to a FILE object that identifies an input stream.
stdin can be used as argument to read from the standard input.
Refer to the fgets documentation for more information.
fgets man page
OP's fgets() usage is unclear and portNum[sizeof(line)] = (char)line; is certainly in error.
Instead: how to make the below getchar() code more fgets()-like:
// assumed missing code
#define N 100
int c;
char portNum[N];
size_t num = 0;
// size and EOF detection added (which should have been there)
while(num + 1 < sizeof portnum && (c = getchar()) != '\n' && c != EOF) {
portNum[num++] = c;
}
portNum[num] = '\0';
// assumed missing code
if (c == EOF && num == 0) Handle_EndOfFile_or_InputError();
else ...
This can be replaced with fgets() code
#define N 100
char portNum[N+1]; // 1 larger for the \n
if (fgets(portNum, sizeof portNum, stdin)) {
// lop off potential trailing \n
portNum[strcspn(portNum, "\n")] = '\0';
...
} else {
Handle_EndOfFile_or_InputError();
}
Looking to read in using scanf but I want to stop reading if I encounter a ',' '\0' (newline) or EOF
I'm not really sure how to stop achieve this.
I was using
char * aBuff;
char * bBuff;
char * cBuff;
//read in the first three lines and put them into char arrays
//while (scan() != (',' || '\0' || EOF)) //was trying to put it into a while loop, wasn't sure
scanf("%s", aBuff);
scanf("%s", bBuff);
scanf(%s, cBUff);
I plan on taking the input and putting them into separate arrays. Basically take input until a , or new line and place that data into an array and continue this process until the end of file.
scanf() is not a practical method to read until encountering ',', '\0', or EOF. Use fgetc().
The biggest problem is specifying '\0' in the format of scanf(). Example: with format "%[^,\0]", scanf() only reads "%[^," as it stops at the embedded '\0'. So with an invalid format specifier --> undefined behavior.
size_t ReadX(char *dest, size_t size) {
size_t len = 0;
if (size) {
while (--size > 0) {
int ch = fgetc(stdin);
if (ch == 0 || ch == ',' || ch == EOF) break; // maybe add \n too.
*dest[len++] = ch;
}
*dest[len] = '\0';
}
return len; // or maybe return the stopping ch
}
scanf() could be use if code used the ponderous:
scanf("%[\1\2\3...all_char_codes_min_char_to_max_char_except_,_and\0]%*c", &s);
You can try using scansets
scanf() should stop on EOF, but you'd want to maybe do something like this:
scanf("%[^,\0]", &s);
If I do :
int main(){
const int LENGTH_LINE = 100;
char line[LENGTH_LINE];
int len;
FILE* fp = fopen(file.txt,"r");
fgets(line,LENGTH_LINE,fp);
len = strlen(line);
if(line[len-1] == '\n')
printf("I've a line");
//This work if the line have \n , but if the end line of the text dont have \n how can do it?
}
I need to know if I take a whole line with fgets because I got a delimiter.
According to http://en.cppreference.com/w/c/io/fgets
Reads at most count - 1 characters from the given file stream and stores them in str.
Parsing stops if end-of-file occurs or a newline character is found, in which case str will contain that newline character.
So, once fgets returns, there are 3 possibilities
LENGTH_LINE was reached
We got a newline
EOF was reached.
I'm assuming you have a line in cases 2 and 3.
In this case the detection condition is :
line[len-1] == '\n' || feof(fp)
Check for the newline character:
size_t len = 0;
// ... your code using fgets
len = strlen(line);
if ((len > 0) && (line[len - 1] == '\n'))
// your input contains the newline
After the fgets call, your line may not have a newline at the end if:
The character limit was reached before a newline was scanned - in your case this is LENGTH_LINE.
The end-of-file (EOF) was reached before a newline.
There was a read error, but in case of an error consider the contents of line unusable.
You should be looking at the return value from fgets so that you'll be able to handle the EOF: fgets returns NULL upon end-of-file or a read error. You can use feof to check for the end-of-file.
If you check feof, and know that you're at the end of your input with no fgets errors, then even without a newline character on the final line you'll know that you've read the entire line.
If for some reason you must have a newline character terminating each line, you can add it yourself:
// you've checked for EOF and know this is your final line:
len = strlen(line);
if (line[len-1] == '\n')
printf("I've a line");
else if ((len + 1) < LENGTH_LINE)
{
line[len] = '\n';
line[len + 1] = '\0';
}
else
// no room in your line buffer for an add'l character
Use like this
while(fgets(line,LENGTH_LINE,fp)!=EOF)
// your code here
Why not just use fgetc instead? That way you can just keep scanning until you get to the end of the line so you don't have to check if you have it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char line[100];
int ch, i = 0;
FILE* fp = fopen(file.txt,"r");
while(ch != '\n' || ch != '\r' || ch != EOF) //or ch != delimiter
{
ch = fgetc(fp);
line[i] = ch;
i++;
}
line[i] = '\n';
line[i+1] = 0x00;
return 0;
}
In that example I just look for a new line, return, or EOF character but you can really make it look for anything you like (e.g. your delimiter). So if your delimiter was q you would just do
while(ch != 'q')...