Why does the scanf cause my code to be running indefinitely? - c

When I try to run this code it just runs indefinitely. I have tried to use scanf_s but that did not change anything.
#include <stdio.h>
int main (void)
{
int height, length, width, volume, weight;
printf("enter height of box: ");
scanf(" %d", &height);
printf("enter length of box: ");
scanf(" %d", &length);
printf("enter width of box: ");
scanf(" %d", &width);
volume=height*width*length;
weight=(volume+165)/166;
printf("volume (cubic inches): %d\n", volume);
printf("dimensional weight (pounds): %d\n", weight);
return 0;
}

The first print in your code (and similarly the others):
printf("enter height of box: ")
By default, this line will put the text into a buffer. The buffer is written to terminal ("flushed") only if either one of the following happens:
The buffer gets full (can be 1024 bytes, 16384, or any other number).
There is a newline at the end of the text (assuming the output is to the terminal).
Note that this is a common behavior, but not guaranteed by the standard. Read Is stdout line buffered, unbuffered or indeterminate by default? to cover this subject.
Some C implementations will automatically flush stdout when you read from stdin, but many implementations don't.
Read Does reading from stdin flush stdout? to cover this subject.
So you can see your prompt if you change the line to:
printf("enter height of box: \n");
A second option, is to force a flush, so that the buffer is written to the output:
printf("enter height of box: ");
fflush(stdout);
A third option is to disable buffering completely. For that, you can use setbuf:
void setbuf( FILE* stream, char* buffer );
buffer -
pointer to a buffer for the stream to use. If NULL is supplied, the buffering is turned off. If not null, must be able to hold at least BUFSIZ characters
So, simply add the following at the beginning of the program, and all stdout buffering will be turned off:
setbuf(stdout, NULL);

there doesn't seem to be any mistakes in the code. i tried running it on Ubuntu And OnlineGDB. The Code is working just fine. It Can be your compiler's fault.
You should check what "scanf" is returning.
you can check it using this:- (here d is your integer)
if (scanf("%d", &d) == 1)
...all OK...
else
...EOF or conversion failure...
If you have several conversions, check that they all completed.

There may be a problem cause you might not be entering any value as input.
In all other cases, the code seems to work fine.

Related

do-while or scanf() in c does not work

On running this code, the outer do-while does not work. It prints
"Do you want to enter another number(y/n)-"
but it does not let me enter y or n in order to use the program again. Where did I go wrong?
#include <stdio.h>
#include <math.h>
int main()
{
int num, x, sqsm, psqsm;
char further;
sqsm = 0;
do
{
printf("Enter a natural number-");
scanf("%d", &num);
x = num * num;
do
{
sqsm = sqsm + x;
x = (sqrt(x) - 1) * (sqrt(x) - 1);
} while(x > 0);
printf("Sum of squares of first %d natural numbers=%d\n",num,sqsm);
printf("Do you want to enter another number(y/n)-");
fflush(stdin);
scanf("%c",&further);
} while(further == 'y');
}
Use
scanf(" %c",&further);
^^^
otherwise white space characters will be read.
Also remove this statement
fflush(stdin);
because such a call results in undefined behavior.
If you would see in the documentation of fflush() you would find this :
For input streams associated with seekable files (e.g., disk files,
but not pipes or
terminals), fflush() discards any buffered data that has been fetched from the
underlying file, but has not been consumed by the application.
This actually means the fflush() is definitely defined well for input streams but with the given limitation of pipes and terminals.
In your example, the stdin is attached to a terminal stream (it is the default, you can even redirect/change it) and therefore using fflush(stdin) is actually undefined behaviour.
On the other hand, if you closely look into scanf()'s documentation, you will find this :
· A sequence of white-space characters (space, tab, newline,
etc.; see isspace(3)). This directive matches any amount of white space, including none,
in the input.
What it actually says is scanf("<a space character><your string>") can directly be used to flush (or read and ignore, to be accurate) the newline characters (and others stated in the docs).
So, in your example, using scanf(" %c", &further)(with the space before %c) will actually produce the expected behaviour.

Reading and Writing in C

so I was messing with the read functions fgets and scanf and with the printing functions write and printf with the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
printf("Enter an integer: ");
int n = 0; scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
char buffer[200];
read(0,buffer,200);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
fgets(buffer,200,stdin);
write(1,buffer,200);
return 0;
}
I would get these errors:
1-After the first scanf, it won't just show me the message to input the string.
2-What I write now it's what it's going to be saved in the string.
3-It will skip the last fgets...
An example of output:
Which doesn't make any sense at all; I would like to get an output like this:
Enter an integer: 15
The input number is: 15
Please enter a string now: This is the message1
The input string is: This is the message1 which is: This is the message1
Now please enter another message: This is the message2
This is the message2
Thanks for your help!
Interesting question. Mixing standard I/O (scanf(), fgets()) and file descriptor I/O (read()) on the same underlying file descriptor (0 aka standard input; stdin as a file stream) is at best problematic. You will get odd-ball effects.
At the file stream level, there is some synchronization between stdin and stdout when the input comes from a terminal; pending output on stdout is often flushed by the library. When you use read(), there is no such synchronization. That's why the prompt doesn't appear until after you hit return.
When you type 1 for the number, you also supply a newline. Standard I/O buffers the newline; it is kept so that the next file stream operation can read it. Then you read a line with read(). This does not know about the standard I/O buffer, so it waits for a new line of input from the terminal. You need to capture how much data was read because the input was not null terminated; that's a service provided by the standard I/O library, not the low-level read() function.
When you then call fgets(), it reads the newline that was buffered (not processed by scanf() when reading the integer) and returns with the empty line.
Note that if you had any buffered output waiting on standard output (e.g. you had used printf("Beginning of line: "); with no newline), then the output from write() would appear before the information buffered on stdout.
Using fread() and fwrite() would give you direct binary I/O (no null termination, for example), but would use the same I/O buffers as functions such as printf() and fgets(). You get hybrid behaviour when using these — it is normally best to use either fread()/fwrite() or the text I/O functions on a single file stream, and not both, but mixing them is permissible, relatively simple to understand, and occasionally useful.
So, what you see is all explainable, but it is hard work doing the explaining. It is also a clear indication of why you should not, in general, mix file stream and file descriptor I/O on the same underlying file descriptor — especially not standard input.
Why not use scanf with some better formatting:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
int n, i;
char buffer[200], ch;
printf("Enter an integer: ");
scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
scanf(" %[^\t\n]s",buffer);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
scanf(" %[^\t\n]s",buffer);
printf("%s", buffer);
return 0;
}
read(0,buffer,200);
reads up to 200 characters but it won't add a terminating null character to buffer. Hence the following call to printf results in undefined behavior.
You need to add code to capture the return value of the function and make sure to null terminate the string.
int n = read(0, buffer, 199); // Leave one for the terminating null character
if ( n == -1 )
{
// Deal with the error.
}
else
{
// null terminate the string.
buffer[n] = '\0';
}

Program output in wrong order

I working on a C project in Eclipse environment the code is correct and executable but the output
lines are not in order the program ask user to
enter a number from 1-5 then asks for a name then street
but nothing appear on console screen unless i entered these values
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char name[20], address[30];
char c;
printf("How do you feel on a scale of 1-5?");
c = getchar();
printf("Enter name: ");
scanf("%s", &name);
printf("Enter your address: ");
scanf("%s", &address);
printf("Entered Name: %s\n", name);
printf("Entered address:%s\n", address);
printf("You said you feel: ");
putchar(c);
return EXIT_SUCCESS;
}
The problem is that stdout is line buffered (when going to a console), so unless you print a newline character, the output will remain buffered and not be displayed (OK, there's going to be a maximum size that can be buffered put that's just detail, your small amount of output will remain in buffer).
The two solutions that occur to me are, use fflush (stdout); after your first 3 printf calls, this will cause the stdout buffer to be flushed to the console, and should resolve your problems.
You could also turn off buffering of stdout, see setvbuf for how to do this, but I think, placing this call near the start of main (before any output) should work (untested):
setvbuf (stdout, NULL, _IONBF, 0);
The problem is your second scanf is capturing the \n character of the previous input, try to use fgets in order to avoid this behaviour.

Is it possible to use scanf("%d" &i) and use the first number inputted only, and nothing else?

First off, I am not familiar with c at all. It would be great if you treated me like a total beginner, which I am.
So, the problem I have is that I don't seem to be able to make it so that the program only takes the information of one number, uses it, then disregards any other information.
At the moment I have something similar to this:
#include <stdio.h>
#include <string.h>
int main(){
int i, ret;
char c, type;
do
{
printf("Convert ASCII # to character\n");
printf("q: Quit.\n");
scanf("%c", &type);
/* I use the " if(type== 'n'); " a number of times. */
/* I left the others out to simplify what my problem is. */
if(type=='1'){
printf("ASCII NUMBER -> CHAR \n");
printf("\t Please input one ASCII code \n");
int ret = scanf("%d", &i);
/* My aim here is to get the amount of integers the user inputs,*/
/* and use that to categorize, but I think I am failing to do so. */
if(ret==1){
printf("\t The character for ASCII code %d is -> '%c' \n\n", i, i);
break;
}
else{
printf("Please input one number./n/n");
break;
}
}
}
while(type=='q');
return 0;
/* A problem I face a lot is where the program would terminate*/
/* even when the while conditions weren't met. */
}
I hope you could understand what I'm trying to do by looking at the code above.
Any help would be greatly appreciated!
the program ends because of the character [enter] left in the input buffer.
You give input value for type then for i and press [enter]. this [enter] is a character left in the input buffer which will be read by next
scanf("%c",type);
so the loop exits. Therefore use getchar() after
int ret = scanf("%d", &i);
To clear the input buffer. and the loop will not end unexpectedly.
Make these changes,
printf("\t Please input one ASCII code \n");
int ret = scanf("%d", &i);
getchar(); //this will read the [enter] character in input buffer
/* My aim here is to get the amount of integers the user inputs,*/
/* and use that to categorize, but I think I am failing to do so. */
if(ret==1){
In general, I find it better to use fgets() (alternatively, if you are using C99, gets_s() -- although I still prefer fgets() for maximum portability to older compiler environments) for all user-based input, then if necessary use sscanf(), strtol(), and the like to convert the string into other data types, as this will read data by line in a way that is buffer-safe and you won't have to worry about things left in the input buffer. This is especially true for user-based input which is never well-formed (due to typos, etc). scanf() really only works well when reading from well-formed input files.
See the comp.lang.c FAQ which describes some of the problems that often occur when using scanf() in detail, including the problem you are seeing above, where inputs seem to be getting skipped:
http://c-faq.com/stdio/scanfprobs.html
http://c-faq.com/stdio/scanfhang.html
http://c-faq.com/stdio/scanfinterlace.html
http://c-faq.com/stdio/scanfjam.html
To find out more about any C standard library function, at a linux command prompt (or Google) type: man 3 fgets and so on.
fgets: http://linux.die.net/man/3/fgets
sscanf: http://linux.die.net/man/3/sscanf
strtol: http://linux.die.net/man/3/strtol
Example:
char buffer[256], type;
fgets( buffer, sizeof(buffer), stdin );
if( sscanf( buffer, "%c", &type ) == 1 ) {
// Was able to read a char from the buffer, now you can use it.
}
else {
// Wasn't able to read a char from the buffer. handle it if required.
}

Write int structure data type to file in c

A bit of background to my program. I'm asking the user to input coordinates for two different colour crystals. This will be held in a structure and then written to file, to be read back later by the program (function yet to be written).
I have had a look on forums and blogs but I seem to be only finding results relating to character arrays, whereas I am using an int array.
My code works fine until the writing of the data to the file. (this is the snippet of code)
char fname[20];
FILE *fp;
int loop;
struct coord{
int x;
int y;
};
for(loop=0;loop<3;loop++){
printf("Enter MAGENTA X coordinate: \n");
scanf("%2d",&mg[loop].x);
printf("Enter MAGENTA Y coordinate: \n");
scanf("%2d",&mg[loop].y);
printf("\n\n");
}
for(loop=0;loop<3;loop++){
printf("Enter YELLOW X coordinate: \n");
scanf("%2d",&ylw[loop].x);
printf("Enter YELLOW Y coordinate: \n");
scanf("%2d",&ylw[loop].y);
printf("\n\n");
}
clrscr();
printf("\nDetail entered:");
printf("\n\n\tMagenta\t\tYellow\n");
for(loop=0;loop<3;loop++){
printf("\tx %d,%d y\tx %d,%d y\n",mg[loop].x,mg[loop].y,ylw[loop].x,mg[loop].y);
}
printf("\n\nPlease save your data. Enter file name: ");
gets(fname);
fp=fopen(fname,"w");
for(loop=0;loop<3;loop++){
fprintf(fp,"%d,%d ",mg[loop].x,mg[loop].y);
fprintf(fp,"%d,%d ",ylw[loop].x,ylw[loop].y);
}
fclose(fp);
Thank you in advance.
There's nothing wrong with how you write the data to the file (maybe except that you should check the return value of fopen.)
Your problems are in the input of your data from stdin. First, your read in a bunch of coordinates with scanf. scanf is not a line-based format; it treats a new-line character like any other white-space.
Then you use gets, which you really shouldn't - use fgets instead, because it allows you to specify a maximum buffer size so that you don't overflow your buffer of 20.
Okay, say you use fgets, which is a line-based format. You have to take care when mixing scanf and fgets, because they work differently. Also input from the console is usually buffered until the next newline, when it is all flushed, which can create a discrepancy between what you see on the screen and how the program processes input.
Say you read two numbers with scanf and then a filename with fgets. Your input looks like this:
1 2 \n 5 1 \n d a t a . t x t
a a b b b c
After reading the first number the input marker is after the number, before the newline. scanf skips white space before numbners read with "%d", so the second number is read in, but again, input stops before the newline. Then you read a line with fgets and read everything up to the next newline, which is nothing. The real filename would be read by the next scanning function, but there isn't any, so it's discarded.
(That's where your str != NULL is coming from: it's an assertion that has failed withinfopen`. This is nopt something that the compiler does, though. When you run the program, it has already been compiled. The run-time library does such error checking of conditions it can't know at compile time.)
(What's worse: fgets, unlike gets, retains the newline after the read string. You shoud remove that and possibly other leading and trailing white-space, too. Otherwise you'll end up with a file name that has a new-line in it, which is not funny.)
Anyway, how can you fix this? Change your scanf formats from "%d" to "%d " with a trailing space. "Space" has a meaning to scanf: read any amount of white space.
Alternatively, you could stick to scanf and read your filname with scanf("%19s ", filename). That has the benefit of reading a string without any whitespace in it.
Reportedly you have fixed this by calling fflush(stdin) before reading the filename. The behaviour of fflush on input streams is implementation-dependent and not guaranteed by the standard. If it worked for you, leave it at that.

Resources