what is wrong with the while loop here ? C basics - c

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

Related

Is it correct to use a do-while loop inside a for loop? Why and why not?

//program to count words
#include<stdio.h>
int main()
{
int i;
int word = 0;
char sent[] = "How are you doing mister"; //character pointer
for (i = 0; sent[i] != '\0'; i++)
{
do
{
word++;
} while (sent[i] == ' ');
}
printf("There are %d words in the sentence\n", word + 1); //words are always 1 more than the no. of spaces.
return 0; //or word=1;
}
This is a code for counting the number of words. Please tell me why cannot we use do-while loops inside a for loop. Or if we can, how to do it.
Nesting the various composite statements such as for and do/while is allowed in C at least up to 127 levels, as specified in 5.2.4.1 Translation limits.
The problem is not a syntax issue, but rather a conceptual one:
your do/while loop iterates on a constant condition as neither i, nor sent is modified in the body or in the condition of the loop, leading to an infinite loop if sent[i] is a space.
counting spaces is not a correct approach to counting words in a string: "" has 0 words, not 1 per your intended code, " " also but you would get 2 and "A B" only has 2 words, not 3.
you should count the number of transitions from space to non space, starting with an implicit space before the beginning of the string.
note also that char sent[] = "..."; is not a character pointer, but a character array.
Here is a modified version:
//program to count words
#include <stdio.h>
int main() {
int i, words, last;
char sent[] = "How are you doing mister?";
words = 0;
last = ' ';
for (i = 0; sent[i] != '\0'; i++) {
if (sent[i] != ' ' && last == ' ')
word++;
last = sent[i];
}
printf("There are %d words in the sentence '%s'\n", words, sent);
return 0;
}
In my experience proof reading code, do/while loops tend to be written incorrectly, especially by beginners, missing test conditions or broken in some other way. I you think a do/while loop solves a given problem, think again, a for loop might be a safer approach. The only place do/while loops are needed is in a macro expansion where you want to combine multiple statements into a single compound statement:
#define swap_ints(a, b) do { a ^= b; b ^= a; a ^= b; } while (0)
Note however that the swapping method in this macro is inefficient and macros are very error prone and should be avoided even more than do/while loops :)
It is completely valid to nest a do-while loop within a for loop. Syntactically, there is nothing wrong with your program.
However, as others have described, your nested loop will never terminate when sent[i] == ' '. Your program has bugs, but they have nothing to do with the validity of nesting loops.

C program to count number of n-letter words in a text stuck in nested while loop

I'm getting back into coding after quite a few years out of school and I'm stuck trying to write a program in C that counts how many n-letter words are in a text, storing them into a length n array and then printing them. To keep is simple, I've assumed n is b/w 1 and 10 and each word is seperated by exactly one space.
Here's the code, However, it seems my program never gets out of the inner while loop so nothing is printed on the screen. I tried printing something at the end of that loop to test it and for some reason the program prints it as many times as there are characters (including spaces, which the inner while condition should catch and exit). Am I overlooking something here?
main()
{
int c, i, j, counter;
counter = 0;
int wlength [10];
for (i=0; i<10; ++i) //initialize array
wlength[i]=0;
while((c=getchar())!=EOF){ // keep taking input until end of file
while (c!=' '){ //keep counting until you reach the end of the word
++counter;
c=getchar();
}
wlength [counter-1]++; //increment the counter for that word length
counter=0 ; //reset the counter for the next word
}
for (j=0;j<10;++j) //print the array
printf("%d ", wlength[j]);
You have two loops reading standard input, and only one checks for EOF. So your program reads the file and gets stuck if there isn't exactly a space before the end of the file.
You would be better off with only one loop, replacing the other by an if - else statement :
Pseudo-code :
while ( getchar and !EOF )
{
if ( char isn't a space )
{
increment counter
} else {
increment value for given length
set first counter to 0
}
}
You should also check that you're in the bounds of your array... Words like 'expotentially` exist ;-)
The problem is the inner while loop. Because in unix or unix-like system. At the end of each line is \n. so your code is blocked in the first inner loop. you need to add more check on that. The test condition should change to:
while(c != ' ' && c != '\n'){
++counter;
c=getchar();
}
And I ran that, it worked.

Reverse of a string in C program?

I found this program for reversing this program online.
I have just started learning C.
I am not able to understand few things here.
Why while is ended with ;
what does while(str[++i]!='\0'); mean?
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
This is the program:
#include<stdio.h>
int main(){
char str[50];
char rev[50];
int i=-1,j=0;
printf("Enter any string : ");
scanf("%s",str);
while(str[++i]!='\0');
while(i>=0)
rev[j++] = str[--i];
rev[j]='\0';
printf("Reverse of string is : %s",rev);
return 0;
}
while(str[++i]!='\0');
is equivalent to
while(str[++i]!='\0')
/*do nothing*/;
which is equivalent to
++i;
while (str[i]!='\0') {
++i;
}
and
while(i>=0)
rev[j++] = str[--i];
is equivalent to
while (i>=0) {
--i;
rev[j] = str[i];
++j;
}
Note that i is decremented before the statement since --i is a pre-decrement, whereas j is incremented after the statement since j++ is a post-increment.
I'll try to answer as best as i can...
Why while is ended with ;
This is valid syntax, it's often used to cause the program to wait at that line until a certain flag is set in an embedded scenario. In this case it's used to find the length of the string.
All strings are terminated with a null character, which is '\0', and the preincrement on i means that after that line i will hold the value for the length of the string.
Effectively its equivalent to this:
/* If the ith position of the string is not the end */
while (str[i] != '\0') {
/* Increment i and repeat */
i = i + 1;
}
The main concept here is the difference between postincrement and preincrement operators - might be worth reading up on that.
What does while(str[++i]!='\0'); mean?
See above.
3.Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
If you're asking if its in the while loop, its entirely equivelant to:
while(i>=0) {
rev[j++] = str[i--];
}
Since there is only a single operation in the while loop the brackets aren't needed.
Just a note, and this is entirely subjective, but the majority of coding standards I've come accross use brackets even in this scenario.
Your questions seem to be related mainly to the syntax of C - it might be worth getting a book out or watching some tutorials to familiarise yourself with it.
The ; is there to close the loop
2: while(str[++i]!='\0'); means "Go throuch each char of str until the \0 char is reached".\0 is the ending char of a string
3: Yes
First of all, while(str[++i]!='\0'); increments i until it finds the last character. In C all strings end with \0 or NULL (both are the same).
The second one, no. It is not the same --i than i++.
Check the following code snipet:
int a,b,x=10,y=10;
a = x--;
b = --y;
At the end of execution, a = 10 but b = 9. This is because --y is a pre-decrement. It decrements the value first and then assigns its value to b.
Here's a commented version of the program:
// Include standard input output functions
#include<stdio.h>
// declares the main function. It accept an undefined number
// of parameters but it does not handles them, and returns an integer
int main(){
// declares tho arrays of 50 characters initialized with random values
char str[50];
char rev[50];
// declare and initialize two integer variables
int i=-1,j=0;
printf("Enter any string : ");
scanf("%s",str);
// executes the ';' instruction while the condition is satisfied.
// ';' is an empty statement. Thus do nothing.
// The only action executes here, is the increment of the i variable with
// a preincrement. Because the i variable was initialized with
// -1, the first control start checking if str[0] != '\0'
// If the post increment operator was used, the variable must
// have been initialized with 0 to have the same behaviour.
while(str[++i]!='\0');
// at the end of the previous while, the i variable holds the
// str lenght + 1 (including the '\0')
// starting from the end (excluding the '\0', using the pre-decrement on the i variable)
// assign to rev[j] the variable of str[i], then (post increment)
// increment the j variable
while(i>=0)
rev[j++] = str[--i];
// now j is equals to str lenth +1
// therefore in this position add the null byte
rev[j]='\0';
// print result
printf("Reverse of string is : %s",rev);
// return 0 to the OS
return 0;
}
; means the end of a statement in c.
while(condition)
{
//do something
}
do something means at least one statement should be executed. For this the ; is used here.
while(str[++i]!='\0'); '\0' represents end of the string. Here the loop is terminated at the end of the string and ++i increases i.
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
Yes. But as --i increases i before executing rev[j++] = str[--i] so i-- should be before rev[j] = str[i] and j++ increases j after executing rev[j++] = str[--i] so j++ should be after rev[j] = str[i]
The key here is understanding the difference in behaviour between prefix (++i), and postfix (i--) operators.
The prefix operator will increment its operand (i), and then evaluate to the new value.
The postfix operator will evaluate to its operands current value, and then increments the operand afterwards.
As for:
int i = -1;
while (str[++i] != '\0');
This is a loop with no block, because all of the statements can be expressed in the conditional. On each iteration:
Increment i by one.
Get the char at the position i evaluates to.
continue if it is not the NUL character.
This might be better understood when written as:
int i = -1;
do {
i++;
} while (str[i] != '\0');
The result of this operation is that i now holds the position of the NUL character in the string, since all valid character strings must end with the NUL character.
In the next section of the program, the prefix operator is used again to immediately get the character one position before the NUL character, and then one position before that, and so on, until we get the first character of the string, and then we're done.
while(i>=0)
rev[j++] = str[--i];
Why while is ended:
while(str[++i]!='\0')
Once str is an asciiz string it ends with a '\0' character. So while will end whenever the while reaches the end of the string.
The line above means:
=> ++i : Increments the string index before getting the corresponding character.
=> Checks if str[index] != '\0' // End of the string reached
On the end of while the i variable will contain the string length (excluding the '\0' character).
It would be easier to use this:
i = strlen(str);
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
No.
This line is the same as:
while(i>=0)
{
i = i - 1;
rev[j] = str[i];
j = j + 1;
}
--i : Gets the string character after decrementing i.
If you changed to i-- the code would get the str[i] before decrementing i, but it is not what you want.

what is wrong with my understanding of strings ie character arrays ending with '\0' element in C programming

I am a total beginner and recently started studying strings in C programming.
I understand that we need to supply the '\0' (null) character at the end of the string (to act as a end of string marker).
So if my character array is
char string[]={'H','E','L','L','O','\0'};
This makes it a 6 element array.
So I was going through this simple example of copying one string to another string. Here is the code.
#include<stdio.h>
int main()
{
char string1[80],string2[80];
int i;
printf("Enter a string \n");
gets(string2);
for(i=0; string2[i]!= '\0';i++)
{
string1[i]=string2[i];
}
string1[i]='\0'; /*here is my problem*/
printf("The copied string is \n");
printf("%s",string1);
printf("\n");
printf("The number of character are \t");
printf("%d \n",i);
}
why isn't it string1[i+1]='\0'??
I mean, isn't by putting string1[i]='\0' overwrite the last element that was just stored in the above for loop?
The code is correct, because of the way the for loop works:
for(A; B; C)
CODE;
Is equivalent to:
A;
while (B)
{
CODE;
C;
}
(Except for the use of continue, that will jump to the increment expression, not the condition, as it would happen with a while).
And since the loop ends when string2[i] != '\0', it is obvious that upon exiting, i is the index for the proper NUL byte. So after that:
string1[i] = '\0';
will write the \0 at the same place as it is in string2.
Usually for this kind of analysis it is helpful to think about preconditions and postconditions. That is, assuming there are no break and no goto, you are guaranteed that at the beginning of a for or while loop the condition is always true. And just after the end of a for or while loop the condition is always false.
Your particular code, illustrated with assert calls:
for(i=0; string2[i] != '\0'; i++)
{
asssert(string2[i] != '\0');
string1[i] = string2[i];
}
asssert(string2[i] == '\0');
string1[i] = '\0';
Looking at the code, it seems as if i is incremented as long as the character is not '\0'. So, the last time it's incremented, it increments to a new position that hasn't had a character written to it yet.
So, at the end of the loop, there's a space to write the null character to.

How does this clean up the empty space in an array?

void empty_spaces(char array[]){
int j=0,i=0,n=0;
n=strlen(array);
while(i<n){
if(array[i]==' '){
j=i;
while(j<n){
array[j]=array[j+1];
++j;
}
--n;
}else
++i;
}
if(n>15)
n=15;
array[n]='\0';
}
Could someone explain me, this code? This function cleans up the empty spaces in array, but could someone explain me exactly what it works?
It's a rather flabby attempt at a function that removes spaces from a string. The problem with the code is that it has gratuitous iteration and it turns an O(n) algorithm into an O(n^2) algorithm.
Rather than trying to understand the code you have I feel it is best to do it the efficient and simple way. Like this.
void empty_spaces(char str[])
{
char *src = str;
char *dst = str;
while (*src)
{
if (*src != ' ')
{
*dst = *src;
dst++;
}
src++;
}
*dst = '\0';
}
We perform a single pass across the string with two pointers, src and dst. When a non-space character is encountered it is copied from source to destination. Maintaining two separate pointers into the array avoids the spurious iteration from your code.
I ignored the n>15 part of your code. The effect of that is that the string is always truncated to have length no greater than 15 characters, but quite why that would be done is mysterious to me. It surely shouldn't be mixed up in this function.
Since I've not really answered the question as asked, but since I hope this is useful to you, I have made the answer community wiki.
A rewritten and commented version of the above:
//....
n = strlen(array); // n is the number of characters in the array up to the final 0
while (i < n) {
if (array[i] != ' ') { // not a space
i++; // next char,
continue; // continue
}
j = i; // j is the current array index
while (j < n) { // while there are chars left...
array[j] = array[j+1]; // copy the next character into the current index
j++;
}
n--; // and remove one from the string len since a space is removed
}
The code after that limits the string length to 15 before returning.
So this code removes spaces and possibly truncates the string to 15 chars only.
It loops over every character in the array, removing all ' ' (space) characters. The inner loop is what does the erasing. When the outer loop finds a space character, the inner loop "shifts" the rest of the array to the left one index, overwriting the space.
Basically, as soon as the loop encounters ' ' character (space), it moves all the elements of array one place ' left ', therefore replacing the space with the following character.

Resources