This question already has answers here:
How do curly braces and scope wоrk in C?
(4 answers)
What does a 'for' loop without curly braces do?
(4 answers)
Closed 5 years ago.
The code won't work. The counting results of b(blank) and t(tab) are both 0. I think there maybe the issue with my condition set up. Can anyone help?
main()
{
int c, b, t, nl;
nl = 0;
b = 0;
t = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
if (c == ' ')
++b;
if (c == ' ')
++t;
printf("%d\t%d\t%d\n", nl, b, t);
}
The code as posted by you is equivalent to:
main()
{
int c, b, t, nl;
nl = 0;
b = 0;
t = 0;
while ((c = getchar()) != EOF) //your code is equivalent to this
{
if (c == '\n')
++nl;
} //the following if conditions fall outside the loop
if (c == ' ')
++b;
if (c == '\t')//tab is represented by \t not by ' '
++t;
printf("%d\t%d\t%d\n", nl, b, t);
}
You need to add braces around your while loop i.e.
int main(void)
{
int c, b, t, nl;
nl = 0;
b = 0;
t = 0;
while ((c = getchar()) != EOF){
if (c == '\n')
++nl;
if (c == ' ')
++b;
if (c == '\t')
++t;
}
printf("%d\t%d\t%d\n", nl, b, t);
return 0;
}
Another important thing: main() is not standard C
how does int main() and void main() work
Two spaces is not char, it is string.
Try this:
if(c == ' ')
b++;
if(c == '\t')
t++;
if(c == '\n')
nl++;
Related
I'm reading The C Programming Language.
I have used this program to replace multiple blanks to single blanks but I want to replace multiple blanks and tabs into single blank and tab in same time
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
if (c == ' ') {
putchar(c);
while ((c = getchar()) == ' ')
;
}
if (c != ' ')
putchar(c);
}
}
Your program is almost correct: there is a problem if the file ends with a space as the inner loop while ((c = getchar()) == ' '); will stop and the end of file leaving c with the value EOF, which will be output as the byte 0xFF (if EOF is defined as -1, the most common value).
You should check for this possibility:
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
if (c == ' ') {
putchar(c);
while ((c = getchar()) == ' ')
continue;
if (c != EOF)
break;
}
putchar(c);
}
return 0;
}
It is unclear what you mean by replace multiple blanks and tabs into single blank and tab.
To replace both spaces and TABs with a single space, you just need to test both byte values:
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t') {
putchar(' ');
while ((c = getchar()) == ' ' || c == '\t')
continue;
if (c != EOF)
break;
}
putchar(c);
}
return 0;
}
Conversely, if you mean to replace multiple spaces with a single space and multiple TABs with a single TAB, a different approach can be used:
#include <stdio.h>
int main() {
int c, last = EOF;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t') {
if (c == last)
continue;
}
putchar(c);
last = c;
}
return 0;
}
This approach can be used for the original problem and produces simpler code:
#include <stdio.h>
int main() {
int c, last = EOF;
while ((c = getchar()) != EOF) {
if (c != ' ' || c != last) {
putchar(c);
last = c;
}
}
return 0;
}
This question already has answers here:
End of File (EOF) in C
(3 answers)
Closed 3 years ago.
I am testing out code from the book "The C programming Language" and I would like to know what is the value of EOF and how can I find it out? I tried referencing the value with a pointer of some kind but I just get a const pointer error. In anywise, below is my code and I would like to know why is there no output upon clicking enter:
#include <stdio.h>
#define IN 1 /*inside a word*/
#define OUT 0 /*outside a word*/
/* count lines, words, and characters in input*/
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if (c == '/n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT){
state = IN;
++nw;
}
}
printf("%D %D %D\n", nl, nw, nc);
}
#include <stdio.h>
#define IN 1 /*inside a word*/
#define OUT 0 /*outside a word*/
/* count lines, words, and characters in input*/
int main(void)
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF){
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT){
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
printf("EOF = %d\n", EOF);
return 0;
}
I am new to programming, and I have decided to start with c. I am using the book of K & R, and there is this exercise, which asks to write a program that copies input to output , replacing one or more blanks with a single blank. However when I wrote my program (and I am sure it's not correct but that's okay, since I am here to learn) I was wondering what I am doing wrong. Also a note: when I type my name with 3 blanks it's reduced to two, but when using two or one blank(s) nothing happens. Code posted below
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int c; // getchar value
int blanks = 0; // counting the amount of blanks. If more than one then replace with blanks_2
char blanks_2 = ' '; //character value for replacement in case blanks is more than one
printf("Enter your name please\n");
while((c = getchar()) != EOF){
if(c == ' '){
++blanks;
if (blanks >= 1){
putchar(blankos); }
}
if(c >= 'a' && c <= 'z'){
putchar(c);
}
if (c >= 'A' && c <= 'Z'){
putchar(c);
}
}
return 0;
}
You do not need to count the exact number of blanks. Once you find a blank "raise a flag" that blank is found. When you revisit a non-blank character print a blank and turn the flag back to 0. Moreover, insert "continue" statements in your code to avoid unecessary checks:
int main(void)
{
int c; // getchar value
int blankfound = 0;
printf("Enter your name please\n");
while((c = getchar()) != EOF){
if(c == ' '){
blankfound = 1;
continue;
}
if(c >= 'a' && c <= 'z'){
if (blankfound == 1)
{
putchar(' ');
blankfound = 0;
}
putchar(c);
continue;
}
if (c >= 'A' && c <= 'Z'){
if (blankfound == 1)
{
putchar(' ');
blankfound = 0;
}
putchar(c);
continue;
}
}
return 0;
}
I guess you are trying to write a program that get something like this as input:
John David Doe
and display this as output:
John David Doe
by removing all extra spaces. This should work:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int c; // getchar value
int blanks = 0; // counting the amount of blanks. If more than one then replace with blanks_2
printf("Enter your name please\n");
while((c = getchar()) != EOF)
{
if(c == ' ')
{
// count blanks
++blanks;
if (blanks==1)
putchar(c); // display only the 1st blank
}
if(isalpha(c))
{
putchar(c);
blanks=0; // reset blanks counter as c is an alpha character
}
}
return 0;
}
Many of these learner code assignments work on the idea of function based on a previous character.
Consider the following layout
int previous = something();
while ((c = getchar()) != EOF) {
do_stuff(previous, c);
previous = c;
}
For OP, that would be: If the character is not a space or the previous character was not a space, print it.
printf("Enter your name please\n");
int previous = 0;
int c;
while((c = getchar()) != EOF) {
if ((c != ' ') || (previous != ' ')) {
putchar(' ');
}
previous = c;
}
Simplifying the algorithm helps one see flaws like below. blanks is not reset when a letter appears. It prints when 1 or more spaces encountered.
if(c == ' '){
++blanks;
if (blanks >= 1){
putchar(blankos); }
}
if(c >= 'a' && c <= 'z'){
putchar(c);
}
if (c >= 'A' && c <= 'Z'){
putchar(c);
}
Reference to previous chapters (Used only 'while' and 'if'), my code look like this.
#include <stdio.h>
main()
{
int c;
while ((c = getchar()) != EOF) {
if (c == ' ') {
putchar(c);
while ((c = getchar()) == ' ')
;
}
putchar(c);
}
}
--beware of horrible newbie code ahead--
I'm trying to rewrite this simple counting program from while to for.
int c, nc;
nc = 0;
while ((c = getchar()) != EOF) {
if (c != '\n')
++nc;
}
}
printf("%d\n", nc);
this outputs example->8.
so far I tried this couple of examples:
int c, nc;
for (nc = 0; ((c = getchar()) != EOF && (c = getchar()) != '\n'); ++nc)
;
printf("%d", nc);
and
int nc;
for (nc = 0; getchar() != EOF; ++nc)
if (getchar() == '\n')
--nc;
printf("%d", nc);
both this attempts lead to strange output like example->3 or a->0, also the program doesn't "wait" anymore for a break after receiving its input, it just shows the output and close itself.
I would like to know what's happening here, because as I see it I just inserted (quite clumsily.. ) an if check and can't seem to explain what's happening..
You are calling getchar() twice
for (nc = 0; getchar() != EOF; ++nc)
if (getchar() == '\n')
--nc;
printf("%d", nc);
try this instead
int chr;
int nc;
chr = fgetc(stdin);
for (nc = 0 ; chr != EOF ; nc += (chr == '\n') ? 0 : 1)
chr = fgetc(stdin);
printf("%d\n", nc);
getchar() which is equivalent to fgetc(stdin) reads a character from the input stream stdin, once you read that character you have to process it because it's removed from the stream, so calling the function twice will remove two characters from stdin and hence your count will be wrong.
So it doesn't matter how you write the for loop, what is important is to call getchar() once per iteration, for example this could work
int chr;
int nc;
for (nc = 0 ; ((chr = fgetc(stdin)) != EOF) ; nc += (chr == '\n') ? 0 : 1);
printf("%d\n", nc);
or this
int chr;
int nc;
for (nc = 0 ; ((chr = fgetc(stdin)) != EOF) ; )
{
if (chr != '\n')
nc += 1;
}
printf("%d\n", nc);
note that x = (condition) ? value : another_value is called the ternary operator, and is equivalent to
if (condition)
x = value;
else
x = another_value;
This is one equivalent way, although I'm not really happy about having to initialize c to \n. (the reason for this is that the get_char is performed in the post step:
int c, nc;
for (c = '\n', nc = 0; c != EOF; c = getchar()) {
if (c != '\n')
++nc;
}
}
printf("%d\n", nc);
Another way is:
int c, nc;
c = getchar();
for (nc = 0; c != EOF; c = getchar()) {
if (c != '\n')
++nc;
}
}
printf("%d\n", nc);
It can be done as shown below
int nc=0;
char ch;
for (; (ch =getchar()) != EOF; )
{
if (ch != '\n')
nc++;
}
printf("Count = %d\n",nc);
The initialization and increment are not mandatory they can be skipped as shown in the above code.So by doing this we are achieving the same as we do with your while() loop
Just a quick question; I've been working through K&R and the code for the digit/whitespace/other counter works fine. However, whilst trying to get my head round the functionality of else I've encountered something which doesn't work as expected.
The code from the book is as follows:
#include <stdio.h>
/* count digits, white space, others */
main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf("digits =");
for (i = 0; i < 10; ++i)
printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
}
If I then modify the while loop so it reads:
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
It should still have the same functionality as the original code except for the fact it won't count 'other' characters. However what I actually get is in fact just the 'digit' part working, with 'nwhite' returning zero no matter what the input. I feel the disparity is perhaps due to a fundamental misunderstanding of how if statements function.
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
The second if statement is no longer in the loop. Use { and } to enclose the loop statements.
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
Is equivalent to
while ((c = getchar()) != EOF) {
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
}
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
Only the first statement that follows a looping or branch construct "belongs" to that construct. That is why the original if-else if-else chain works without braces. Each statement chains to the previous with the first if/else statement belonging to the while loop and the second if/else belonging to the first if/else. It is idiomatic to express the logic this way to avoid unnecessary indenting.
It may help to visualize the code with braces
while ((c = getchar()) != EOF) {
if (c >= '0' && c <= '9') {
++ndigit[c-'0'];
}
else {
if (c == ' ' || c == '\n' || c == '\t') {
++nwhite;
}
else {
++nother;
}
}
}