difference for and while loops file i/o - c

i write a code which takes values from text file and write in a text file, so I'm stuck on for and while reading end of file i think both of codes are right there is no any difference btw them,however I get difference. I'm unable to understand. Besides is there other way to read eof ? Thank you all appreciated answers.
for(st=(fscanf(fptr_in,"%c",&ch));
st==1;
st=(fscanf(fptr_in,"%c",&ch))){
the other
st=(fscanf(fptr_in,"%c",&ch));
while(st==1)
st=(fscanf(fptr_in,"%c",&ch));

The conditionals are different. In the for you are using the return value of fscanf which is an int. When an int is used as a conditional, it is the same thing as != 0:
int x;
if( x ) {}
//equiv to:
if( x != 0 ){}
In the while loop, you explicitly check if the return value is a 1. So, if you change your for loop to
for( (st=(fscanf(...)) == 1 )
(or conversely remove the ==1 from the while loop) they should produce the same behavior.

Related

For versus while versus do loop statements

Is there a difference between for and while statements? Is it just syntax?
#include <stdio.h>
void main() {
int cent_temp = 0;
int fah_temp;
while (cent_temp <= 20) {
fah_temp = (9 * cent_temp) / 5 + 32;
printf("%d degrees C = %d degrees F\n", cent_temp, fah_temp);
cent_temp++;
}
}
This means to me....
While the value of cent_temp is less than 20 then calculate fah_temp. Then increase the value of cent_temp by 1 and check it is still less than 20; then go round the loop again.
Regarding the syntax:
printf("%d degrees C = %d degrees F\n", cent_temp, fah_temp);
This means %d means print to the screen, replace with a decimal number the value of cent_temp and %d means replace with a decimal number the value of fah_temp.
#include <stdio.h>
void main() {
int cent_temp;
int fah_temp;
for (cent_temp = 0; cent_temp <= 20; cent_temp++) {
fah_temp = (9 * cent_temp) / 5 + 32;
printf("%2d degrees C = %2d degrees F\n", cent_temp, fah_temp);
}
}
My interpretation of the above is:
for cent_temp = 0 repeat while cent_temp less than 20 and then execute cent_temp+1 at the end. So cent_temp 0 goes into the loop to calculate fah_temp and gets printed to the screen. Then cent_temp goes up by one then goes round the loop again. Here I've used %2d instead of %d to signify that it should have 2 spaces for a decimal number (and they line up when executed). Both codes will not execute if cent_temp > 20.
Similarly rearranging the statement in a do while loop has a similar effect and doesn't really have an impact on the result.
Does each type of loop have a different application?
Please correct me if I wrong!
Is there a difference between 'for' and 'while' statements? Is it just
syntax?
To me, it is just syntax.
From K&R section 3.5 Loops -- While and For, I quote:
The for statement
for (expr1; expr2; expr3)
statement
is equivalent to
expr1;
while (expr2) {
statement
expr3;
}
except for the behavior of continue.
Grammatically, the three components of a for loop are expressions.
Most commonly, expr1 and expr3 are assignments or function calls
and expr2 is a relational expression.
Notes
As user #chqrlie has mentioned in the comments, control statements like break and continue make the situation slightly murkier.
There are some situations where the modify statement is necessary in the loop body. For example Erase-remove idiom with std::set failing with constness-related error (in C++ though)
Example
As an example, let us write a loop to print all the odd numbers between 1 and 100.
int i = 1;
while (i <= 100) {
printf("%d\n", i);
i += 2;
}
for (int i = 1; i <= 100; i += 2) {
printf("%d\n", i);
}
Opinion
I am not a language expert, but in most situations in practice I find them transformable.
I personally prefer using for syntax because:
loop control structure is in one single place (the for header) making it easy to read, and
the loop variable (e.g. i) is not exposed to the outer scope.
for(cent_temp = 0; cent_temp <= 20; cent_temp++)
{ /* code */ }
is 100% equivalent to
cent_temp = 0;
while(cent_temp <= 20)
{
/* code */
cent_temp++;
}
But a do-while is different since it puts the condition check at the end.
As for when to use which loop, it is a matter of style and therefore a bit subjective. The industry de facto standard style, used by the majority of all C programmers, goes like this:
for loops should always be used when performing a known number of iterations. It is then considered the most readable form.
while loops should be used the the number of iterations is unknown in advance, or when the loop is turning complex for some reason. For example if you need to alter the loop iterator variable inside the loop body, then you should use a while loop instead of a for loop.
do while loops should be used for special cases where you need to skip the condition check the first lap of the loop, for example do { result = send(); } while(result == ok);.
I looked at my Code Complete by Steve McConnell (the bible).
Here is what you can read in chapter 16:
A for loop is a good choice when you need a loop that executes a specified number of times. [...]
Use for loops for simple activities that don't require internal loops controls. Use them when the loop involves simple increments or simple decrements, such as iterating through the elements in a container. The point of a for loop is that you set it up at the top of the loop and then forget about it. You don't have to do anything inside the loop to control it. If you have a condition under which execution has to jump out of a loop, use a while loop instead.
Likewise, don't explicitly change the index value of a for loop to force it to terminate. Use a while loop instead. The for loop is for simple uses. Most complicated looping tasks are better handled by a while loop.
In general, you would use a for loop to iterate over a finite set of values, whereas you'd use a while or do-while loop to iterate while a specific condition or set of conditions is true. In most of C's contemporaries (Basic, Pascal, Fortran, etc.), a for loop can only iterate over a scalar index:
Fortran:
DO 10 i=1,10
statements
10 CONTINUE
Pascal:
for i := 1 to 10 do
begin
statements
end;
Both of these snippets loop exactly 10 times. The index i is initialized and updated by the loop automagically. I'd have to go back and check, but I'm pretty sure you cannot write to i in the loop body.
C actually blurred the lines between a for and while loop by adding the control expression:
for ( init-expr ; control-expr ; update-expr )
statement
In C, a for loop can iterate over a scalar just like Fortran or Pascal:
for( i = 0; i < 10; i++ )
{
do_something_with( i );
}
Or it can iterate over multiple scalars:
for ( i = 0, j = 0; i < 10 && j < 10; i++, j++ )
{
do_something_with( i, j );
}
Or it can iterate over the contents of a file:
for( c = fgetc( in ); c != EOF; c = fgetc( in ) )
{
do_something_with( c );
}
Or it can iterate over a linked list:
for( cur = head; cur != NULL; cur = cur->next )
{
do_something_with( cur );
}
In Fortran and Pascal, those last three loops would have to be expressed as while loops (which I'm not going to do, because I've pretty much exhausted my Fortran and Pascal knowledge already).
The other big difference between a C for loop and those of Fortran or Pascal is that you can write to the loop index (i, j, c, or cur) in the loop body; it's not specially protected in any way.
A while or do-while loop is used to iterate as long as a specific condition or set of conditions is true:
while( control-expr )
statement
do
statement
while( control-expr );
In both a for and while loop, the condition is tested before the loop body executes; in a do-while loop, the condition is tested after the loop body executes, so a do-while loop will always execute at least once.
In C, you can use either a for loop or a while loop in many circumstances:
while ( ( c = fgetc( in ) ) != EOF )
do_something_with( c );
for ( c = fgetc( in ); c != EOF; c = fgetc( in ) )
do_something_with( c );
Both loops do exactly the same thing; it's just a matter of which one you think more clearly expresses your intent, or which you think would be easier for other people to understand.
From the point of view of algorithmic for and while are not the same. Shortly, in algorithmic, for should be used when bounds are known and while when you don't know if the condition can be met or when it can be. For is to repeat something n times (n known), which is exactly the case of your example computation; a for loop should be used (don't you think what the loop makes is more clearly stated in the for loop ?). If you want an example of a must be used while loop, look at something like Collatz sequence. From a point of view of computability, for loops can always be transformed in while loops but not the converse.
From the point of view of computer languages it is now common to fuse both, in C for example, it makes no difference, only syntactic. But remember that in some other language that could be very different, for example in Pascal for loops are very limited.
Source code is written not only to be compiled and executed by computers but also to be read and understood by humans.
A computer doesn't really mind whether a for loop, a while loop or a goto is used. On the other hand, a human expects different meanings for different structures.
computing values over a known range of inputs is best shown with a for loop;
reading a file up to its end is best shown with a while loop.
Choosing which structure to use is similar as choosing a variable name.

Array-member comparison in a function not working

First of all I'm not even sure whether you call it a member, couldn't think of a better term.
I'm trying to learn basics of debugging and arrays - so I wanted to create something resembling insert-sort from memory (so mistakes would be made) and then debug the program.
void findingsmaller (int *array, int num_inputs){
int a = 0;
int b = 1;
for ( b=1; b == num_inputs-1; b++ ) {
if ( array[a] > array[b] ) {
goleft(array, a, b);
a++;
}
}
}
Let's say we have this in array: 6 5 3 1 8 7 2 4. array[a] should be 6 and array[b] should be 5. 6 > 5 so we should enter the function that would find the first smaller number on the left of the array.
From my debugging session it seems like the condition is FALSE so I don't enter goleft at all. More specifically, Step into ignores it, the testing printf wasn't executed either. I'm assuming the array comparison is not written properly, what's the correction?
WHOLE CODE if somebody wants to see other possible mistakes.
Thank you in advance!
EDIT: <= num_inputs is correct, somehow I thought for has (range1, range2, change) instead of (start, condition, change). Anyway, now the problem seems that my goleft function does its do-while cycle one time too many although it shouldn't get past that condition.
EDIT2: A couple of other mistakes were fixed.
My printing in main is now for( ; i <= num_inputs-1; )
My goleft would do too many iterations due to the condition, fixed into ... while ( a >= 0 && array[a] > array[b] )
My findingsmaller would only operate if the number next is smaller but does nothing when the number is greater. For example for 6 8 the program wouldn't function properly. Added else {a++}
My fixed code for anyone interested in the comparison of the changes.
The for loop is executed as long as the condition is True.
for ( ;Condition; )
{
// body
}
In your for loop, the condition is always False if the input is greater than 1.
Instead of b == num_inputs - 1, you should put b < num_inputs in your for loop condition. Since the equality isn't true on the first iteration of the loop, it is immediately breaking.
I was looking a little bit at your code and i notice something that doesnt work.
while (scanf("%d", &array[i]) != EOF)
As the documentation of the function scanf say :
The return value is EOF for an error
your while condition was making you num_imputs reaching 200 even if there was only 3 inputs. I would replace EOF by '\n'.
while (scanf("%d", &array[i]) != '\n') /* stop when the user input '\n' you
can replace with any character you want to make it stop. */
I did not make a lot of test but this should make your program work fine.

assignment works as a condition

Consider the following Code,
int i;
while(i=0)
printf("Hello");
Now Generally speaking i=0 is an assignment and not a condition for while to check.
But the GCC compiler lets it go with a warning and even evaluates it correctly (does not execute the print statement).
Why? I usually would do with parenthesis for the truth value but my juniors feel that I am wrong and there is no real reason for the parenthesis in this!
EDIT: Zeroing down on the 'actual' doubt, Please consider the following test case
int callme(){
return 0;
}
int main(int argc,char*argv[]){
int c;
while(c = callme()){
printf("Calling...\n");
}
return 0;
}
The expression i = 0 does 2 things:
Has the side effect of storing o in i
Yields the value 0
I usually would do with parenthesis for the truth value but my juniors
feel that i am wrong and there is no real reason for the parenthesis
in this
It's usually a hint to the compiler meaning "I actually want this, I didn't forget a =, shut up".
For your specific case there's no reason to write if (i = 0): you already know what if (0) does. But it's pretty useful when used as:
if ((i = some_function()))
...
i=0 is always an assignment (unless you have it as part of int i = 0; where it is an initialization). But any non-void expression may appear inside the condition of a while loop and if it evaluates to non-zero, the body of the loop will be executed, and if it is zero, the body of the loop will not be executed.
The notation:
while (i = 0)
printf("Hello\n");
is always equivalent to:
i = 0;
There is very little justification for writing the loop at all.
People do write other expressions:
while (c = getchar())
...process EOF or a non-null character...
But that's usually a bug. It is more likely that you should be writing:
while ((c = getchar()) != EOF)
...process a character - possibly null...
or even:
while ((c = getchar()) != EOF && c != '\0')
...process a non-null character...
The first getchar() loop gets a warning from GCC; the latter two do not because of the the explicit test of the value from the assignment.
The people who write a condition like this:
while ((c = getchar()))
really annoy me. It avoids the warning from GCC, but it is not (IMNSHO) a good way of coding.
When you use an assignment operator such as
a=0;
You assign the value to 'a', and still return the number 0.
To test your question, I tried these lines of codes:
int a;
printf("%d", a=0);
and these lines displayed 0.
Then, I tested another set of codes:
int b;
printf("%d", b=15);
Here, the lines displayed 15.
So, if you do:
while(a=0)
{
printf("zero");
}
The (a=0) statement would return false, thus not displaying anything.
But if you do:
while(a=15)
{
printf("fifteen");
}
The "fifteen" will be displayed endlessly, because the statement (a=15) will return a non zero value, or 15, which is not false, not zero, thus it is true. :)
As cnicutar has told above the assignment also yields the value zero.
Some additional info:
It is a common coding mistake for people to omit an extra '=' whereby the comparison becomes an assignment.
An easy way to avoid this is to write the comparison as below, in which case even if a '=' is missed compiler will give an error
while(0 == i)
{
prinf("Hello");
}

fgetc() doesn't work properly

I have file that goes like 7 4 5 1 etc. I want to put these number in a multi-dimensional array.
for(x=0;x<9;x++)
for(y=0;y<9;y++)
{
current=fgetc(fp);
if(current!=EOF&current!=' '&current!='\n')
sudokuArray[x][y] = current-'0';
}
This code doesn't work properly. sudokuArray[0][0] gives the result true(first number in the file) but [0][1] gives some random number like 131231304. [0][2] gives what [0][1] supposed to be. Why is that?
It's because if your inner loop:
for(y=0;y<9;y++)
{
current=fgetc(fp);
if((current!=EOF) && (current!=' ') && (current!='\n'))
sudokuArray[x][y] = current-'0';
}
If your input is 7 4 5 1, then when y == 0, you read '7', which gets put in sudokuArray[0][0].
Now on your next loop, y == 1, and you read ' '. Because of your if statement, you don't put that in sudokuArray but y still gets incremented.
Next time you do the loop, y == 2, you read '4' and it gets put in sudokuArray[0][2].
So fgetc() does work properly and your code is doing exactly what you told it to do. Code is very obedient that way.
Edit: Also note your if statement should contain && instead of &. They are different operators. A little whitespace and some parenthesis make the code easier to read and maintain as well.
I am not sure why you use nested loops to read from file. I see one problem in your code:
Change & to &&:
if(current!=EOF&current!=' '&current!='\n')
to:
if(current!=EOF && current!=' ' && current!='\n')
&& is the logical AND and & is bitwise AND.
Since, you have only integers and you seem to know the exact no. of integers. You can simply use fscanf:
fscanf(fp, "%d", &arr[x][y]);
Inside your loop you're ignoring characters - but then you're incrementing the indexes even though you haven't filled the related array element. Try re-implementing as:
#include <stdlib.h>
for(x=0;x<9;x++)
for(y=0;y<9;y++)
{
/* Get next character */
current=fgetc(fp);
/* Loop, retrieving additional chars, until either EOF is hit or
you find a non-whitespace character */
while(current != EOF && iswhite(current))
current = fgetc(fp);
if(current != EOF)
sudokuArray[x][y] = current - '0';
}
Also - do you want to check current != EOF, or should this be !feof(fp)?
Share and enjoy.

Explanation of stack overflow when using read on a small file and a questionable workaround

I hope the question explained my problem. I would also be grateful if the workaround that "works" is explained.
The traditional way of reading a file (that i know of)
int fd;
char buffer[MAX];
while(read(fd,buffer,MAX)>0)
{
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}
was causing an overflow. The workaround that somehow unexpectedly worked was
while((read(fd,buffer,MAX)!=0)||(read(fd,buffer,MAX)!= -1))
{
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}
^^ This code printed out the entire file, no skips as far as observable.
Things like
do
{
int temp;
temp=read(fd,buffer,MAX);
if((temp == 0) || (temp == -1))
{
break;
}
buffer[MAX]='\0';
write(sockfd,buffer,MAX);
memset(buffer,NULL,MAX);
}while(1);
also caused a stack overflow. Am i missing something really important here?
Thanks
Why do you say that it's causing an overflow?
Do note that read() will not write a \0 in the end of the char array, so if you do something like printf("%s", buffer) it will likely fail because printf will be expecting a NUL terminated string. You may be wanting to read MAX-1 and set buffer[number_of_read_characters] = '\0' where number_of_read_characters is whatever read() returned, if positive.
Also note that when you declare char buffer[MAX], since in C indexing is zero-based, the highest buffer index is MAX-1, so when you're setting buffer[MAX]='\0' you're already out of your array bounds.
One problem:
buffer[MAX]='\0';
steps on stack, as the highest valid index for array of size MAX is MAX-1 (due to 0-based indexes).
-1 return value from read indicates an error, so the right thing to test read() > 0. Moreover, the normal return value from read is the number of bytes read, and read does not guarantee any 0-termination. you have to do someting along the lines of
while (bytesRead=read() > 0) {
write(buffer, bytesRead);
...
Glancing at the code, I'd suggest that it's because the logic is different.
In the example that works, the read(fd,buffer,MAX) method is being executed twice.
Think of it like:
while (dosomething() != 0 || dosomething() != -1)
{
// some work
}
This loop will be infinite if the dosomething() method is idempotent, however if the first time you run it within the while statement is different than the second, it will break.
That explains how the execution path differs, but I can't figure out why the first option overflows... I'll think about it and update. (or not - it seems it's been answered!)
Try this:
int fd, readCharacter;
char buffer[MAX];
while( readCharacter = read(fd, buffer, MAX**-1**) > 0 )
{
buffer[readCharacter] = '\0';
// ...
}

Resources