scanf format string not recognized [closed] - c

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.

Related

Why is the first value of my char array 10?

I'm new to programming but I wanted to make a program that gets as input a number, (length) and then stores a series of a's and b's of said length. Finally it should output the numbers as the ascii numbers. (so 97 and 98)
I thought I should malloc a char array of the size length and then do a for-loop over it and print everything as an integer.
The problem is however that I get a value 10 as the value of the first letter.
Thanks a lot for any help!
int main()
{
int length;
scanf("%d", &length);
char *matrix = malloc((length + 1 ) * sizeof(char));
for (int i = 0; i < length; i++)
{
scanf("%c", &matrix[i]);
}
for (int i = 0; i < length; i++)
{
printf("\n%d", matrix[i]);
}
return 0;
}
When inputting 3 on the first line and aba on the next line, I get 10 97 98.
However I expected it to be 97 98 97. Why do I get a value of 10 in the first place of the array?
Use
scanf(" %c", &matrix[i]);
^^^^
instead of
scanf("%c", &matrix[i]);
^^
When the format starts with a blank all white spaces are skipped.
From the C Standard (7.21.6.2 The fscanf function)
5 A directive composed of white-space character(s) is executed by
reading input up to the first non-white-space character (which remains
unread), or until no more characters can be read.
10 is the ASCII code of the (white space) new line character '\n' that was present in the input buffer after you entered the length of the array.
The first scanf() with the format string %d leaves a newline in the input buffer.
What happens here, is that your terminal collects input one full line at a time, passing it to the program, and then the scanf() only reads the digits from the buffer, leaving the newline character there for the next scanf() to see. The same would happen if you entered 10 abc: the space, abc and the newline would be left there.
This mismatch is not something people usually expect, and it's one of the things that makes scanf() annoying. I would suggest using fgets() instead to first read a full line, matching what the terminal gives, and then parse the number from it with sscanf() or strtol() (or atoi()).
This cleans up the issue at the point where the first line is read, instead of passing it on to the next input function to handle. Otherwise all your input functions are tied together, if the next input would be for a whole line with possible white space, you'd need to know if you expect to clear a pre-existing newline or not. (You could also replace the later scanf("%c") with getchar(), not that that matters with buffering though.)
That said, the scanf("%c")/getchar() loop may still see newlines if you enter lines that don't have as many characters as the loop expects, so if you don't want to see them at all, filter them out.
So, something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int length;
char linebuf[100];
fgets(linebuf, 100, stdin);
length = strtol(linebuf, NULL, 10);
char *matrix = malloc(length + 1);
for (int i = 0; i < length; i++)
{
matrix[i] = getchar();
}
for (int i = 0; i < length; i++)
{
printf("\n%d", matrix[i]);
}
printf("\n");
return 0;
}
(The obvious downside of fgets() is that you have to decide on a maximum length for the input line, allocate a buffer and call another function in addition to it.)

Taking strings as a 2-D char array

I want a code such that I enter some strings one-by-one (by pressing enter) and display it.
for example;
Input
abc
def
Output
abc
def
also I want this input to be in a array so that I can select any character
from the array whenever I want. For example: s[1][1] gives 'e'.
I have writen a code for this problem.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, n, m;
scanf("%d%d", &n, &m);
char a[n][m];
for (i = 0; i<n; i++)
scanf("%s", a[i]);
for (i = 0; i<n; i++) {
printf("%s", a[i]);
printf("\n");
}
}
But for this code my input/output goes like this:
Input
ab
cd
Output
abcd
cd
Can anyone tell where am I going wrong?
You have not shown the input value of n and m in the question. But from the input and output string shown, it seems that char array a[i] does not have the enough space for terminating null-character \0. When you give format specifier %s, scanf() automatically adds a terminating null character at the end of the stored sequence. I tried your code with input 2 for both n and m and I am getting the output as you are getting:
$ ./a.out
2 2
ab
cd
abcd
cd
Give the value 4 to m and the output is:
2 4
ab
cd
ab
cd
When using scanf() for string input, it is good to add check for max character modifier that is 1 less than the length of the input buffer. So, if the size of input buffer is 4 then you can do
scanf("%3s",a[i]);
With this, the scanf() will read not more than 3 characters in a[i] and will add \0 at the fourth location of a[i]. Beware with this, it does not discard the remaining input from input stream and they will be consumed by consecutive scanf() call.
If you want to drop the extra input which wasn't consumed by scanf, one way of doing it is to read and discard the extra input using a loop, like this:
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
You can add it after scanf() reads data from input stream, like this:
for(i=0; i<n; i++) {
scanf("%3s", a[i]); // assuming the size of a[i] is 4
int c;
while((c = getchar()) != '\n' && c != EOF) // <=== This loop read the extra input characters and discard them
/* discard the character */;
}
This will work fine for the input that does not contain any whitespace characters. If your input contain any whitespace character, it may not behave as expected. Hence, I would suggest you to read about fgets() which gives you better control for string input.
Check this: fgets
and this: How to read from stdin with fgets()?
you are working with a 2D array of char:
char a[n][m];
but keep in mind the value for the 2nd index should be 1 character longer than the length of the string you wish it to allow room for the \0 byte. (all C strings must be null terminated)
This means char a[n][m]; can contain up to n strings, each string with maximum length of m-1 bytes.
char exampleStr[] = {"char count"}; //for example contains 11 characters (not 10)
|c|h|a|r| |c|o|u|n|t|\0| //note nul char is appended
Another common problem when reading user input in a loop is failure to remove any unwanted newlines, which can cause the loop to behave poorly. Following is an example of how to read a user specified number of strings ( using fgets() instead of scanf() ), each with a user specified length: (also removing unwanted newlines ( \n ) in the process)
For readability, the following example replaces n & m with lines & maxLen.
int main(void)
{
int lines, maxLen, i=0;
printf("Enter number of lines:");
scanf(" %d", &lines);
printf("Enter maxLen line length:");
scanf(" %d", &maxLen);
char line[lines][maxLen+2]; //+2 to allow for trailing newline and null
fgets(line[i], maxLen, stdin);//consume anything left in stdout
printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
for(i=0;i<(lines);i++)
{
fgets(line[i], maxLen, stdin);
line[i][strcspn(line[i], "\n")] = 0; // clear newline
printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
}
return 0;
}
All strings in C must be terminated with the null character \0, print knows this and prints all character UP TO that sign. You should make all of your strings 1 character longer than the words you plan to fit in them and fill them with 0 (0 is the integer value of \0) in the start to avoid this problem.

using scanf("%d ") with a space after the %d

In my c class today I was troubling with the scanf() command, we were just learning pointers and we got a question asking us to get an array, and print it reversed without using the [] for anything but declaring the (int) array. Of course it seems like a piece of cake but not when you accidentally write:
scanf("%d ", arr + i);
Did you notice the space after the %d? Sure did take me a while to figure it out but for some reason that makes loops go crazy, and I wanted you guys to help me (and my teachers) to figure out why does that happen. Example:
#include <stdio.h>
#define LEN 10
void arrayInput(int * arr, unsigned int len);
void arrayReverseOutput(int * arr, unsigned int len);
int main(void)
{
int arr[LEN] = { 0 };
arrayInput(arr, LEN);
arrayReverseOutput(arr, LEN);
system("pause");
return 0;
}
void arrayInput(int * arr, unsigned int len)
{
unsigned int i = 0;
printf("Enter 10 numbers: ");
for (i = 0; i < len; i++)
{
//printf("i = %d \n", i); see what happens when you use this line
scanf("%d ", arr + i);
}
}
void arrayReverseOutput(int * arr, unsigned int len)
{
int i = 0;
printf("The numbers in reverse order: ");
for (i = --len; i >= 0; i--)
{
printf("%d ", *(arr + i));
}
}
I'm really curios to see what's going on with that scanf... it's as if it requires 2 inputs at the first time it runs but somehow still manages to put the inputs in their right position in the array...
Thanks for taking your time to read this <3
A space in the format string tells scanf() to match zero or more whitespace characters, until the match fails. Spaces (' '), newlines('\n'), carriage returns ('\r'), and tabs ('\t') are among the whitespace characters. When a space occurs at the end of a format string, scanf() will try to match whitespace characters from the input until no match is found. But, scanf() can only return when a match fails, or end of file is reached. Thus, in the case of a statement like:
scanf("%d ", arr + i);
the call to scanf() will appear to hang, greedily waiting for more input from the user. Whenever the Enter key is pressed, a newline is sent and matched by scanf(), which is still waiting for a failing match. Or end of file. You can escape such a loop by signalling end of file from the keyboard with Ctrl-D on Linux, or Ctrl-C on Windows.
It is almost always a mistake to terminate a scanf() format string with a space. A newline ('\n') is also a whitespace character, and has the same effect when placed at the end of a format string.
Note that spaces can be used effectively in scanf() format strings. For example:
int retval = scanf(" %c %c", &c1, &c2);
Here, if a previous IO operation has left a newline in the input stream (a not uncommon occurrence), the leading whitespace directs scanf() to read and ignore it. The second space in the format string tells scanf() to expect zero or more whitespace characters between the input characters to be converted. This allows the user to input the characters with an intervening space. Without the added whitespace, if a user entered a b\n, c2 would end up holding the value for a space character, and the b would be left behind in the input stream for the next IO operation to pick up. Also note that scanf() returns the number of successful conversions, allowing the program to check whether the input is as expected. If retval in the above line is anything other than 2, something has gone wrong.

How to read n numbers separated by space in C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I want to read n integers from user during execution and the numbers are separated by spaces. It would be the best to be received as an array. For input 1 22 3 445 3, the result is, array[0]=1, array[1]=22 and so on. I have to do it in C. Can't use
scanf("%d %d %d", &var1, &var2, &var3);
because, I don't know how many such numbers would be inserted. The value of n would be read from user just before reading this data.
enum { MAX_NUMBERS = 1000000 }; // Choose appropriate upper bound
int n;
if (scanf("%d", &n) == 1 && n > 0 && n < MAX_NUMBERS)
{
int array[n];
for (int i = 0; i < n; i++)
{
if (scanf("%d", &array[i]) != 1)
…process error — terminate loop?…
}
…use array…
}
You can read multiple numbers with scanf() using a loop as shown. You've no idea whether they were all presented on a single line, or each was on its own line, or whether there were many blank lines between successive numbers (or any permutation of all these possibilities).
The scanf() family of functions basically do not care about newlines — it is hard to force them to do so. When you care about line-based input, use fgets() or POSIX function getline() to read a line and sscanf() — or other string parsing functions — to process the line.
I'm assuming support for C99 with VLA (variable length arrays). The principles are the same without that support — the mechanics are a little different (and there are multiple options for how to do it).
Use fgets() and then strtok() with atoi().
Take the numbers as a string.
Here is one way to do it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char numbers[100];
int myn[100];
printf("Give me numbers..\n");
fgets(numbers,100,stdin);
const char s[2] = " ";
char *token;
token = strtok(numbers, s);
int i=0;
myn[i]=atoi(token);
while( token != NULL )
{
i++;
printf( " %s\n", token );
token = strtok(NULL, s);
myn[i]=atoi(token);
}
printf("You gave me: ");
for (int j=0; j<i; j++){
printf ("%d, ", myn[j]);
}
return(0);
}
The above C program does exactly what you want. At the for loop, it prints to the screen the numbers you gave from keyboard. The "problem" would be much easier by using enter instead of spaces between the numbers.
Click on the links, to see very useful details about the functions used.

C program gives strange results [closed]

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

Resources