Program task -
Enter a string, display it word for word on the screen.
The problem is that if you type a lot of spaces between words, they will show up when you check. How can this be fixed?
#include <stdio.h>
int main()
{
int inw = 0, i = 0, count = 0;
char s[10000];
printf("Print string (max 10000 sb):\n");
gets(s);
while (s[i] != '\0') {
if (s[i] != ' ' && s[i] != '\t') {
putchar(s[i]);
}
else if (s[i] == ' ') {
printf("\n");
}
i++;
}
return 0;
}
Ugly, but this gets the job done. Just need a flag to keep track of whether or not you just printed a new line. Also cleaned up unused variables and changed to using fgets
#include <stdio.h>
#include <stdbool.h>
int main()
{
int i = 0;
char s[10000];
bool justPrintedNewline = false;
printf("Print string (max 10000 sb):\n");
fgets(s, sizeof s, stdin);
while (s[i] != '\0') {
if (s[i] != ' ' && s[i] != '\t') {
putchar(s[i]);
justPrintedNewline = false;
}
else if (s[i] == ' ' && justPrintedNewline == false) {
printf("\n");
justPrintedNewline = true;
}
i++;
}
return 0;
}
Demo
You did a great job in the algorithm just fix a little thing.
You can create a flag and after space you increase the flag to 1.
Then you will know you will print just one space.
After printing " " check for a char that isn't " " for update the flag to 0.
When the flag is 1 DONT print anything just wait for another valid char.
Take care,
Ori
Only print a line-feeed when starting a word and after all is done.
Change code to:
If a space
-- print a '\n' when the prior character is a non-white-space.
Else
-- if (prior character is white-space) print a '\n'
-- print it
char prior = 'a';
while (s[i]) {
char ch = s[i];
if (ch != ' ' && ch != '\t') {
if (prior == ' ' || prior == '\t') {
putchar('\n');
}
putchar(ch);
}
prior = ch;
i++;
}
putchar('\n');
There is a bit of a trick to it: use a second, inside loop to skip past spaces and another to print words. The outer loop should only terminate if you have reached the end of the string.
while (s[i] != '\0')
{
// skip all spaces
while ((s[i] != '\0') && isspace( s[i] )) ++i;
// print the word
while ((s[i] != '\0') && !isspace( s[i] ))
{
putchar( s[i] );
}
// print the newline after a word
putchar( '\n' );
}
By the way, gets() is a really, really dangerous function. It should never have been included in the language. You are OK to use it for a homework, but in reality you should use fgets().
char s[1000];
fgets( s, sizeof(s), stdin );
The fgets() function is a bit more fiddly to use than gets(), but the above snippet will work for you.
Your other option for solving this homework is to use scanf() to read a word at a time from user input, and print it each time through the loop. I’ll leave that to you to look up. Don’t forget to specify your max string length in your format specifier. For example, a 100 char array would be a maximum 99-character string, so you would use "%99s" as your format specifier.
I'm trying to write a program in C that copies its input to its output while replacing each string of one or more Spaces with a single Space.
My code isn't doing that but is instead taking away every second character.
This is my code:
#include <stdio.h>
main()
{
int c;
int lastc;
lastc = 0;
while(getchar() != EOF){
c = getchar();
if(c == 32 && lastc == 32)
;
else
putchar(c);
lastc = c;
}
}
Your loop should look like:
while((c = getchar()) != EOF){
if(c == 32 && lastc == 32)
;
else
putchar(c);
lastc = c;
}
In your version you get a char with getchar while checking the condition for the while loop and then as a next step you again get a char with getchar. So the first one is not used in your code. Therefore it is taking away every second character.
Keep running in while loop until you get non-space character and print just one space after you get out.
int main()
{
int c;
bool space=false;
while ((c=getchar()) != EOF) {
while (isspace(c)) {
space = true;
c = getchar();
}
if (space) {
putchar(' ');
space = false;
}
putchar(c);
}
return 0;
}
I use fgets() function to getting string from input i.e stdin and store in the scroll string.
Then you must implement a way to analyze string to find spaces in it.
When you find first space, increase index if you face another space.
This is the code.
Code
#include <stdio.h>
int main(void){
char scroll[100];// = "kang c heng junga";
fgets(scroll, 100, stdin);
printf ("Full name: %s\n", scroll);
int flag = 0;
int i=0;
while (scroll[i] != '\0')
{
if (scroll[i] == ' ' )
flag=1;//first space find
printf("%c",scroll[i]);
if (flag==0){
i++;
}else {
while(scroll[i]==' ')
i++;
flag=0;
}
}
return 0;
}
Sample input: Salam be shoma doostane aziz
Program output: Salam be shoma doostane aziz
[Edit]
Use new string st to hold space eliminated string an print as output.
Also this code work for Persian string.
char scroll[100]={0};// = "kang c heng junga";
printf("Enter a string: ");
fgets(scroll, 100, stdin);
printf ("Original string: %s\n", scroll);
char st[100]={0};
int flag = 0;
int i=0;
int j=0;
while (scroll[i] != '\0')
{
if (scroll[i] == ' ' )
flag=1;//first space find
st[j]=scroll[i];
j++;
if (flag==0){
i++;
}else {
while(scroll[i]==' ')
i++;
flag=0;
}
}
printf("Eliminate Spaces: %s", st);
As part of my course, I have to learn C using Turbo C (unfortunately).
Our teacher asked us to make a piece of code that counts the number of characters, words and sentences in a paragraph (only using printf, getch() and a while loop.. he doesn't want us to use any other commands yet). Here is the code I wrote:
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int count = 0;
int words = 0;
int sentences = 0;
char ch;
while ((ch = getch()) != '\n')
{
printf("%c", ch);
while ((ch = getch()) != '.')
{
printf("%c", ch);
while ((ch = getch()) != ' ')
{
printf("%c", ch);
count++;
}
printf("%c", ch);
words++;
}
sentences++;
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
It does work (counts the number of characters and words at least). However when I compile the code and check it out on the console window I can't get the program to stop running. It is supposed to end as soon as I input the enter key. Why is that?
Here you have the solution to your problem:
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int count = 0;
int words = 0;
int sentences = 0;
char ch;
ch = getch();
while (ch != '\n')
{
while (ch != '.' && ch != '\n')
{
while (ch != ' ' && ch != '\n' && ch != '.')
{
count++;
ch = getch();
printf("%c", ch);
}
words++;
while(ch == ' ') {
ch = getch();
printf("%c", ch);
}
}
sentences++;
while(ch == '.' && ch == ' ') {
ch = getch();
printf("%c", ch);
}
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
The problem with your code is that the innermost while loop was consuming all the characters. Whenever you enter there and you type a dot or a newline it stays inside that loop because ch is different from a blank. However, when you exit from the innermost loop you risk to remain stuck at the second loop because ch will be a blank and so always different from '.' and '\n'. Since in my solution you only acquire a character in the innermost loop, in the other loops you need to "eat" the blank and the dot in order to go on with the other characters.
Checking these conditions in the two inner loops makes the code work.
Notice that I removed some of your prints.
Hope it helps.
Edit: I added the instructions to print what you type and a last check in the while loop after sentences++ to check the blank, otherwise it will count one word more.
int ch;
int flag;
while ((ch = getch()) != '\r'){
++count;
flag = 1;
while(flag && (ch == ' ' || ch == '.')){
++words;//no good E.g Contiguous space, Space at the beginning of the sentence
flag = 0;;
}
flag = 1;
while(flag && ch == '.'){
++sentences;
flag=0;
}
printf("%c", ch);
}
printf("\n");
I think the problem is because of your outer while loop's condition. It checks for a newline character '\n', as soon as it finds one the loop terminates. You can try to include your code in a while loop with the following condition
while((c=getchar())!=EOF)
this will stop taking input when the user presses Ctrl+z
Hope this helps..
You can implement with ease an if statement using while statement:
bool flag = true;
while(IF_COND && flag)
{
//DO SOMETHING
flag = false;
}
just plug it in a simple solution that uses if statements.
For example:
#include <stdio.h>
#include <conio.h>
void main(void)
{
int count = 0;
int words = 1;
int sentences = 1;
char ch;
bool if_flag;
while ((ch = getch()) != '\n')
{
count++;
if_flag = true;
while (ch==' ' && if_flag)
{
words++;
if_flag = false;
}
if_flag = true;
while (ch=='.' && if_flag)
{
sentences++;
if_flag = false;
}
}
printf("The number of characters are %d", count);
printf("\nThe number of words are %d", words);
printf("\nThe number of sentences are %d", sentences);
getch();
}
#include <stdio.h>
#include <ctype.h>
int main(void){
int sentence=0,characters =0,words =0,c=0,inside_word = 0,temp =0;
// while ((c = getchar()) != EOF)
while ((c = getchar()) != '\n') {
//a word is complete when we arrive at a space after we
// are inside a word or when we reach a full stop
while(c == '.'){
sentence++;
temp = c;
c = 0;
}
while (isalnum(c)) {
inside_word = 1;
characters++;
c =0;
}
while ((isspace(c) || temp == '.') && inside_word == 1){
words++;
inside_word = 0;
temp = 0;
c =0;
}
}
printf(" %d %d %d",characters,words,sentence);
return 0;
}
this should do it,
isalnum checks if the letter is alphanumeric, if its an alphabetical letter or a number, I dont expect random ascii characters in my sentences in this program.
isspace as the name says check for space
you need the ctype.h header for this. or you could add in
while(c == ' ') and whie((c>='a' && c<='z') || (c >= 'A' && c<='Z')
if you don't want to use isalpace and isalnum, your choice, but it will be less elegant :)
The trouble with your code is that you consume the characters in each of your loops.
a '\n' will be consumed either by the loop that scans for words of for sentences, so the outer loop will never see it.
Here is a possible solution to your problem:
int sentences = 0;
int words = 0;
int characters = 0;
int in_word = 0; // state of our parser
int ch;
do
{
int end_word = 1; // consider a word wil end by default
ch = getch();
characters++; // count characters
switch (ch)
{
case '.':
sentences++; // any dot is considered end of a sentence and a word
break;
case ' ': // a space is the end of a word
break;
default:
in_word = 1; // any non-space non-dot char is considered part of a word
end_word = 0; // cancel word ending
}
// handle word termination
if (in_word and end_word)
{
in_word = 0;
words++;
}
} while (ch != '\n');
A general approach to these parsing problems is to write a finite-state machine that will read one character at a time and react to all the possible transitions this character can trigger.
In this example, the machine has to remember if it is currently parsing a word, so that one new word is counted only the first time a terminating space or dot is encountered.
This piece of code uses a switch for concision. You can replace it with an if...else if sequence to please your teacher :).
If your teacher forced you to use only while loops, then your teacher has done a stupid thing. The equivalent code without other conditional expressions will be heavier, less understandable and redundant.
Since some people seem to think it's important, here is one possible solution:
int sentences = 0;
int words = 0;
int characters = 0;
int in_word = 0; // state of our parser
int ch;
// read initial character
ch = getch();
// do it with only while loops
while (ch != '\n')
{
// count characters
characters++;
// count words
while (in_word)
{
in_word = 0;
words++;
}
// skip spaces
while (ch == ' ')
{
ch = -1;
}
// detect sentences
while (ch == '.')
{
sentences++;
ch = -1;
}
// detect words
while ((ch != '\n')
{
word_detected = 1;
ch = -1;
}
// read next character
ch = getch();
}
Basically you can replace if (c== xxx) ... with while (c== xxx) { c = -1; ... }, which is an artifical, contrieved way of programming.
An exercise should not promote stupid ways of doing things, IMHO.
That's why I suspect you misunderstood what the teacher asked.
Obviously if you can use while loops you can also use if statements.
Trying to do this exercise with only while loops is futile and results in something that as little or nothing to do with real parser code.
All these solutions are incorrect. The only way you can solve this is by creating an AI program that uses Natural Language Processing which is not very easy to do.
Input:
"This is a paragraph about the Turing machine. Dr. Allan Turing invented the Turing Machine. It solved a problem that has a .1% change of being solved."
Checkout OpenNLP
https://sourceforge.net/projects/opennlp/
http://opennlp.apache.org/
I have a code which finds if there is more than one space between the words, in that case change them to one.
And I need to add some additional function which should make two spaces between sentences.
(A sentence's last symbol is . )
For example.
if i have file with text:
This is my first program. Hello world
program should print me:
This is my first program. Hello world
Code:
# include <stdio.h>
# include <stdlib.h>
int main()
{
FILE *in;
char myStr[100],newStr[100];
int ch;
int j,i,k,z=0;
in=fopen("duom.txt","r");
if(in){
while(EOF != ch){
ch=fgetc(in);
myStr[z] = ch;
z++;
k=0;
for(i=0; myStr[i] != '\0'; i++) {
if(myStr[i-1] != '.' && myStr[i] == ' ' && myStr[i+1] == ' ' )
continue;
newStr[k]= myStr[i];
k++;
}
}
}
for(j=0;j<k;j++){
printf("%c",newStr[j]);
}
printf("\n");
fclose(in);
system("pause");
return 0;
}
I don't ask you to write my whole code, just give me some ideas.
Sorry for my bad english :/
This loop follows your general approach of processing the file in blocks:
Your Approach Revised:
# include <stdio.h>
# include <stdlib.h>
int main() {
FILE *in;
char myStr[100],newStr[100];
int ch;
int j,i,k,z=0;
in=fopen("duom.txt","r");
if(!(in)) { fprintf(stderr,"Error opening file!\n"); }
else { //the file was opened
int go = 1; //master loop control
while(go) { //master loop
z = 0; //set sub loop
ch = '\0';//control variables
while(z < 100 && EOF != ch){ //process file in 99 character blocks
ch=fgetc(in); //getting one character at a time
if(EOF == ch) { go = 0; } //break master loop
else { myStr[z++] = ch; } //or process char
}
myStr[z] = '\0'; //null terminate the string
for(i=0; myStr[i] != '\0'; i++) {
//i=99='\0' <-- assumed is highest string size
//if i=0; Do you really want that leading space?
if(i== 0 && myStr[i] == ' ' ) { continue; }
//if i=98 it is the last char in the string i=99 should be '\0'
//So do you really want that trailing space?
if(i==98 && myStr[i] == ' ' ) { continue; }
//Same rational as above.
//So do you really want those trailing 2 spaces?
if(i==97 && myStr[i] == ' ' && myStr[i+1] == ' ') { continue; }
//if i=0; myStr[i-1] will likely cause a segmentation fault
if(i > 0 && myStr[i] == ' ' && myStr[i+1] == ' ' && myStr[i-1] != '.') { continue; }
newStr[k] = myStr[i];
k++;
}
for(j=0;j<k;j++){ printf("%c",newStr[j]); } //print the 99 char block
}
printf("\n"); //print a newline for good measure
fclose(in); //close file
}
return 0;
}
Note that the code will misbehave for files with size greater then 99 chars because spacing format comparisons are not be made from the end of one 99 char block to the beginning of another. You could implement this by not deleting the leading/trailing spaces comparing the values at i=1 & i=2 with the last two chars at i=97 & i=98 in the previous block.
This is a different, better loop. It solves the block barrier issues of the other approach and uses much less memory
Better approach:
# include <stdio.h>
# include <stdlib.h>
int main() {
FILE *in;
in=fopen("duom.txt","r");
if(!(in)) { fprintf(stderr,"Error opening file!\n"); return -1; }
//the file was opened
int x; //stores current char
int y; //stores previous char
for(y='\0'; (x=fgetc(in)) != EOF; y=x) { //read in 'x' until end of file
// The following conditions cover all cases:
// is 'x' not a space? Then print 'x'
// is 'x' a space but 'y' a period? Then print two spaces
// is 'x' a space and 'y' not a period but also not a space? Then print a space
// Otherwise 'x' is part of extra spacing, do nothing
if(x != ' ') { printf("%c",x); }
else if(x == ' ' && y == '.') { printf(" "); }
else if(x == ' ' && y != '.' && y != ' ') { printf(" "); }
else { ; } //do nothing
}
printf("\n"); //print a newline for good measure
fclose(in); //close file
return 0;
}
I suggest using strtok() and concatenate the tokens together separated by the correct number of spaces. If a token ends with a period, use two spaces. Otherwise, only use one. This way you don't even need to check how many spaces are in between words.
"Write a program to copy its input to
its output, replacing each string of
one or more blanks by a single blank."
I'm assuming by this he means input something like...
We(blank)(blank)(blank)go(blank)to(blank)(blank)(blank)the(blank)mall!
... and output it like:
We(blank)go(blank)to(blank)the(blank)mall!
This is probably easier than I'm making it out to be, but still, I can't seem to figure it out. I don't really want the code... more so pseudo code.
Also, how should I be looking at this? I'm pretty sure whatever program I write is going to need at least one variable, a while loop, a couple if statements, and will use both the getchar() and putchar() functions... but besides that I'm at a loss. I don't really have a programmers train of thought yet, so if you could give me some advice as to how I should be looking at "problems" in general that'd be awesome.
(And please don't bring up else, I haven't got that far in the book so right now that's out of my scope.)
Look at your program as a machine that moves between different states as it iterates over the input.
It reads the input one character at a time. If it sees anything other than a blank, it just prints the character it sees. If it sees a blank, it shifts to a different state. In that state, it prints one blank, and then doesn't print blanks if it sees them. Then, it continues reading the input, but ignores all blanks it sees--until it hits a character that isn't a blank, at which point it shifts back to the first state.
(This concept is called a finite state machine, by the way, and a lot of theoretical computer science work has gone into what they can and can't do. Wikipedia can tell you more, though in perhaps more complicated detail than you're looking for. ;))
Pseudo code
while c = getchar:
if c is blank:
c = getchar until c is not blank
print blank
print c
C
You can substitute use of isblank here if you desire. It is unspecified what characters contrive blank, or what blank value is to be printed in place of others.
After many points made by Matthew in the comments below, this version, and the one containing isblank are the same.
int c;
while ((c = getchar()) != EOF) {
if (c == ' ') {
while ((c = getchar()) == ' ');
putchar(' ');
if (c == EOF) break;
}
putchar(c);
}
Since relational operators in C produce integer values 1 or 0 (as explained earlier in the book), the logical expression "current character non-blank or previous character non-blank" can be simulated with integer arithmetic resulting in a shorter (if somewhat cryptic) code:
int c, p = EOF;
while ((c = getchar()) != EOF) {
if ((c != ' ') + (p != ' ') > 0) putchar(c);
p = c;
}
Variable p is initialized with EOF so that it has a valid non-blank value during the very first comparison.
This is what I got:
while ch = getchar()
if ch != ' '
putchar(ch)
if ch == ' '
if last_seen_ch != ch
putchar(ch)
last_seen_ch = ch
Same explanation with Matt Joiner's, but this code does not use break.
int c;
while ((c = getchar()) != EOF)
{
if (c == ' ') /* find a blank */
{
putchar(' '); /* print the first blank */
while ((c = getchar()) == ' ') /* look for succeeding blanks then… */
; /* do nothing */
}
if (c != EOF) /* We might get an EOF from the inner while-loop above */
putchar(c);
}
I worked really hard at finding a solution that used only the material that has already been covered in the first part of the first chapter of the book. Here is my result:
#include <stdio.h>
/* Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank. */
main()
{
int c;
while ((c = getchar()) != EOF){
if (c == ' '){
putchar(c);
while ((c = getchar()) == ' ')
;
}
if(c != ' ')
putchar(c);
}
}
Here is how I think of the algorithm of this exercise, in pseudo-code:
define ch and bl (where bl is initially defined to be 0)
while ch is = to getchar() which is not = to end of file
do the following:
if ch is = to blank and bl is = 0
--> output ch and assign the value 1 to bl
else --> if ch is = to blank and bl is = 1
--> do nothing
else --> output ch and assign the value 0 to bl
Example implementation in C:
#include <stdio.h>
#include <stdlib.h>
main() {
long ch,bl=0;
while ((ch=getchar()) != EOF)
{
if (ch == ' ' && bl == 0)
{
putchar(ch);
bl=1;
} else if (ch == ' ' && bl == 1) {
// no-op
} else {
putchar(ch);
bl=0;
}
}
return 0;
}
I wrote this and seems to be working.
# include <stdio.h>
int main ()
{
int c,lastc;
lastc=0;
while ((c=getchar()) != EOF)
if (((c==' ')+ (lastc==' '))<2)
putchar(c), lastc=c;
}
#include <stdio.h>
int main()
{
int c;
while( (c = getchar( )) != EOF )
{
if (c == ' ')
{
while ((c = getchar()) == ' ');
putchar(' ');
putchar(c);
}
else
putchar(c);
}
return 0;
}
#include <stdio.h>
main()
{
int c, numBlank=0 ;
while((c= getchar())!=EOF)
{
if(c ==' ')
{
numBlank ++;
if(numBlank <2)
{
printf("character is:%c\n",c);
}
}
else
{
printf("character is:%c\n",c);
numBlank =0;
}
}
}
First declare two variables character and last_character as integers.when you have not reach the end of the file( while(character=getchar() != EOF ) do this;
1. If character != ' ' then
print character
last_character = character
2. If character == ' '
if last_character ==' '
last character = character
else print character
Using the constraints of not using else or and operators. This code only prints a blank when the blank variable is equal to 1 and the only way to reset the counter is by typing something other than a blank. Hope this helps:
include
/* Write a program that replaces strings of blanks with a single blank */
void main(){
int c, bl;
bl = 0;
while((c = getchar()) != EOF){
if(c == ' '){
++bl;
if(bl == 1){
putchar(' ');
}
}
if(c != ' '){
putchar(c);
bl = 0;
}
}
}
Many others have already used the last character logic in their code, but perhaps the following version is easier to read:
int c, prevchar;
while ((c = getchar()) != EOF) {
if (!(c == ' ' && prevchar == ' ')) {
putchar(c);
prevchar = c;
}
}
#include <stdio.h>
main() {
int input, last = EOF;
while ((input = getchar()) != EOF) {
if (input == ' ' && last == ' ') continue;
last = input;
putchar(input);
}
}
I am at the same point in the book. and my solution goes with making a count++ if blank is found and making the count back to zero if anything other than blank is found.
For if statement I put another another check to check value of count (if zero) and then print.
Though at this point of learning I shouldn't be concern about efficiency of two methods but which one is efficient a.) Accepted solution here with while inside while or b.) the one I suggested above.
My code goes like below:
#include <stdio.h>
main()
{
int count=0,c;
for( ; (c=getchar())!=EOF; )
{
if(c==' ')
{
if(count==0)
{
putchar(c);
count++;
}
}
if(c!=' ')
{
putchar(c);
count=0;
}
}
}
#include <stdio.h>
main()
{
int CurrentChar, LastChar;
LastChar = '1';
while ((CurrentChar = getchar()) != EOF)
{
if (CurrentChar != ' ')
{
putchar(CurrentChar);
LastChar = '1';
}
else
{
if (LastChar != ' ')
{
putchar(CurrentChar);
LastChar = ' ';
}
}
}
}
a way to make it easier for the new people are stuck on this book
(by not knowing any thing then what brought up until page 22 in K&R).
credits to #Michael , #Mat and #Matthew to help me to understand
#include <stdio.h>
main()
{
int c;
while ((c = getchar()) != EOF) /* state of "an input is not EOF" (1) */
{
if (c == ' ') /* "blank has found" -> change the rule now */
{
while ((c = getchar ()) == ' '); /* as long you see blanks just print for it a blank until rule is broken (2) */
putchar(' ');
}
putchar(c); /* either state (2) was broken or in state (1) no blanks has been found */
}
}
1.Count the number of blanks.
2.Replace the counted number of blanks by a single one.
3.Print the characters one by one.
<code>
main()
{
int c, count;
count = 0;
while ((c = getchar()) != EOF)
{
if (c == ' ')
{
count++;
if (count > 1)
{
putchar ('\b');
putchar (' ');
}
else putchar (' ');
}
else
{
putchar (c);
count = 0;
}
}
return;
}
</code>
#include <stdio.h>
int main(void)
{
long c;
long nb = 0;
while((c = getchar()) != EOF) {
if(c == ' ' || c == '\t') {
++nb;
} else {
if(nb > 0) {
putchar(' ');
nb = 0;
}
putchar(c);
}
}
return 0;
}
To do this using only while loops and if statements, the trick is to add a variable which remembers the previous character.
Loop, reading one character at a time, until EOF:
If the current character IS NOT a space:
Output current character
If the current character IS a space:
If the previous character WAS NOT a space:
Output a space
Set previous character to current character
In C code:
#include <stdio.h>
main()
{
int c, p;
p = EOF;
while ((c = getchar()) != EOF) {
if (c != ' ')
putchar(c);
if (c == ' ')
if (p != ' ')
putchar(' ');
p = c;
}
}
I am also starting out with the K&R textbook, and I came up with a solution that uses only the material which had been covered up until that point.
How it works:
First, set some counter 'blanks' to zero. This is used for counting blanks.
If a blank is found, increase the counter 'blanks' by one.
If a blank is not found, then first do a sub-test: is the counter 'blanks' equal or bigger than 1? If yes, then first, print a blank and after that, set the counter 'blanks' back to zero.
After this subtest is done, go back and putchar whatever character was not found to be a blank.
The idea is, before putcharing a non-blank character, first do a test to see, if some blank(s) were counted before. If there were blanks before, print a single blank first and then reset the counter of blanks. That way, the counter is zero again for the next round of blank(s). If the first character on the line is not a blank, the counter couldn't have increased, hence no blank is printed.
One warning, I haven't gone very far into the book, so I'm not familiar with the syntax yet, so it's possible that the {} braces might be written in different places, but my example is working fine.
#include <stdio.h>
/* Copy input to output, replacing each string of one or more blanks by a single blank. */
main()
{
int c, blanks;
blanks = 0;
while ((c = getchar()) != EOF) {
if (c != ' ') {
if (blanks >= 1)
printf(" ");
blanks = 0;
putchar(c); }
if (c == ' ')
++blanks;
}
}
Like many other people, I am studying this book as well and found this question very interesting.
I have come up with a piece of code that only uses what has been explained before the exercice (as I am not consulting any other resource but just playing with the code).
There is a while loop to parse the text and one if to compare the current character to the previous one.
Are there any edge cases where this code would not work ?
#include <stdio.h>
main() {
// c current character
// pc previous character
int c, pc;
while ((c = getchar()) != EOF) {
// A truthy evaluation implies 1
// (learned from chapter 1, exercice 6)
// Avoid writing a space when
// - the previous character is a space (+1)
// AND
// - the current character is a space (+1)
// All the other combinations return an int < 2
if ((pc == ' ') + (pc == c) < 2) {
putchar(c);
}
// update previous character
pc = c;
}
}
for(nb = 0; (c = getchar()) != EOF;)
{
if(c == ' ')
nb++;
if( nb == 0 || nb == 1 )
putchar(c);
if(c != ' ' && nb >1)
putchar(c);
if(c != ' ')
nb = 0;
}
Here is my answer, I am currently in the same spot you were years ago.
I used only the syntax taught until this point in the books and it reduces the multiple spaces into one space only as required.
#include<stdio.h>
int main(){
int c
int blanks = 0; // spaces counter
while ((c = getchar()) != EOF) {
if (c == ' ') { // if the character is a blank
while((c = getchar()) == ' ') { //check the next char and count blanks
blanks++;
// if(c == EOF){
// break;
// }
}
if (blanks >= 0) { // comparing to zero to accommodate the single space case,
// otherwise ut removed the single space between chars
putchar(' '); // print single space in all cases
}
}
putchar(c); //print the next char and repeat
}
return 0;
}
I removed the break part as it was not introduced yet in the book,hope this help new comers like me :)
This is a solution using only the techniques described so far in K&R's C. In addition to using a variable to achieve a finite state change for distinguishing the first blank space from successive blank spaces, I've also added a variable to count blank spaces along with a print statement to verify the total number. This helped me to wrap my head around getchar() and putchar() a little better - as well as the scope of the while loop within main().
// Exercise 1-9. Write a program to copy its input to its output, replacing
// each string of one or more blanks by a single blank.
#include <stdio.h>
int main(void)
{
int blank_state;
int c;
int blank_count;
printf("Replace one or more blanks with a single blank.\n");
printf("Use ctrl+d to insert an EOF after typing ENTER.\n\n");
blank_state = 0;
blank_count = 0;
while ( (c = getchar()) != EOF )
{
if (c == ' ')
{
++blank_count;
if (blank_state == 0)
{
blank_state = 1;
putchar(c);
}
}
if (c != ' ')
{
blank_state = 0;
putchar(c);
}
}
printf("Total number of blanks: %d\n", blank_count);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int c, flag=0;
while((c=getchar()) != EOF){
if(c == ' '){
if(flag == 0){
flag=1;
putchar(c);
}
}else{
flag=0;
putchar(c);
}
}
return 0;
}
I hope this will help.
/*a program that copies its input to its output, replacing each string of one or more blanks by a single blank*/
#include <stdio.h>
#include<stdlib.h>
int main(void)
{
double c;
char blank = ' ';
while((c = getchar()) != EOF)
{
if(c == ' ')
{
putchar(c);
while(( c = getchar() )== ' ')
{
if(c != ' ')
break;
}
}
if(c == '\t')
{
putchar(blank);
while((c = getchar()) == '\t')
{
if(c != '\t')
break;
}
}
putchar(c);
}
return 0;
}
// K & R Exercise 1.9
// hoping to do this with as few lines as possible
int c = 0, lastchar = 0;
c = getchar();
while (c != EOF) {
if (lastchar != ' ' || c != ' ') putchar(c);
lastchar=c;
c=getchar();
}
Considering what's asked in the question, I have also made sure that the program runs smooth in case of various tabs, spaces as well as when they're clubbed together to form various combinations!
Here's my code,
int c, flag = 1;
printf("Enter the character!\n");
while ((c = getchar()) != EOF) {
if (c == ' '||c == '\t') {
c=getchar();
while(c == ' '|| c == '\t')
{
c = getchar();
}
putchar(' ');
if (c == EOF) break;
}
putchar(c);
}
Feel free to run all test cases using various combinations of spaces and tabs.
Solution1: as per topics covered in the k&R book:
#include <stdio.h>
int main()
{
int c;
while ((c = getchar()) != EOF)
{
if (c == ' ')
{while ( getchar() == ' ' )
; // ... we take no action
}
putchar(c);
}
return 0;
}
Solution2 : using program states:
int main()
{
int c, nblanks = 0 ;
while ((c = getchar()) != EOF)
{
if (c != ' ')
{ putchar(c);
nblanks = 0;}
else if (c==' ' && nblanks == 0) // change of state
{putchar(c);
nblanks++;}
}
return 0;
}
Solution3 : based on last seen char
int main()
{
int c, lastc = 0;
while ((c = getchar()) != EOF)
{
if ( c != ' ')
{putchar(c);}
if (c == ' ')
{
if (c==lastc)
;
else putchar(c);
}
lastc = c;
}
return 0;
}