The C Programming Language K&R exercise 1- 9 - c

I'm new on here and relatively new to programming logic in general. In an effort to develop my skill I've begun reading this fine piece of literature. I really feel that I am grasping the concepts well but this exercise seems to have caught me off guard. I can produce the program but some of the examples I've seen seem to introduce some concepts not yet covered by the book like the examples here. inspace seems to be serving a function that is more than just a variable created by the programmer.
#include <stdio.h>
int main(void)
{
int c;
int inspace;
inspace = 0;
while((c = getchar()) != EOF)
{
if(c == ' ')
{
if(inspace == 0)
{
inspace = 1;
putchar(c);
}
}
/* We haven't met 'else' yet, so we have to be a little clumsy */
if(c != ' ')
{
inspace = 0;
putchar(c);
}
}
return 0;
}
In the next example, pc seems to be doing something in regards to counting spaces but I'm not sure what.
I managed to create a program that completes this task but it was using only the variable c that I created, thus I understand its purpose.

The objective of this code is copy text and if there is more then one spaces ' ' consecutive print only one space.
Variable inspace is used to keep track of whether last time printed char was scape or non-space.
if inspace is zero means a char was printed that was not space. and
if inspace is one means a last time space was printed.
So if inspace is zero next time scape can be printed on reading a scape, and if inspace is one then next consecutive scape found so not to print space.
See C is current char read. (read comments)
if(c == ' ') // currently space read
{
if(inspace == 0) // last time non-space printed, So space can be print
{
inspace = 1; // printing space so switch inspace 1
putchar(c); // print space
}
}
Next if
if(c != ' ') // A char not space read, its to to print unconditionally
{
inspace = 0; // remember that non-scape print
putchar(c);
}

Took me a while but this is the answer I think.
#include <stdio.h>
main()
{
int c, blank;
blank = 0;
while ((c=getchar()) != EOF){
if (c == ' '){
if (blank == 0){
printf("%c", c);
blank = 1;
}
}
if (c != ' '){
if (blank == 1){
blank = 0;
}
printf("%c", c);
}
}
}

inspace is essentially a variable to indicate you are or are not in the "just seen a space" state. You enter this state after seeing a space, and you exit this state when you see a non-space. You print your input only if you're not in the inspace state, thus you do not print multiple adjacent spaces.
I managed to create a program that completes this task but it was using only the variable c that I created, thus I understand its purpose.
In your program, if the input is "hello world", is that its exact output? The program you posted will output "hello world" (compressing the multiple spaces between the words down to one).

I was also having the same problem but finally got a program that works.
#include<stdio.h>
/* copy input to its output, replacing each
string of one or more blanks by a single blank */
int main()
{
int c, nspace=0;
while((c=getchar()) != EOF){
if(c==' ') ++nspace;
else{
if(nspace >= 1){
printf(" ");
putchar(c);
nspace=0;
}
else
putchar(c);
}
}
}

Related

Multiple blank lines are not squeezed in one blank line(C) using I/O redirection

I am asked to squeezed two or more consecutive blank lines in the input as one blank line in the output. So I have to use Cygwin to do I/O or test it.
Example: ./Lab < test1.txt > test2.txt
my code is:
int main(void){
format();
printf("\n");
return 0;
}
void format(){
int c;
size_t nlines = 1;
size_t nspace = 0;
int spaceCheck = ' ';
while (( c= getchar()) != EOF ){
/*TABS*/
if(c == '\t'){
c = ' ';
}
/*SPACES*/
if (c ==' '){/*changed from isspace(c) to c==' ' because isspace is true for spaces/tabs/newlines*/
/* while (isspace(c = getchar())); it counts while there is space we will put one space only */
if(nspace > 0){
continue;
}
else{
putchar(c);
nspace++;
nlines = 0;
}
}
/*NEW LINE*/
else if(c == '\n'){
if(nlines >0){
continue;
}
else{
putchar(c);
nlines++;
nspace = 0;
}
}
else{
putchar(c);
nspace = 0;
nlines = 0;
}
}
}
However my test2.txt doesn't have the result I want. Is there something wrong in my logic/code?
You provide too little code, the interesting part would be the loop around the code you posted...
What you actually have to do there is skipping the output:
FILE* file = ...;
char c, prev = 0;
while((c = fgets(file)) != EOF)
{
if(c != '\n' || prev != '\n')
putchar(c);
prev = c;
}
If we have an empty line following another one, then we encounter two subsequent newline characters, so both c and prev are equal to '\n', which is the situation we do not want to output c (the subsequent newline) – and the inverse situation is any one of both being unequal to '\n', as you see above – and only then you want to output your character...
Side note: prev = 0 – well, I need to initalise it to anything different than a newline, could as well have been 's' – unless, of course, you want to skip an initial empty line, too, then you would have to initialise it with '\n'...
Edit, referring to your modified code: Edit2 (removed references to code as it changed again)
As your modified code shows that you do not only want to condense blank lines, but whitespace, too, you first have to consider that you have two classes of white space, on one hand, the newlines, on the other, any others. So you have to differentiate appropriately.
I recommend now using some kind of state machine:
#define OTH 0
#define WS 1
#define NL1 2
#define NL2 3
int state = OTH;
while (( c= getchar()) != EOF )
{
// first, the new lines:
if(c == '\n')
{
if(state != NL2)
{
putchar('\n');
state = state == NL1 ? NL2 : NL1;
}
}
// then, any other whitespace
else if(isspace(c))
{
if(state != WS)
{
putchar(' ');
state = WS;
}
}
// finally, all remaining characters
else
{
putchar(c);
state = OTH;
}
}
First differentiation occurs to the current character's own class (newline, whitespace or other), second differentiation according to the previous character's class, which defines the current state. Output occurs always for any non-whitespace character or if the two subsequent whitespace characters only, if they are of different class (newline is a little specific, I need two states for, as we want to leave one blank line, which means we need two subsequent newline characters...).
Be aware: whitespace only lines do not apply as blank lines in above algorithm, so they won't be eliminated (but reduced to a line containing one single space). From the code you posted, I assume this is intended...
For completeness: This is a variant removing leading and trailing whitespace entirely and counting whitespace-only lines as empty lines:
if(c == '\n')
{
if(state != NL2)
{
putchar('\n');
state = state == NL1 ? NL2 : NL1;
}
}
else if(isspace(c))
{
if(state == OTH)
state = WS;
}
else
{
if(state == WS)
{
putchar('');
}
putchar(c);
state = OTH;
}
Secret: Only enter the whitespace state, if there was a non-ws character before, but print the space character not before you encounter the next non-whitespace.
Coming to the newlines - well, if there was a normal character, we are either in state OTH or WS, but none of the two NL states. If there was only whitespace on the line, the state is not modified, thus we remain in the corresponding NL state (1 or 2) and skip the line correspondingly...
To dissect this:
if(c == '\n') {
nlines++;
is nlines ever reset to zero?
if(nlines > 1){
c = '\n';
And what happens on the third \n in sequence? will nlines > 1 be true? Think about it!
}
}
putchar(c);
I don't get this: You unconditionally output your character anyways, defeating the whole purpose of checking whether it's a newline.
A correct solution would set a flag when c is a newline and not output anything. Then, when c is NOT a newline (else branch), output ONE newline if your flag is set and reset the flag. I leave the code writing to you now :)

printing a word per line

I need to write a program that prints its input one word per line. Here's what I got so far:
#include <stdio.h>
main(){
int c;
while ((c = getchar()) != EOF){
if (c != ' ' || c!='\n' || c!='\t')
printf("%c", c);
else
printf("\n");
}
}
The logic is pretty simple. I check to see if the input is not a newline, tab or space, and in that case it prints it, otherwise prints a newline.
When I run it, I get results like this:
input--> This is
output--> This is
It prints the whole thing. What goes wrong here?
if (c != ' ' || c!='\n' || c!='\t')
This will never be false.
Perhaps you meant:
if (c != ' ' && c!='\n' && c!='\t')
instead of using printf try putchar, also as per above comments, you should use && instead of ||.
here is my code-
#include<stdio.h>
main()
{
int c, nw; /* nw for word & c for character*/
while ( ( c = getchar() ) != EOF ){
if ( c != ' ' && c != '\n' && c != '\t')
nw = c;
else {
nw = '\n';
}
putchar (nw);
}
}
this code will give you the desired output
you can use if you want the strtok function in string.h library which can cut the input into many words by providing a delimiter.
Here is a perfect code commented which can fit to your needs
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char line[1000]=""; // the line that you will enter in the input
printf("Input the line:\n>>");
scanf("%[^\n]",line); // read the line till the you hit enter button
char *p=strtok(line," !#$%&'()*+,-./'"); // cut the line into words
// delimiter here are punctuation characters (blank)!#$%&'()*+,-./'
printf("\nThese are the words written in the line :\n");
printf("----------------------------------------\n");
while (p!=NULL) // a loop to extract the words one by one
{
printf("%s\n",p); // print each word
p=strtok(NULL," !#$%&'()*+,-./'"); // repeat till p is null
}
return 0;
}
If we execute the code above we will get
Input the line:
>>hello every body how are you !
These are the words written in the line :
----------------------------------------
hello
every
body
how
are
you
suggest the code implement a state machine,
where there are two states, in-a-word and not-in-a-word.
Also, there are numerous other characters that could be read
(I.E. ',' '.' '?' etc) that need to be check for.
the general logic:
state = not-in-a-word
output '\n'
get first char
loop until eof
if char is in range a...z or in range A...Z
then
output char
state = in-a-word
else if state == in-a-word
then
output '\n'
state = not-in-a-word
else
do nothing
end if
get next char
end loop
output '\n'
I think the simple solution would be like
#include <stdio.h>
int main(void) {
// your code goes here
int c;
while((c=getchar())!=EOF)
{
if(c==' ' || c=='\t' || c=='\b')
{
printf("\n");
while(c==' ' || c=='\t' || c=='\b')
c=getchar();
}
if(c!=EOF)
putchar(c);
}
return 0;
}

Why is this program yielding wrong output

This program is supposed to remove all comments from a C source code (in this case comments are considered double slashes '//' and a newline character '\n' and anything in between them, and also anything between '/* ' and '*/'.
The program:
#include <stdio.h>
/* This is a multi line comment
testing */
int main() {
int c;
while ((c = getchar()) != EOF)
{
if (c == '/') //Possible comment
{
c = getchar();
if (c == '/') // Single line comment
while (c = getchar()) //While there is a character and is not EOF
if (c == '\n') //If a space character is found, end of comment reached, end loop
break;
else if (c == '*') //Multi line comment
{
while (c = getchar()) //While there is a character and it is not EOF
{
if (c == '*' && getchar() == '/') //If c equals '*' and the next character equals '/', end of comment reached, end loop
break;
}
}
else putchar('/'); putchar(c); //If not comment, print '/' and the character next to it
}
else putchar(c); //if not comment, print character
}
}
After I use this source code as its own input, this is the output I get:
#include <stdio.h>
* This is a multi line comment
testing *
int main() {
int c;
while ((c = getchar()) != EOF)
{
if (c == '') ////////////////
{
c = getchar();
if (c == '') ////////////////////
while (c = getchar()) /////////////////////////////////////////
if (c == '\n') ///////////////////////////////////////////////////////////////
break;
else if (c == '*') ///////////////////
{
while (c = getchar()) ////////////////////////////////////////////
{
No more beyond this point. I'm compiling it using g++ on the ubuntu terminal.
As you can see, multi lines comments had only their '/' characters removed, while single line ones, had all their characters replaced by '/'. Apart from that, any '/' characters that were NOT the beginning of a new comment were also removed, as in the line if (c == ''), which was supposed to be if (c == '/').
Does anybody know why? thanks.
C does not take notice of the way you indent your code. It only cares about its own grammar.
Look carefully at your elses and think about which if they attach to (hint: the closest open one).
There are other bugs, as well. EOF is not 0, so only the first while is correct. And what happens if the comment looks like this: /* something **/?
You have some (apparent) logic errors...
1.
while (c = getchar()) //While there is a character and is not EOF
You're assuming that EOF == 0. Why not be explicit and change the preceding line to:
while((c = getchar()) != EOF)
2.
else putchar('/'); putchar(c);
Are both of the putchars supposed to be part of the else clause? If so, you need braces {} around the two putchar statements. Also, give each putchar its own line; it not only looks nicer but it's more readable.
Conclusion
Other than what I've mentioned, your logic looks sound.
As already mentioned, the if/else matching is incorrect. One aditional missing functionality is that you must make it more stateful to keep track of whether you are inside a string or not, e.g.
printf("This is not // a comment\n");

K&R answer 1-12 (using functions to reduce the number of lines of code)

I have written the following program to answer Kernighan and Ritchies ch1 problem 12.
The issue is that I have never really understood how to properly use functions and would like to know why the one I wrote into this program, getcharc(), does not work?
What are good resources that explain correct function usage. Where? and How?
I know the optimal solution to this problem from Richard Heathfield's site (which uses || or, rather than nested while statements, which I have used), however I would like to know how to make my program work properly:
#include <stdio.h>
int getcharc ();
// Exercise 1-12
// Copy input to output, one word per line
// words deleniated by tab, backspace, \ and space
int main()
{
int c;
while ((c = getchar()) != EOF) {
while ( c == '\t') {
getcharc(c);
}
while ( c == '\b') {
getcharc(c);
}
while ( c == '\\') {
getcharc(c);
}
while ( c == ' ') {
getcharc(c);
}
putchar(c);
}
}
int getcharc ()
{
int c;
c = getchar();
printf("\n");
return 0;
}
The original program (and I know it has bugs), without the function was:
#include <stdio.h>
// Exercise 1-12
// Copy input to output, one word per line
// words deleniated by tab, backspace, \ and space
int main()
{
int c;
while ((c = getchar()) != EOF) {
while ( c == '\t') {
c = getchar();
printf("\n");
}
while ( c == '\b') {
c = getchar();
printf("\n");
}
while ( c == '\\') {
c = getchar();
printf("\n");
}
while ( c == ' ') {
c = getchar();
printf("\n");
}
putchar(c);
}
}
So all I am trying to do with the function is to stop
c = getchar();
printf("\n");
being repeated every time.
What, exactly, is this getcharc() function supposed to do? What it does, is read a character from input, print a newline, and return zero. The character just read from input is discarded, because you didn't do anything with it. When it's called, the return value is ignored as well. In each of the places where it is called, you're calling it in an infinite loop, because there's no provision made for changing the loop control variable.
Perhaps you were intending something like c = getcharc(), but that wouldn't really help because you aren't returning c from the function, anyway. (Well, it would help with the "infinite loop" part, anyway.)
What's the point of this function anyway? If you just use getchar() correctly in its place, it looks like you'd have your solution, barring a few other bugs.
One of the possible solution is, change prototype for your function to int getcharc (int c, int flag).
Now your code after some modification;
#include <stdio.h>
int getcharc (int c, int flag);
// Exercise 1-12
// Copy input to output, one word per line
// words deleniated by tab, backspace, \ and space
int main()
{
int c;
int flag = 0; //to keep track of repeated newline chars.
while ((c = getchar()) != '\n') {
flag = getcharc(c, flag); // call getcharc() for each char in the input string. Testing for newline and printing of chars be done in the getcharc() function
}
return 0;
}
int getcharc (int c, int flag)
{
if( (c == ' ' || c == '\t' || c == '\b' || c== '\\') && flag == 0)
{
printf("\n");
flag = 1;
}
else
{
if(c != ' ' && c != '\t' && c != '\b' && c!= '\\')
{
putchar(c);
flag = 0;
}
}
return flag;
}
EDIT:
but I wanted to keep the nested while statements rather than using || or
Your nested while loop is executing only once for each character as grtchar() reads one character at one time. No need of nested loops here! You can check it by replacing while to if and your code will give the same output for a given string. See the output here.
know the optimal solution to this problem from Richard Heathfield's site (which uses || or, rather than nested while statements, which I have used), however I would like to know how to make my program work properly:
You make your program work to some extent (with your bugs) by adding an if condition and a break statement as;
#include <stdio.h>
int getcharc (int c);
int main()
{
int c;
while ((c = getchar()) != '\n') {
while ( c == '\t') {
c = getcharc(c);
if(c != '\t')
break;
}
....
....
while ( c == ' ') {
c = getcharc(c);
if(c != ' ')
break;
}
putchar(c);
}
return 0;
}
int getcharc (int c)
{
c = getchar();
printf("\n");
return c;
}
// compiled by my brain muhahaha
#include <stdio.h>
int getcharc(); // we prototype getcharc without an argument
int main()
{
int c; // we declare c
// read character from stdio, if end of file quit, store read character in c
while ((c = getchar()) != EOF) {
// if c is tab \t call function getcharc() until forever since c never changes
while ( c == '\t') {
getcharc(c); // we call function getcharc with an argument
// however getcharc doesn't take an argument according to the prototype
}
// if c is \b call function getcharc() until forever since c never changes
while ( c == '\b') {
getcharc(c);
}
// if c is \\ call function getcharc() until forever since c never changes
while ( c == '\\') {
getcharc(c);
}
// if c is ' ' call function getcharc() until forever since c never changes
while ( c == ' ') {
getcharc(c);
}
// since we never will get here but if we happened to get here by some
// strange influence of some rare cosmic phenomena print out c
putchar(c);
}
}
// getcharc doesn't take an argument
int getcharc ()
{
int c; // we declare another c
c = getchar(); // we read from the keyboard a character
printf("\n"); // we print a newline
return 0; // we return 0 which anyway will never be read by anyone
}
maybe you are getting confused with the old K&R
nowadays when you write a function argument you specify it like
int getcharch(int c)
{
...
}

C Program that counts Words and Lines in Standard input

I am new to C programming and I am currently trying to teach myself how to create a C program that can count words and lines in the input stream and print the two totals to the standard output.
What I am actually trying to do is to have the program count the number of lines and count the number of words depending on the definition of a word in which I feel that I am off.
I want the words to exclude blanks, tabs, newlines, hyphens, or colons. While having the program output the results (words and lines) as decimals.
#include<stdio.h>
int main()
{
int iochar;
int words;
int lines;
printf("Enter something here:\n\n");
while ((iochar = getchar ()) !=EOF)
{
if((iochar == ' ') || (iochar == '\t') || (iochar == '\n'))
putchar(iochar);
}
return 0;
}
Am I totally off on this program?
If your question is how to fix the compile error, that's simple. Add one more closing brace at the end.
But your program will still do only one pass through the loop and will print only one character if and only if the user types a space, tab or newline. No matter what the user types, the program will then terminate. I doubt that's what you wanted.
I suspect this is what you intended:
while ((iochar = getchar ()) !=EOF)
{
if((iochar == ' ') || (iochar == '\t') || (iochar == '\n'))
{
putchar(iochar);
}
}
return 0;
After your "I am trying to have thee numbers be right justified in an 8-column field ..." I cannot understand what you are trying to say :(
int words = 0;
int lines = 0;
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
lines++;
if(buffer[0] == '\n')
continue;
char *tmp = buffer-1;
while(tmp = strchr(tmp+1, ' '))
words++;
words++; /* count last word before \0*/
}
printf("lines: %d, words: %d\n", lines, words);
is that what you need/want?
The error message is:
Test.c:20:1: error: expected declaration or statement at end of input
It does not compile because you are missing a }.
Had you properly indented your code, like so, you would have found your mistake:
#include<stdio.h>
int main() {
int iochar;
int words;
int lines;
printf("Enter something here:\n\n");
while ((iochar = getchar ()) !=EOF)
{
if((iochar==' ')||(iochar=='\t')||(iochar=='\n'))
{
putchar(iochar);
iochar = getchar();
}
return 0;
}
Yet another example of the importance of readability :)

Resources