C: Print on previous line after newline check - c

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);

Related

Copying the input from `getchar()` to another variable

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)

Take N input strings with spaces in C

I am trying to take t (test cases) strings as inputs in C. Every string ends with a # and it can have spaces.
I am using getchar and some while loops but I am not able to achieve what I want.
int t;
scanf("%d",&t);
while(t>0){
char expression[100];
char c;
int i=0;
while(1){
c = getchar();
if(c == '#'){
break;
}
else{
expression[i]=c;
i++;
}
}
t--;
printf("%d\n",i);
for(int j=0;j<i;j++){
printf("%c",expression[j]);
}
}
What I am trying to achieve is if # is encountered I want to ignore whatever is after It.
My input:
1
test#wtf
Output:
5
test
So in case of 1 test case it is working fine.
But when I give try this.
2
test#wtf
test#
The corresponding outs are:
5
test
and
8
wtf
test
As you can see the second output should be test and length should be 5 but it is not so.
In order to ignore text after #, you'll have to consume those characters using getchar() and ignore them till you encounter a new line character '\n'.
So, after you exit the inner while loop, you need to add the following code
while(1) {
c = getchar();
if(c == '\n'){
break;
}
}
You can do it this way, you process all characters, once you get a '#' you keep reading characters without adding them to the array and you get out of the outer loop once you get a new line character '\n'.
while (--t > 0)
{
int i,s,c;
char exp[100];
s = 0;
while (s < 100 && (c = getchar()) != '#')
exp[s++] = c;
while ((c = getchar()) != '\n')
;
printf("%d\n", s);
i = -1;
while (++i < s)
printf("%c", exp[i]);
printf("\n");
}

Why is this code printing a random character inbetween the input and output lines?

I'm trying to write a program (in C) where the input is reversed and printed in reverse line by line. For the most part, the code actually does just that. The trouble is that for some (most) of my input, I will get a random character or an extra newline in between my input and my output in the console.
For example, I start the program, type "testing" into the console, and get "gnitseT" back after hitting enter. This has happened successfully and is what I expect. It looks like this:
Testing
gnitseT
But then when I type "Hello" into the console, it looks like this:
Hello
g (unexpected)
olleH
Or if I type "running" into the console, instead of getting an unexpected "g" in between my input and output lines, I get an extra newline.
Running
newline here
extra newline here (unexpected)
gninnuR
#include <stdio.h>
void reverse(int length, char s[])
{
int i;
for (i = length; i >= 0; i--)
{
printf("%c", s[i]);
}
printf("\n");
}
int main(void)
{
char smain[2000];
int c;
int i;
i = 0;
while ((c = getchar()) != EOF)
{
smain[i] = c;
i++;
if (c == '\n')
{
reverse(i, smain);
i = 0;
}
}
return 0;
}
The expected behavior is for the program to output into the console the reversed input after the enter key is pressed.
Sometimes, especially at the very beginning of the program, it will work perfectly.
Then, it starts giving me a random character in between my input and output, or it starts giving me an extra newline.
I would like to have it so that it just prints the input in reverse order without any unexpected odd characters showing up in between the input and the output.
Thanks for any help.
Your immediate problem is you are reading and attempting to print one character past the end of the characters stored in your array with
for (i = length; i >= 0; i--) {
printf("%c", s[i]);
}
Why? You add length characters to smain in main(). In C, arrays are zero-based. The characters in your string are from 0 -> length-1 (the nul-character in a string is located at s[length], but here you never add a nul-terminating character, so the value at that index is simply indeterminate). If the element has not been initialized (which it will not be on your first word or any subsequent word equal to or longer than your longest word entered at that time) Undefined Behavior results since you are attempting to read and print an indeterminate value from an uninitialized element in array. How your terminal will output the indeterminate is undefined -- and may well result in a G being printed.
To correct the problem, loop for (i = length - 1; i >= 0; i++) or very simply:
while (length--)
printf ("%c", s[length]);
putchar ('\n'); /* don't printf a single-character */
(note: don't call the variadic printf function to output a single-character, that is what putchar() is for)
Putting it altogether and fixing your logic so you don't add and print the '\n' as part of every word you are reversing, you could do:
#include <stdio.h>
#define MAXC 2048 /* if you need a constant, #define one (or more) */
void reverse(int length, char s[])
{
while (length--)
printf ("%c", s[length]);
putchar ('\n'); /* don't printf a single-character */
}
int main (void) {
char smain[MAXC];
int c, i = 0;
while ((c = getchar()) != EOF) {
if (c == '\n') {
reverse(i, smain);
i = 0;
}
else
smain[i++] = c;
}
if (i) /* protect against file with no POSIX end-of-file */
reverse (i, smain);
return 0;
}
(note: the if {...} else {...} logic to prevent adding the '\n')
Example Use/Output
$ printf "Hello\nGoodbye\n" | ./bin/prnrevlines
olleH
eybdooG
Which will work just as well without the POSIX eof, e.g.
$ printf "Hello\nGoodbye" | ./bin/prnrevlines
olleH
eybdooG
on line 29
++i;
this means "i" now have length+1 so, you have been out of the string, you can change the program to :
#include <stdio.h>
void reverse(int length, char s[])
{
int i;
for (i = length; i >= 0; i--)
{
printf("%c", s[i]);
}
printf("\n");
}
int main(void)
{
char smain[2000];
int c;
int i;
i = 0;
while ((c = getchar()) != EOF)
{
smain[i] = c;
if (c == '\n')
{
reverse(i, smain);
i = 0;
}
else i++;
}
return 0;
}

not able to understand the role of getchar and putchar here

#include <stdio.h>
#include <stdlib.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
}
return 0;
}
when I compile and give input ABC and then press enter, the never ending loop starts like AAAAAAAAA....
And now look at this code below
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar (); // added this single line
}
return 0;
}
In this program, when I input ABC, the output is ABC.
Can anyone please explain why it is not showing just a single A as output?
Look at the below code you mentioned
int main(void){
int c;
c = getchar();
while (c != EOF) {
putchar(c);
}
return 0;
}
When c = getchar(); executes & if you provided input as ABC at runtime & press ENTER(\n), that time c holds first character A.
Next come to loop, your condition is c!=EOF i.e A!=EOF which always true & it will print A infinitely because you are not asking second time input so c holds A.
correct version of above code is
int main(void){
int c;
while ( (c = getchar())!=EOF) { /* to stop press ctrl+d */
putchar(c);
}
return 0;
}
case 2 :- Now looks at second code
int main(void){
int c;
c = getchar();
while (c != EOF) { /*condition is true */
putchar(c);
c = getchar ();/*After printing ABC, it will wait for second input like DEF, unlike case-1 */
}
return 0;
}
Can anyone please explain why it is not showing just a single A as output ? Why it should prints only A, it prints whatever input you given like ABC & so on. Just note that getchar() works with buffered input i.e when you press ENTER getchar() will read upto that & when there is nothing left to read getchar() returns EOF.

K&R C Exercise 1-9 *almost* solved

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;

Resources