How to read character until a char character? - c

I'm trying to do a loop that read from a file a single character until it finds '\n' or '*'.
This is the loop that I wrote:
i=0;
do {
fscanf(fin,"%c",&word[i]);
i++;
} while(word[i]!='*'&&word[i]!='\n');
Now I tried to see why it doesn't work with a debugger. When I print word[i] immediately after the fscanf it shows me the correct character but then, if I try to print word[i] while it's doing the comparison with '*' or '\n' it shows me that word[i] is '\000' and the loop never ends.
I also tried with fgetc but I have the same error.

You have to make sure that the character you are processing is the same you just read.
Actually you increment counter i before testing word [i], that's why your check fails.
Try instead
i=0;
do {
fscanf(fin,"%c",&word[i]);
}while(word[i]!='*'&&word[i++]!='\n');
I would rather move the check in the loop (break if the condition is satisfied) leaving in the while check the test on word array length.

Another way:
for(;;) {
int c = fgetc(fin);
if ( c == EOF ) {
break;
word[i] = c;
if( c == '*' || c == '\n' ) {
break;
}
}

Your while condition is not testing the same element of word that you just read, because i++ incremented the variable before the test.
Change the test to use word[i-1] instead of word[i] to adjust for this.
BTW, word[i] = fgetc(fin); is a simpler way to read one character.

Related

Copying string:while loop breaks on the first condtion only using C

I want to copy a string and want to stop copying either the next character is '\0' or '.'
so I wrote
while((dest[i]=src[i])!='\0'||src[i]=='.');
i++;
when the character is '\0' the while loop works perfectly
but in case of '.'
must I write a separate "if condition" for the second part ?and why?
You have an infinite loop there.
while((dest[i]=src[i])!='\0'||src[i]=='.'); // This is the end of the loop,
// with an empty statement.
Also, you need to change the conditional a little bit.
(dest[i]=src[i]) != '\0' && src[i] != '.'
To avoid the empty statement problem after while and if statements, you can change your coding standard so that you always use the {}.
while ( (dest[i]=src[i]) != '\0' && src[i] != '.' )
{
++i
}

Trying to understand a simple C copy function

I'm trying to understand function which copies characters from stdin but I can't understand the while loop and the code following it exactly..... How does the while loop here work??
From what I understand it means until ith character from to[] isn't equal to ith character of from[] keep on adding i am I correct??
If yes than how does the ith character be equal in both the variables ??
Here is a short code :
void copy(char to[] , char from[])
{
int i;
i = 0 ;
while ((to[i] = from[i]) != '\0')
++i;
}
Rewriting it might help:
do{
to[i] = from[i];
++i;
}while (from[i-1] != '\0') // -1 here because we incremented i in the line before and need to check the copied position
Do you understand now?
The condition in the while loop uses the fact that in C an assignment expression has a value which is the value assigned in the assignment. This means that the condition in the while loop can be implemented to have a side-effect, namely the element-wise assignment of the source to the destination. In total, the actual work of the loop is carried out in its condition, while the loop's body just increases the index i.
It's how assignments work. An assignment (a = b) returns a value (b). What you're doing there, is moving from[i] to to[i], and comparing the return value (in this case, from[i]) to the character '\0'.
The null character (0x00) terminates any string, and is thus the terminating character of the string you're copying.
I'd be careful with this code, however, as you don't check the bounds on the array and are leaving yourself open to a segmentation fault if you were to encounter a string that isn't properly null terminated, or where the to[] string is too short.
It first copy from ith character to to ith position and check that, if its the end of string. if not then it increments i(position or index that will point now to next character) and perform this operation until its matches end of string i.e '\0' .
Your code is the same as
void copy(char to[] , char from[])
{
int i;
i = 0 ;
while (from[i] != '\0')
{
to[i] = from[i];
++i;
}
to[i] = '\0';
}
So while it's not at the end of to, it continue copying from in to.

what is wrong with the while loop here ? C basics

I am trying to count the number of letters of a word before the space. For eg. "Hello how" is my input string and I am trying to count the number of letters in the first word.
#include<stdio.h>
#include<string.h>
int main()
{
char a[30];
int count = 0;
printf("Enter the string.\n"); // Enter hello how as string here.
gets(a);
for ( i = 0; a[i] != '\0'; i++ )
{
while( a[i+1] != ' ' )
count++;
}
printf("%d\n",count);
}
This is a small part of a bigger code, I am actually expecting the value of count to be 5 but it gets into some sort of infinite loop which I am unable to figure out. If I use if instead of while , I get the expected answer. I know gets is not very reliable and I will not use once I get better at programming so it will be kind of you to post your answer about the loop instead of gets. Thank You.
The NUL character is written with a backslash (\), not forward slash (/).
for (i = 0; a[i] != '\0'; i++)
Furthermore, the inner loop will not terminate because you're not incrementing i.
while (a[i] != ' ') {
i++;
count++;
}
Actually, you should not really have two loops. One loop is all you need.
for (i = 0; a[i] != '\0' && a[i] != ' '; i++) {
count++;
}
The expression within the while statement does not depend on count. So with every iteration of the while loop the count gets incremented, but that has no influence on the while conditional, hence it will loop ad infinitum or never, depending on the character at a[i+1].
In addition to that, the conditional statement for the for loop is not written correctly either. The string escape for a NUL character is \0 (backslash). Or you can just compare against a 0 literal, which has exactly the same outcome (though when it comes to the subtleties of C it does not mean exactly the same, but that's splitting hairs).
Use '\0' instead of '/0' in the for loop condition and also the while loop condition will never be false because i remains the same

Infinite loop when getting a line with getchar()

I was trying an exercise from K&R (ex 1-17), and I came up with my own solution.
The problem is that my program appears to hang, perhaps in an infinite loop. I omitted the NUL ('\0') character insertion as I find C generally automatically attaches it to the end of a string (Doesn't it?).
Can somebody please help me find out what's wrong?
I'm using the GCC compiler with Cygwin on win8(x64), if that helps..
Question - Print all input lines that are longer than 80 characters
#include<stdio.h>
#define MINLEN 80
#define MAXLEN 1000
/* getlin : inputs the string and returns its length */
int getlin(char line[])
{
int c,index;
for(index = 0 ; (c != '\n') && ((c = getchar()) != EOF) && (index < MAXLEN) ; index++)
line[index] = c;
return (index); // Returns length of the input string
}
main()
{
int len;
char chArr[MAXLEN];
while((len = getlin(chArr))>0)
{
/* A printf here,(which I had originally inserted for debugging purposes) Miraculously solves the problem!!*/
if(len>=MINLEN)
printf("\n%s",chArr);
}
return 0;
}
And I omitted the null('\0') character insertion as I find C generally automatically attaches it to the end of a string (Doesn't it?).
No, it doesn't. You're using getchar() to read input characters one at a time. If you put the chars in an array yourself, you'll have to terminate it yourself.
The C functions that return a string will generally terminate it, but that's not what you're doing here.
Your input loop is a little weird. The logical AND operator only executes the right-hand-side if the left-hand-side evaluates to false (it's called "short-circuiting"). Rearranging the order of the tests in the loop should help.
for(index = 0 ; (index < MAXLEN) && ((c = getchar()) != EOF) && (c != '\n'); index++)
line[index] = c;
This way, c receives a value from getchar() before you perform tests on its contents.
I'm not positive about what's wrong, but you don't provide the input to the program so I'm guessing.
My guess is that in getlin your variable c gets set to '\n' and at that point it never gets another character. It just keeps returning and looping.
You never SET c to anything inside your getlin function before you test it, is the problem.
C does not insert a NUL terminator at the end of strings automatically. Some functions might do so (e.g. snprintf). Consult your documentation. Additionally, take care to initialize all your variables, like c in getlin().
1) C doesn't add a final \0 to your string. You are responsible for using an array of at least 81 chars and puting the final \0 after the last character you write in it.
2) You're testing the value of c before reading it
3) Your program doesn't print anything because printf uses a buffer for I/O which is flushed when you send \n. Modify this statement to print a final \n:
printf("\n%s",chArr);
to become:
printf("%s\n",chArr);
4) To send an EOF to your program you should do a Ctrl+D under unix and I don't know if it's possible for windows. This may be the reason why the program never ends.

Does anyone think there is something wrong in The C Programming Language 2E Page29?

I am currently studying the well-known book for C - The C Programming Language, 2Ed. And when I trying the code in P.29, I think there is something wrong in the getline function:
int getline(char s[], int lim) {
int c, i;
for (i=0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; i++)
s[i] = c;
if (c == '\n') {
s[i] = c;
i++;
}
s[i] = '\0';
return i;
}
What if when the for loop ended, i == lim-1 and c == '\n'? In this case, I think the array would be out of boundary, since s[lim] would be set to '\0'.
Does anyone think this is wrong? Thanks for your help.
The && operator has "early-out" semantics. This means that if i == lim-1, the rest of the condition is not executed - in particular, c = getchar() will not be called.
This means that in this case, c will have its value from the last iteration of the loop - and since the loop condition includes c != '\n', this value can't be '\n' (or the loop would have exited last time around).
This is true as long as lim is greater than 1, which must be a precondition of the function (because calling the function with lim less than or equal to 1 would cause the uninitialised value of c to be read).
So, let's look at some cases:
If lim == 0:, then this will do undefined behavior. There's two places this will happen:
We will execute no iterations of the for loop, giving i == 0 and c == undefined.
We then access c at (c == '\n'). It has no defined value yet, so it's undefined behavior.
We then cause undefined behavior again by overflowing s with: s[i] = '\0';
What if lim == 1:
The for loop will not be run, because the condition is not met.
We will hit undefined behavior just like in lim == 0 because c has no value.
The last line will work fine.
What if lim == 2, and the input string is "ab":
The for loop will grab 'a', and place it into s.
The for loop will exit on the next iteration, with the value of c still being 'a'.
The if conditional fails.
The adding of the null character works fine.
So s == "a\0"
What if lim == 2 and the input string is "a\n" (Which is the case you're worried about):
The for loop will grab 'a', and place it into s.
The for loop will exit on the next iteration, with the value of c still being 'a'.
The if conditional fails.
The adding of the null character works fine.
So s == "a\0"
Loop will continue until the condition i < lim-1 is true.When i == lim - 1, condition for loop becomes false and loop will terminate, and last element of array will stored in s[lim -2].It will not go out of boundary.
I think you are correct. - but in a different way.
There may have been is a problem. Should the limit be reached i==lim-1, and c had the value \n from the previous loop - but this can not happen as the previous loop c!='\n' would have exited.
This is a problem with lim <=1. The for loop exits, and c is not intiialized yet, thus undefined behavior with if (c == '\n'). Could be fixed with
int c = 0;
As mentioned by others, there is an additional problem with lim = 0 and s[i] = '\0';
It isn't possible for i to be lim-1 and c to be '\n' at the same time. If i==lim-1, then i<lim-1 will be false, so it will never read the next character. If c was '\n', then the loop would have terminated before i got to be lim-1.
The loop is equivalent to this:
i=0;
while (i<lim-1) {
c = getchar();
if (c==EOF) break;
if (c=='\n') break;
s[i] = c;
i++;
}

Resources