I am trying to solve this problem and I need your help.
I have this code...
while(a != EOF){
scanf("%f",&a);
...
}
...and I want to terminate this loop by pressing CTRL+D. It works but I need to press it two times. I tried to use this
while(getchar() != EOF){
scanf("%f",&a);
...
}
but the same result. Is there any way to end this loop by pressing CTRL+D only once?
Thank you for any response.
You can check for EOF directly in scanf:
while (scanf("%f",&a) != EOF) {
...
}
For more information, read the docs on scanf (an example of them).
You should be checking the result of the call to scanf, not just for EOF, but also to ensure that the value parsed correctly. scanf returns the number of items that were successfully scanned, in your particular case, it will return 1 if it successfully scanned one float. If the parse was unsuccessful, then you can't rely on the value of a after that.
int result;
do
{
while ((result = scanf("%f", &a)) != EOF)
if (result == 1)
{
// scan was successful, you can safely use the value of "a"
}
else
{
// scan was unsuccessful
// you can skip to the next line, produce an error, etc.
}
}
You have at least two solution:
I.
while (scanf("%f",&a) != EOF) {
...
}
II.
get a from File Descriptor
Try testing the return from scanf(): if your stream has ended it'll return EOF.
Try this, this may help for you:
while(1) {
scanf("%f",&a);
if(a==EOF)
break;
......
}
Related
I can't seem to figure out why my program doesn't work if I call scanf() from within a case statement.
Everything works fine until I call scanf(). It's a really small console based menu. It reads a string that has just been entered and goes down the menu accordingly. It all works fine until I try scanf() in an integer that it should respond to.
I first thought that returning a value will break the Switch statement... then that didn't work so I placed break statements in just in case. But it still doesn't work though. As soon as the scanf() is not commented the whole sequence is just messed up.
void main(void) {
char MenuS;
MenuS = 's';
while (MenuS != 'q') {
MenuS = Menu();
}
}
char Menu() {
unsigned char Menu;
unsigned char UserInput[9];
unsigned int Offset;
Offset = 0;
printf("\nEnt:");
gets(UserInput);
trim(UserInput);
if (UserInput[0] != 'q') {
switch (UserInput[0]) {
case 'r':
scanf("%d", &Offset);
printf("\nIn R");
return ('r');
break;
case 'w':
// printf("Is w");
printf("\nIn W");
return ('w');
break;
default:
printf("\nSomething else");
break;
}
} else {
return 'q';
}
}
I think you're having a problem, because you declared an unsigned int variable, but you used a wrong format specifier here:
scanf("%d", &Offset);
Offset is an unsigned int variable.
You have to use %u for unsigned integer instead of %d
Try this, this might solve the problem:
scanf("%u", &Offset);
Learn to enable all warnings and debug info in your compiler. With GCC compile using gcc -Wall -g
Then use the debugger (e.g. gdb) to run your program step by step.
At last, read the documentation of functions that you are using. scanf(3) is documented to return an integer number:
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
The value EOF is returned if the end of input is reached before
either the first successful conversion or a matching failure occurs.
EOF is also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set
indicate the error.
So you should code probably
if (scanf("%d", &Offset)<1) { perror("scanf failed"); exit (EXIT_FAILURE); };
BTW, your printf(3) format strings look strange: they should end (not start) with a newline \n e.g. code printf("In R\n"); or even better
printf("line %d of %s: In R\n", __LINE__, __FILE__);
or at least call explicitly fflush(NULL); after them, read
about fflush(3) and remember that stdio(3) is buffered.
At last, gets(3) is deprecated and dangerous, use fgets(3) or preferably getline(3). So at least replace gets(UserInput); with
memset (UserInput, 0, sizeof(UserInput));
if (NULL == fgets(UserInput, sizeof(UserInput), stdin))
{ perror("fgets"); exit(EXIT_FAILURE); }
BTW, your main function is incorrectly declared. It should be int main (int argc, char**argv); preferably. It should not return void but EXIT_SUCCESS i.e. 0 on success and something else on failure. See also EXIT_SUCCESS and EXIT_FAILURE and exit(3)
PS. You are missing several #include directives at the beginning of your program, at least:
#include <stdio.h>
#include <stdlib.h>
I assume your code have them but you did not show them to us.
NB: Using capital letters in variables is not conventional in C. Generally, people
reserve upper-case letters for macros. But that is a convention.
when I call ScanF from within the Switch it seems to ignore the Return AND the Break and just to Default which just prints "Not Something"..
If it "ignored the return and the break" then you would fall through to the case 'w'. But that isn't happening. Therefore it is not ignoring the return and the break (not that that is possible anyway).
Actually the program flow is working just as you wrote it. The sequence is:
scanf("%d", &Offset);
You type some numbers and press enter
return ('r');
back to main: MenuS = Menu(); - MenuS is now 'r'
while (MenuS != 'q') { MenuS = Menu(); - call Menu again
gets(UserInput); - gets the blank string you typed earlier
if (UserInput[0] != 'q') - true, since UserInput[0] is 0, the end-of-string marker for your blank string
switch (UserInput[0]) { there is no case 0, so default: is entered
printf("\nSomething else");
To fix this: you need to discard the Enter that was pressed after you typed in the number. One way is to put this code straight after the scanf:
int c;
while ( (c = getchar()) != '\n' && c != EOF ) {}
Note, your code has a lot of other problems but this was the main issue.
So i have some code that will allow the user to write anywhere they want inside a text file, thanks to the answers from How do I write to a specific line of file in c? , However i have hit a new obstacle, whenever i write back to the file an annoying random character will always appear at the end of the last word, and if it's on the first line a new line is created before it.
I know this has something to do with the file copy but i don't know where, can someone please help?
int main()
{
FILE *fp,*fc;
int lineNum;
int count=0;
int ch=0;
int edited=0;
char t[16];
fp=fopen("start.txt","r");
fc=fopen("end.txt","w");
if(fp==NULL||fc==NULL)
{
printf("\nError...cannot open/create files");
return 1;
}
printf("\nEnter Line Number Which You Want 2 edit: ");
scanf("%d",&lineNum);
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n')
count++;
if(count==lineNum-1 && edited==0)
{
printf("\nEnter input to store at line %d:",lineNum);
scanf(" %s[^\n]",t);
fprintf(fc,"\n%s\n",t); /
edited=1;
while( (ch=fgetc(fp))!=EOF )
{
if(ch=='\n')
break;
}
}
else
fprintf(fc,"%c",ch);
}
fclose(fp);
fclose(fc);
if(edited==1)
{
printf("\nCongrates...Error Edited Successfully.");
FILE *fp1,*fp2;
char a;
system("cls");
fp1=fopen("end.txt","r");
if(fp1==NULL)
{
puts("This computer is terrible and won't open end");
exit(1);
}
fp2=fopen("start.txt","w");
if(fp2==NULL)
{
puts("Can't open start for some reason...");
fclose(fp1);
exit(1);
}
do
{
a=fgetc(fp1);
fputc(a,fp2);
}
while(a!=EOF);
fclose(fp1);
fclose(fp2);
getch();
}
else
printf("\nLine Not Found");
return 0;
}
(Sorry about ident, i'm in a rush)
Try changing your do-while loop like,
while((a=fgetc(fp1))!=EOF)
fputc(a,fp2);
I guess it will solve your problem.
do
{
a=fgetc(fp1);
fputc(a,fp2);
}
while(a!=EOF);
A do-while loop evaluates its condition after performing the body of the loop. In other words, this loop is writing EOF to the file, which you shouldn't be doing. EOF isn't actually a character, it's just something that gets returned by the OS when it's finished reading a file. I'm not sure what would be the end result of actually writing EOF to a file, but I'd hazard a guess this is what's causing the "annoying random character" you're talking about.
Invert the loop into a normal while loop, as follows, so that you're checking for EOF before writing anything:
while ((a=fgetc(fp1))!=EOF)
{
fputc(a,fp2);
}
1) As you said "and if it's on the first line a new line is created before it"
To solve this problem you have to optimize the use of fprintf(fc,"\n%s\n",t); statement.
Replace this fprintf(fc,"\n%s\n",t); with below code.
if(count==0) //if its the first line to edit..
fprintf(fc,"%s\n",t) //watch closely,no '\n' before %s,This will copy wihtout creating new line at beginning of line or file.
else
fprintf(fc,"\n%s\n",t);
2) And Your statement scanf(" %s[^\n]",t); will not work properly if you give multiple-words input.You have tried to use both ScanSet and %s fromat specifer. You should only use any one of them.
Lets understand with a code snippet:-
char t[16]="\0";
scanf(" %s[^\n]",t); //Assume that you gave input "abc efg" from keyboard
printf("%s",t); // This will output only "abc" on moniter.
You should change it to some thing like this:-
char t[16]="\0";
scanf(" %15[^\n]",t);//here 15 is sizeof(array)-1. one left to accomadate '\0'.
printf("%s",t); //this will successfully output "abc efg" (if given)
Sorry for the bad title, but i didn't know a better one!
Target: I'm trying to make an command handler. So I'm printing out via printf("cmd: ") and listing on stdin via fgets(). If theres an Input I'm check on commands via if .. else if. So my Problem now: If there is no input on stdin it should repeat the function and print cmd!
int cmd_handler()
{
printf("cmd: ");
char command[LINE_MAX];
fgets(command, LINE_MAX, stdin);
if(command != NULL)
{
if(strcmp(command, "xyz"))
{
xyz();
}
}
return 0;
}
I really don't know how i can arrange that. simple call cmd_handler() on else isn't working. Maybe someone can give me a tip how to solve it.
EDIT:
It should look like this, if there is no input(2x for example) on stdin:
cmd:
cmd:
cmd:
THIS CODE ISN'T THE REAL ONE!
regards
You need a loop. I would suggest a while loop with an exit condition, perhaps set by an "exit" command.
int run = 1;
while (run) {
printf("cmd: ");
...
else if (strcmp(command, "exit") == 0) {
run = 0;
}
}
You need to check whether fgets() returns NULL, not whether command is NULL:
if (fgets(command, LINE_MAX, stdin) != NULL)
Then you can add an 'else' clause to handle the error condition, as you were trying to do.
The way you check for empty string is not going to work.
if(command != NULL)
This condition will always evaluate to true as command, in the expression, gets converted to a pointer and is always non-null.
To check if there are any alpha-numeric characters, use isalnum() from <ctype.h> and ensure there's no whitespace characters in command. You seem to want to use recursion whereas a loop is probably more suited.
char command[LINE_MAX];
int alnum=0;
while(1) {
alnum=0;
printf("cmd: ");
fgets(command, LINE_MAX, stdin);
for(i=0;i<strlen(command);i++)
if(isalnum(command[i])) {
alnum=1;
break;
}
if(!alnum) continue;
if(strcmp(command, "xyz"))
{
xyz();
}
....
break;
}
This way, you can ensure it handles any whitespace you may input. But rest of your strcmp(command"xyy") will fail if user inputs " xyz". So it may suffice to check whether user simply hits ENTER:
if(command[0] == '\n') continue;
instead of the above check using alnum().
Soo... I saw a guy claim this code was working on another question.
while(scanf("%X", &hex) != EOF) {
//perform a task with the hex value.
}
So, in what context does the EOF flag get thrown? I though it would just keep asking for a number indefinitely. I added another line of code to test it, and it does exactly what I expected it too.....
This isn't a file, this seems to be stdin. So.... WHEN is this code useful?
Ie, in what context is the EOF return thrown?
If you look at the documentation for scanf, you will read that the value EOF is returned if a read failure occurred before the first value was assigned. (ie end of file)
http://en.cppreference.com/w/cpp/io/c/fscanf
You could equally test:
while(scanf("%X", &hex) == 1)
This is my preference. I expect one input, so I will be explicit.
Realistically speaking, this input is good on linux because ^d will end the stream, thus throwing the 'error.'
On windows, this behavior is different... whatever it is is not ctrl+d. At least I know now though, since I use both.
Thanks!
EOF is returned on I/O error and end-of-file. With stdin, an I/O error is a rare event and with keyboard input the end-of-file indication usual takes a special key sequence.
A practical use occurs with redirected input.
Assume a program exists that reads hexadecimal text and prints out decimal text:
// hex2dec.c
#include <stdio.h>
int main(void) {
unsigned hex;
int cnt;
while((cnt = scanf("%X", &hex)) == 1) {
printf("%u\n", hex);
}
// At this point, `cnt` should be 0 or EOF
if (cnt != EOF) {
puts("Invalid hexadecimal sequence found.");
return 1;
}
return 0;
}
// hex.txt contents:
abc
123
Conversion occurs with the command
hex2dec < hex.txt
2748
291
By detecting EOF on the stdin, the program knows when to return.
#include <stdio.h>
// copy input to output
// my version
int main()
{
int c;
printf("\n\nUse CONTROL + D to terminate this program\n\n");
while ((c = getchar()) != EOF) {
putchar(c);
}
if ((c = getchar()) == EOF) {
printf("\n\nProgram TERMINATED\n\n");
}
return 0;
}
When I enter control + D, the body of the if statement runs. That's what I had wanted, but as I analyzed the code more thoroughly, shouldn't it ask for my input again since the if's condition is (c = getchar()) == EOF?
When you hit ^D, input to the program is closed, so getchar() will subsequently always return EOF.
Control-D is canonical mode end-of-file character. When entered at the beginning of a line it causes an EOF condition to be seen by the process, that is the read returns 0. However if if Control-D is entered somewhere other than the beginning of the line it just causes the read to return immediately with what has been input thus far.
If you hit Control-D twice in a row you should see what I think you asking about.
EDIT
Here is a pretty good explanation.
^D terminates the program instantly. Thus you're getchar would never return when ^D is hit.
That is why REPL like python exits using 'exit()'.
If you want, try to use 'q' for quiting: