Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I just started programming and came up with a program to count the number of characters in an input.
The code is as below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int number = 0;
int counter = 0;
char sentence[20];
printf("Enter a sentence: ");
scanf("%s", sentence);
while ( sentence[number] != '\n' )
{
counter += 1;
number += 1;
}
printf("no. of characters in sentence you just typed: %d", counter);
return 1;
}
This program has a strange behavior that I cannot understand. It compiles without error but no matter how many characters I type or what character is entered, it shows the no. of characters as 817.
I am curious as to why 817? It's really weird. Also please enlighten me on how I can improve my code since it did not perform as expected.
scanf reads input till \n but not including it So :
while ( sentence[number] != '\n' ) // always true for legal array bound
will lead to illegal memory access, causing undefined behavior. If you do wish to read the string including the [ white-space ] characters, use [ fgets ].
If you wish to count the number of characters, change the while loop to
while ( sentence[number] != '\0' )
scanf with the argument "%s" reads one word, up to the first space or tab or newline, and will not include any \n character in the input. Your loop will never end. Or, more accurately, it will give what the C standard calls "undefined behaviour". In practice, it means that it will keep looping until it either finds a newline somewhere in memory (perhaps 817 places from the start!), or reaches the end of allocated memory and crashes.
If you read the manual page the function scanf does not read white space.
Perhaps fgets would be a better choice along with changing the while loop to
while (sentence[number] != 0 && sentence[number] != '\n')
Just change this line :
while ( sentence[number] != '\n' )
to
while ( sentence[number] != '\0' )
and return 0 at the end
Here is a better version of code to count the number of characters
#include <stdio.h>
main(){
double c;
for(n=0; getchar() != EOF; ++n);
printf("%.0f\n", n);
}
Related
This question already has answers here:
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed 1 year ago.
#include <stdio.h>
#include <string.h>
int main()
{
int num;
char answer[10];
char affirmation[10]="yes";
do
{
printf("Enter a number : \n");
scanf("%d",&num);
if (num % 97 == 0)
{
printf("No. is divisible by 97!\n");
}
else
{
printf("No. is not divisible by 97!\n");
}
printf("Once More ? [yes/no] \n");
fgets(answer,sizeof(answer),stdin);
}
while(strcmp(affirmation,answer) == 0);
return 0;
}
I expected from this program to check the divisibility of a provided number by 97 and then to ask if I again want it to check for another number if I input "yes". But it isn't prompting for my input .
If anybody can explain the reason behind this problem and suggest some ways to get through, it will be appreciated.The output is given below:
This output is for num = 194.
It is being executed but what it's reading is the newline character in the input stream that wasn't read when you did the scanf.
What your scanf does is to first skip any white space, then read an integer up to but not including the first non-digit character, which is probably the \n generated by the ENTER key.
Then, because fgets reads a line up to the next newline, you get an empty line.
In both the preceding two paragraphs, I'm assuming for simplicity ideal conditions such as ensuring it's a valid integer and that the line is not longer than the size you provided. Obviously, deviating from that could cause unruly behaviour.
It's generally not a good idea to mix the two input types unless you know in great detail what will be in the input stream. It's often better to just use line-based input and then sscanf that into more appropriate variables.
That way, you can be more sure about where your input stream is at any given point.
A quick fix in this particular case is simply to augment your scanf so that it skips to the start of the next line:
scanf("%d",&num);
while (getchar() != '\n') {}
The other problem you'll have after that is the fact that your fgets input will actually be "yes\n" rather than "yes", so that string comparison won't work.
If you're after a fairly robust line input function that takes care of that (and many other things), see here.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I tried to write a program which takes a line from user (console) until a comma, full stop or newline character is encountered and tell how many characters read following the specific pattern.
The string is read correctly but the count is not accurate.
#include <stdio.h>
int main()
{
int n;
char s[100];
// The following line should read a string until (. or , or new-line in encountered)
// and %n should tell me the no of characters it read until that point
scanf("%[^.,\n]s%n", s, &n);
// The String in okay
printf("%s\n", s);
// But count of characters read is 0
printf("%d\n",n);
return 0;
}
5 problems:
The "s" in "%[^.,\n]s%n" stops scanning as there can be no 's' read after %[^.,\n]. %[^.,\n] would have read in all 's'. Thus the later "%n" never occurred and the n that was later printed, a 0, was bad code - printing the uninitialized n - which could have been any int or a trap.
Scan lacks a width limit. Bad things happen after the 99th character.
With scanf("%[^.,\n]s%n", s, &n);, scanning will saving nothing in s if the first character is a .,\n. Later printing of s is bad as s[] is uninitialized.
Code fails to check the return value of scanf().
scanf() does not certainly read a line as directed with "write a program which takes a line from user" - it stops short using scanf().
C Std Lib defines a line as below, so code should attempt to read the entire line.
A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character.
scanf() alternative
int n = 0;
char s[100];
s[0] = '\0';
int cnt == scanf("%99[^.,\n]%n", s, &n);
if (cnt == EOF) puts("Nothing was read");
else printf("%s\n", s);
Better alternative
I'd recommend using fgets() instead of scanf(): takes a line from user.
char s[100];
if (fgets(s, sizeof s, stdin)) {
size_t n = strcspn(s, ".,\n"); // offset of string that does not have .,\n
s[n] = '\0';
printf("%s\n", s);
printf("%zu\n", n);
}
Note: Lines longer than about 100 need additional code.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I' ve inserted the followings input for the follow program:
a b c d e
After the e letter I've pressed Enter, but the program blocks on scanf for i equal to 3.
Seems that scanf is not able to fetch other character from stdin.
Thanks in advance for your help.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char a[5];
for (int i = 0; i < 5; i++)
{
scanf("%c ", a + i);
printf("i = %d a[%d] = %c \n", i, i, a[i]);
}
int i = 0;
while( i < 5 )
{
printf("%c ", a[i]);
i++;
}
return 0;
}
It doesn't block when i == 3 -- it completes that iteration -- it blocks when i == 4.
That's because of the space after the %c in the scanf format -- a space causes scanf to read input and skip whitespace up until it finds a non-whitespace character. That non-whitespace character will then be left in the FILE input buffer as the next character to be read. So in the 5th iteration of the loop (i == 4), it reads the e then reads whitespace looking for non-whitespace. So the newline is skipped over (it's whitespace) and it starts (trying to) read the next line which blocks.
Once you provide the next line (assuming its not empty/all whitespace), it will get a non-whitespace character and scanf will return.
Using scanf to fetch a single character at a time from stdin is not a good idea. If the user types more than one character, you can overflow the buffer as there is no room for the null character. This also leaves excess characters in stdin.
Another idea is to use a special format string flag to fetch 5 characters at once, and then print them or do whatever you want with them.
You can use the flag "%5c", where 5 is any integer number, that reads, scan exactly 5 characters.
Here is the modified version of your code
#include <stdio.h>
#include <stdlib.h>
int main()
{
char a[5];
scanf("%5c", a);
int i = 0;
while( i < 5 )
{
printf("%c ", a[i]);
i++;
}
return 0;
}
Now there is no blocking.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am learning C language from a book called "The C Programming Language" by Brian Kernighan & Dennis Ritchie and have been stuck at its basic lesson of line counting program. The program runs but it does not give an output of how many lines were inputed.
Have given the program code below, please help on the same.
#include <stdio.h>
void main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF )
if (c == '\n')
++nl;
printf("%d \n", nl);
return 0;
}
The code should read the input and then output how many lines of text were given. How should this be changed to make it work?
Your program works fine. However, I would prefix main with the int type to keep the compiler quiet. It should look like this:
int main(void)
When you call it, what I did was this:
$$$ ->./test6 < test4.c
19
$$$ ->wc test4.c
19 48 379 test4.c
$$$ ->
The getchar function is the same thing as getc(stdin), so when you run your program, it takes it's input from stdin (keyboard) or a file redirected to stdin.
EDIT: As someone pointed out, if the last line doesn't have a \n terminator, that line will not be counted. So I rewrote your code to account for this:
#include <stdio.h>
int main(void)
{
int c; /* Character */
int cp; /* Previous Character */
int n; /* Number of lines */
n = 0;
c = 0;
while (1)
{
cp = c;
c = getchar();
if (c == '\n')
{
n++;
continue;
}
if (c == EOF && cp == '\n') break;
if (c == EOF)
{
n++;
break;
}
}
printf("%d \n", n);
return 0;
}
As you can see in the code, I used fall-though logic to either continue the loop or to break out of it. Now I tested this code using clang on FreeBSD and it works properly.
The logic of this program is as follows:
Save current character as the previous character.
Get the next character and make it the current character.
Check the current character to see if it's a newline character.
If it is, then we increment the line counter and restart the loop.
Check the current character to see if it's EOF and the previous character to see if it's the newline character.
If it is, then break out of the loop.
Check the current character to see if it's EOF.
If it is, then increment the line counter and break out of the loop.
That is how you deal with the final line not being terminated by a newline character and still have it counted as a line. Note that this is considered a special case and needs to be explicitly coded for. If you continue into the software development profession, then you will encounter special case situations a lot and you need to code the handling for each one that you encounter.
Hope this helps.
There was no issue with code; it work's fine, only the issue- it was taking input and was not giving output.
In windows to end input,
we have to press Ctrl + Z followed by Enter key, it will show the count of lines in input.
Your code is working properly.I checked it in Ubuntu.
Just press Ctrl+d if you are working in Linux to end the input.
Say for example I have the following main function:
int main()
{
char a[1023];
while (scanf("%s",a) != EOF)
{
printf("%s ",a);
}
}
If I input
a ab abc(newline)
it should output:
a ab abc(newline)
but the main function output
a ab abc (newline) // there is a space between newline and the last string
I want to read the string one by one. What is the problem and how can I delete that space? Thank you.
Your printf("%s ",a); statement outputs a space after each string it outputs, regardless. You need to instead output a space only if there are going to be more strings. Equivalently (and easier), output a space before each string if it is not the first:
int first = 1;
while (scanf("%s",a) != EOF) {
if (!first) printf(" ");
printf("%s",a);
first = 0;
}
also, you never output a newline, despite describing a newline as being output...
A little note about independent learning:
The first time you use any standard library function, you should read its corresponding manual at least once. The reason is that as soon as you know about any issues (or helpful features), you'll know to avoid those issues (or use the helpful features). Reading the manual really helps you learn the full potential and avoid the pitfalls of C.
The first time you read something, you may not entirely understand it. Don't let that bother you; Just keep reading. If this happens, I suggest that you read it again once you're at the bottom of the page, and try to understand it completely the second time. Please, read the fscanf manual at least once.
That's out of the way, now. You might notice little ^ superscripts here and there. My intention is to annotate facts that you would have learnt by reading and understanding the manual I linked to above.
The format specifier %s discards as much whitespace as possible prior to attempting to consume as much non-whitespace as possible^. Suppose you were to input something with four leading bytes of whitespace, your output wouldn't have those four leading bytes of whitespace.
"This uses four spaces" translates to "This uses four spaces".
It seems logical that this violates your program specification, which extends your problem^. Perhaps you should be using the %[ format specifier, instead^. In that case, an empty line would be considered a match failure and the destination for the line would be indeterminate, so you'd need to handle the return value of scanf better^ (which I encourage you to do, anyway).
#include <stdio.h>
int main(void) {
char line[512];
int x;
do {
x = scanf("%511[^\n]", line);
if (x == 0) {
/* Match failure caused by inputting an empty line. Print empty line? */
putchar('\n');
}
else if (x == 1) {
/* Success. */
puts(line);
}
/* Read and discard the remainder of a line */
do { x = getchar(); } while (x >= 0 && x != '\n');
} while (x != EOF);
}
From the length of this loop and the simplicity of the problem, you might reason that using scanf for this is probably the wrong way to solve the problem. You can eliminate the line array, the calls to scanf and the resulting scanf error checking by using a derivation of the inner-most loop. Something like this looks nice:
#include <stdio.h>
int main(void) {
int c;
do {
c = getchar();
} while (c >= 0 && putchar(c) >= 0 && c != '\n');
}
PS. There's also a manual for getchar, putchar and many other standard things.