K&R C Exercise 1-9 states:
Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.
I have nearly solved this exercise, but the code I've written (see below) always prints an extra space before the first nonspace character. So input that looks like this
X(space)(space)X(space)(space)X(space)(space)X
results in output that looks like this
(space)X(space)X(space)X(space)X
#include <stdio.h>
int main()
{
int c; //current input character
int s; //consecutive input space counter
c = getchar();
s = 0;
while ((c = getchar()) != EOF){
if (c == ' '){
++s;
if (s == 1) //uses the counter to print only the
putchar(' '); //first space in each string of spaces
}
else {
putchar(c);
if (s != 0) //resets the space counter when it
s = 0; //encounters a non-space input character
}
}
return 0;
}
Why does my code always print a leading space when I run it?
How can I modify this code to print the first input character first instead of a leading space?
Do not throw away the first char. #David Hoelzer
// Commented out
//c = getchar();
s = 0;
while ((c = getchar()) != EOF){
Also note unbalanced } near return 0;
Related
I am reading the C programming language book Dennis M. Ritchie and
trying to solve this question:
Write a program to print a histogram of
the lengths of words in
its input. It is easy to draw the histogram with the bars horizontal; a vertical
orientation is more challenging.
I think my solution works, but the problem is that if I don't press EOF, the terminal won't show the
result. I know that the condition specifies that exactly, but I am
wondering whether there is any way to make the program terminate after
reading a single line? (Sorry if my explanation of the problem is a bit shallow. Feel free to ask more.)
#include <stdio.h>
int main ()
{
int digits[10];
int nc=0;
int c, i, j;
for (i = 0; i <= 10; i++)
digits[i] = 0;
//take input;
while ((c = getchar ()) != EOF) {
++nc;
if (c == ' ' || c=='\n') {
++digits[nc-1];
//is it also counting the space in nc? i think it is,so we should do nc-1
nc = 0;
}
}
for (i = 1; i <= 5; i++) {
printf("%d :", i);
for (j = 1; j <= digits[i]; j++) {
printf ("*");
}
printf ("\n");
}
// I think this is a problem with getchar()
//the program doesn't exit automatically
//need to find a way to do it
}
You could try to make something like
while ((c = getchar ()) != EOF && c != '\n') {
and then adding a line after the while loop to account for the last word:
if (c == '\n') {
++digits[nc-1];
nc = 0;
There is also another problem inside your program. ++digits[nc-1]; is correct, however, for the wrong reason. You should make it because an array starts at zero, i.e. if you have an array of length 10, it will go from 0 to 9, so you should count the length of the words and then add one to the position of the array length - 1 (as there are no words of length zero). The problem is that you are still counting the blank spaces or the newline characters inside the length of a word, so if you have two blank spaces after a word of length 4, the program will add to the array a word of length 5 + a word of length 1. To avoid this, you should do something like this:
while ((c = getchar ()) != EOF) {
if ((c == ' ' || c == '\n' || c == '\t') && nc > 0) {
++digits[nc-1]; // arrays start at zero
nc = 0;
}
else {
++nc;
}
}
In the following code example from K&R's book, if I replace putchar(c) with printf("%c", c) the code works the same. But if I replace it with printf("%d", c) it gives gibberish output.
#include <stdio.h>
int main() {
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
From here, I learned that the getchar() converts the stdin to an 8-bit character whose value ranges from 0 to 255.
Now I want to print the value of c using putchar(c) in one line and printf("%d", c) in another line. So I wrote the following code:
#include <stdio.h>
int main() {
int c, b;
c = getchar();
b = c;
while (c != EOF && c != 10) {
printf("%c",c);
c = getchar();
}
printf("\n");
while (b != EOF && b != 10) {
printf("%d\t",b);
b = getchar();
}
}
I used the condition c != 10 as the newline character is read as 10 by getchar(). I expected the code to work as
$ ./a.out
783
783
55 56 51
but the program terminates as
$ ./a.out
783
783
55
I understand that getchar() takes input from stdin and the variable b is not stdin. So how should I copy the variable c to b so that my program works as I expect it to?
The problem is that your code does not (and cannot, as it stands) 'remember' the inputs you gave in the first loop. So, after you have finished that loop, your second loop is wanting to read in the characters for b (after it has output the first value, which is remembered from the earlier b = c line).
So, after outputting 55 (the integer value of the character 7), it is waiting for further input.
Probably the easiest way to get the output that you're looking for is to have an array of input characters. Then, you can output the %c values as you read them (as before), then re-run the outputs using the %d format in a subsequent for loop.
Here is a demonstration that does what I think you're after:
#include <stdio.h>
#define MAXINS 20 // Set to the maximum number of input characters you want to allow
int main()
{
int c[MAXINS];
int i = 0, n = 0;
c[0] = getchar();
while (i < MAXINS && c[i] != EOF && c[i] != 10) {
printf("%c", c[i]);
c[++i] = getchar();
++n;
}
printf("\n");
for (i = 0; i < n; ++i) {
printf("%d\t", (int)(c[i]));
}
return 0;
}
Feel free to ask for further clarification and/or explanation.
EDIT: On the point in the your first paragraph, "But if I replace it with printf("%d", c) it gives gibberish output." Well, when I try the following code and give 783 and then hit return (which generates a newline) I get the expected 55565110 as the output:
int main()
{
int c;
c = getchar();
while (c != EOF) {
printf("%d", c);
c = getchar();
}
return 0;
}
This may look like gibberish, but it's just the same output as you 'expect' in your later code, but without the spaces and with the addition of the 10 for the newline.
You need to have every character stored, because once you read a char from stdin, it is not present in stdin anymore.
Since you want the newline character in the end as a part of the input, you should use fgets to take the input.
Say you are taking an input that could have a maximum of 100 characters.
#include <stdio.h>
int main(void) {
char c[100]; // A char array
fgets(c,100,stdin);
int x=0;
while (c[x] != 10 && c[x] != EOF)
printf("%c",c[x++]);
printf("\n");
x = 0;
while (c[x] != 10 && c[x] != EOF) // You can simply compare it with the newline character too.
printf("%d ",c[x++]);
printf("\n");
return 0;
}
There are many ways to do this. You can also read stdin character-by-character ans store it in an array. However, since you need to display the ASCII values of the characters in another line after displaying the characters themselves, you will have to store them in an array.
You are copying only the first input, to copy the whole string you need to store each input in a buffer and check if the string doesn't overflow that buffer on each iteration:
int main(void)
{
enum {size = 256};
char buffer[size];
size_t count = 0;
int c;
while ((c = getchar()) && (c != '\n') && (c != EOF))
{
printf("%c", c);
if (count < size)
{
buffer[count++] = (char)c;
}
}
printf("\n");
for (size_t iter = 0; iter < count; iter++)
{
printf("%d\t", buffer[iter]);
}
printf("\n");
}
If you don't want to limit the buffer to an arbitrary size then you need to change your approach to use dynamic memory (realloc or a linked list)
I am a beginner in C and I would like to know if there is a way where I can print my character count on the same line as a putchar() function without going to a newline.
#include <stdio.h>
int main(void) {
int c, i = 0;
while ((c = getchar()) != EOF) {
i++;
if(putchar(c) == '\n'){
printf(":%d\n", i - 1);
i = 0;
}
}
return 0;
}
For example if run this I get:
Input
This is the first line.
Output
This is the first line.
:23
Is there a way to which I can have the output look like this?
This is the first line.:23
Simple: since putchar outputs at the very point it is called, just don't output yet:
if (c == '\n') {
// omit newline here so that no empty lines are printed
printf(":%d", i - 1);
i = 0;
}
putchar(c);
What should i do in this program. I cant understand.
The question is as : Write a program detab that replaces tabs in the input with the proper number
of blanks to space to the next tab stop. Assume a fixed set of tab stops, say every n columns.
Should n be a variable or a symbolic parameter?
I started by replacing the tabs ('\t') with space (' ').
But i guess this is the wrong approach.
please suggest ?
and btw what should n be? variable or symbolic parameter?
code so far:
#include<stdio.h>
#define TAB 5
int main() {
int i, c;
while((c = getchar()) != EOF) {
if(c == '\t') {
for(i = 0; i < TAB; ++i)
putchar(' ');
} else
putchar(c);
}
return 0;
}
In all the questions posted for this exercise i couldn't understand the meaning.
This is my final code, please tell me if it has any problems / bugs. I think it is working as it should..
thanks to #Nit, #Chrono Kitsune , #dasblinkenlight and all the others who helped.
#include<stdio.h>
#define TAB 8
int main() {
int c, count = 0, space = 0;
while((c = getchar()) != EOF) {
if(c == '\t') {
space = (TAB - (count % TAB));
while(space > 0){
putchar(' ');
count++;
space--;
}
}
else{
putchar(c);
++count;
}
if(c == '\n')
count = 0;
}
return 0;
}
What you are doing is not what the exercise wants you to do: rather than inserting a fixed number of spaces for each tab, you should be inserting a different number of spaces depending on how much has been printed on the line so far.
It does not matter how you take the number of spaces per tab - the way you made it a preprocessor constant is perfectly fine. However, rather than producing TAB spaces regardless of where the '\t' has been found, you program needs to count how much "regular" characters have been printed, and count how many spaces are needed when it sees '\t'.
Make a variable count for characters printed so far. Initialize it to zero, and then reset it back to zero each time you see a '\n' character. When you call putchar, also make count++.
Now when you see a tab '\t' compute how far you are form the next tab stop. The expression for that is
TAB - (count % TAB)
That is how many spaces you need to print.
This should be enough information for you to go back and fix your program - I think you need to write only five additional lines of code (not counting lines for curly braces that you would need to insert) in order to finish this exercise.
The first step is to understand the problem. As I read it over and over for several times at first I couldn't understand what exactly it wants me to do. It's because some concepts weren't clear or familiar to me before I searched for more information about tab. First, what is a tab and what is a tab stop exactly? A tab is a character represented by the escape sequence \t in many contexts. Just like other characters such as letters or digits, it's a character, but with special usage, so it's not a wide space or 4 or 8 spaces as it appears to be. Being displayed like a wide space or 4 or 8 spaces is just what it's designed for, which aligns each tab-delimited group of texts on multiple lines to make the region look like a table, but underneath on the level the software sees it's just a character. Tab stops are positions on the line where the cursor goes when the Tab key is pressed. These positions are fixed on the line according to the width or number of characters (or columns, all referring to the same concept) with which the Tab character is displayed. For example, on Windows Notepad the default width for Tab is 8 characters, and when you type Tab key the cursor would move behind the 8th, 16th, 24th... character. You can type 0s on the first line to see the effect more clearly:
00000000000000000000000000000000
Ivan Hello World
This is a table
delimited by tab
Now reading the problem over again it's clear to me that it's about replacing the Tab characters with spaces while maintaining the original table look. Then you can start writing your code to calculate how many spaces are needed for each Tab. Here's my complete code for this exercise:
#include <stdio.h>
#define MAX_LENGTH 1000
#define LINE_NUM 100
#define TAB_WIDTH 8
int readLine(char line[], int maxLength);
void copy(char from[], char to[]);
void detab(char line[], char result[]);
main() {
printf("Input: \n");
char lines[LINE_NUM][MAX_LENGTH];
char line[MAX_LENGTH];
char result[MAX_LENGTH];
int lineId = 0, length = 0;
while ((length = readLine(line, MAX_LENGTH)) != 0) {
detab(line, result);
copy(result, lines[lineId]);
lineId++;
}
printf("Output: \n");
for (int i = 0; i <= lineId; i++) {
printf("%s\n", lines[i]);
}
}
int readLine(char line[], int maxLength) {
char ch;
int length = 0;
while ((ch = getchar()) != EOF && ch != '\n' && length < maxLength) {
line[length] = ch;
length++;
}
if (ch == '\n') {
line[length] = '\0';
}
return length;
}
void copy(char from[], char to[]) {
int i = 0;
while (from[i] != '\0') {
to[i] = from[i];
i++;
}
to[i] = '\0';
}
void detab(char line[], char result[]) {
int i = 0;
char ch;
int column = 0;
int spaces;
int nextTabStop;
while ((ch = line[i++]) != '\0') {
if (ch == '\t') {
spaces = TAB_WIDTH - column % TAB_WIDTH;
nextTabStop = column + spaces;
for (; column < nextTabStop; column++) {
result[column] = ' ';
}
} else {
result[column] = ch;
column++;
}
}
result[column] = '\0';
}
First, try to get familiar with '\t' (TAB character) and see what happens when you print
'\t' + ','
'.' + '\t' + ','
'..' + '\t' + ','
And so on. You will see that there is a fixed number of initial '.'s in which the ',' character after '\t' is on the same position, this means that the '\t' length is not fixed, so if you try to replace it with a fixed number of ' ' characters (white spaces), the output will be different from the input.
Understanding that, your task is to create a program that replaces all '\t' characters with white spaces, so you have to calculate the number of necessary white spaces to print for each '\t' char you read. This is what I've done so far.
#include <stdio.h>
#define WSPT 8 // white spaces per tab
main () {
int c, counter;
counter = 0; // distance from the previous tab stop
while((c = getchar()) != EOF) {
if(c == '\t') {
for(int i = 0; i < WSPT - counter; ++i)
putchar(' '); // print white spaces until reach the next tab stop
counter = 0; // you are again at the start of a tab stop
} else {
putchar(c);
if(c != '\n')
counter = (counter + 1) % WSPT; // move 1 step
else
counter = 0; // you are again at the start of a tab stop
}
}
}
Okay, his is actually a very simple question and I'm not sure why everyone is making it more complicated than it is. We need to simply replace tab's with the necessary number of blanks so the resulting output looks no different than if there was a tab there.
No need for a million lines of code... a few will do...
#include <stdio.h>
/* A program *detab* that replaces tabs in the input with the proper number of blanks to space to the next tab stop. Assuming a fixed set of tabstops, say every n columns */
#define TAB_WIDTH 4 // tab width on particular machine
int main()
{
int c;
int i = 0;
while((c = getchar()) != EOF) {
if(c != '\t')
putchar(c);
else
while(i < TAB_WIDTH - 1){
putchar(' ');
i++;
}
}
}
why so complicated stuffs..just do this
#include <stdio.h>
int main()
{
int c, tab=6, count=0;
while((c=getchar())!=EOF)
{
count++;
if (c=='\t')
{
for (int i=count; i%(tab+1)!=0; i++) putchar(' ');
}
else putchar(c);
if(c=='\n') count=0;
}
}
Im writing a simple program to count the number of character user is entered, and i wrote an if to check wether there is a newline but still printing it..
the code:
#include <stdio.h>
int main()
{
char ch;
int numberOfCharacters = 0;
printf("please enter a word, and ctrl + d to see the resault\n");
while ((ch = getchar()) != EOF)
{
if (numberOfCharacters != '\n')
{
numberOfCharacters++;
}
}
printf("The number of characters is %d", numberOfCharacters);
return 0;
}
what am i doing wrong?
Think about this line:
if (numberOfCharacters != '\n')
how can it make sense? You are comparing the number of characters read so far with a newline, it's like comparing apples to oranges and surely won't work. It's another variable that you should check...
Change your loop to this.
while ((ch = getchar()) != EOF)
{
if(ch != '\n')
numberOfCharacters++;
}