Cant read input line in C - c

Sorry for a stupid question, but this is really starting to annoy me.
I need to take a line of input from a console. Here's the relavent fragment of code:
int number_read=0;
char line[80];
printf("Enter register address: ");
number_read = scanf("%s\n", line);
printf("number of characters entered: %d; characters entered: %s.\n", number_read, line);
if (number_read > 0) {
<read some registers and display the results.>
}
It doesn't work. The "Enter register address" line is printed, and the cursor stops at the end of the line, and moves to the next line when I press enter, but then nothing else happens. I've tried replacing scanf() with fscanf(stdin,...), with fgets(stdin), gets, GNU's getline(), a short function that does the same thing, with diagnostics:
char *new_line, ch;
for(;;) {
ch = fgetc(stdin);
if(ch == EOF) break;
if((*line++ = ch) == '\n') break;
printf("Line so far: %s\n", line);
}
*line='\0';
I get the same response from all of them. I'm including all the requisite headers.
I'm on a Windows XP box, compiling with gcc 3.4.5 (mingw).
Can anyone see what I'm doing wrong?

In scanf you should use a %i to represent a int so, try with
scanf("%I", number_line);

The following code will works,
char buff_msg[1024];
while(1)
{
if(fgets(buff_msg,1024, stdin) != NULL){
printf("%s\n", buff_msg);
memset(buff_msg, 0, 1024); // you will need this line
}
}
You can
break the loop on your own condition

try read() it works in MinGW replace
this
number_read = scanf("%s\n", line);
with this also include #include<unistd.h>
number_read = read(STDIN_FILENO, (void *)line,sizeof line);

value scanf returns is not the number of strings in the number of elements to read(this case meybe 1).
Use the %n To get the number, such as desired.
scanf("%s%n", line, &number_read);
printf("number of characters entered: %d; characters entered: %s.\n", number_read, line);

Related

Issues with scanf() and accepting user input

I am trying to take in user input with spaces and store it in an array of characters.
After, I want to take in a single character value and store it as a char.
However, when I run my code, the prompt for the character gets ignored and a space is populated instead. How can I take in an array of chars and still be allowed to prompt for a single character after?
void main()
{
char userIn[30];
char findChar;
printf("Please enter a string: ");
scanf("%[^\n]s", userIn);
printf("Please enter a character to search for: ");
scanf("%c", &findChar);
//this was put here to see why my single char wasnt working in a function I had
printf("%c", findChar);
}
scanf("%c", &findChar); reads the next character pending in the input stream. This character will be the newline entered by the user that stopped the previous conversion, so findChar will be set to the value '\n', without waiting for any user input and printf will output this newline without any other visible effect.
Modify the call as scanf(" %c", &findChar) to ignore pending white space and get the next character from the user, or more reliably write a loop to read the read and ignore of the input line.
Note also that scanf("%[^\n]s", userIn); is incorrect:
scanf() may store bytes beyond the end of userIn if the user types more than 29 bytes of input.
the s after the ] is a bug, the conversion format for character classes is not a variation of the %s conversion.
Other problems:
void is not a proper type for the return value of the main() function.
the <stdio.h> header is required for this code.
Here is a modified version:
#include <stdio.h>
int main() {
char userIn[30];
int c;
char findChar;
int i, found;
printf("Please enter a string: ");
if (scanf("%29[^\n]", userIn) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
/* read and ignore the rest of input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("Please enter a character to search for: ");
if (scanf("%c", &findChar) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
printf("Searching for '%c'\n", findChar);
found = 0;
for (i = 0; userIn[i] != '\0'; i++) {
if (userIn[i] == findChar) {
found++;
printf("found '%c' at offset %d\n", c, i);
}
}
if (!found) {
printf("character '%c' not found\n", c);
}
return 0;
}
scanf("%[^\n]s", userIn); is a bit weird. The s is guaranteed not to match, since that character will always be \n. Also, you should use a width modifier to avoid a buffer overflow. Use scanf("%29[^\n]", userIn); That alone will not solve the problem, since the next scanf is going to consume the newline. There are a few options. You could consume the newline in the first scanf with:
scanf("%29[^\n]%*c", userIn);
or discard all whitespace in the next call with
scanf(" %c", &findChar);
The behavior will differ on lines of input that exceed 29 characters in length or when the user attempts to assign whitespace to findChar, so which solution you use will depend on how you want to handle those situations.

fgets doesn't stop reading user input

I found some challenge on reddit to make a program which will sum up all DnD dice rolls. Number of throws is unlimited therefore I created this while loop.
I used fgets to input the string, (I can't input only integers because the input is for example 1d3, where 1 is number of dice thrown, and 3 is number of sides of the dice thrown.)
When the user is prompted to input dice, fgets never stops reading user input.
For example:
To end inputting dice type 0
1d3
1d4
1d5
0
0
^C
Main function:
int main(void)
{
char input[MAXSIZE];
int sum = 0;
printf("To end inputting dice type 0\n");
while(*(input) != 0);
{
fgets(input, sizeof(input), stdin);
printf("Debug: input = ");
puts(input);
printf("\n");
sum += dice(input);
printf("Debug: sum = %d\n", sum);
}
printf("Sum of dice rolls is %d.", sum);
return 0;
}
Firstly, the literal value of the character input 0 is not 0. In ASCII, it is 48 (decimal).
Try
while(*(input) != '0') // (1) - use the character literal form
// (2) remove the ;
That said, the standard output is usually line buffered. You need to force a flush if you want to see the outputs in the terminal. You can do that by either
add a newline
printf("Debug: input = \n");
use fflush(stdout).
Try this:-
while(fgets(input, sizeof input, stdin) != NULL)
or
while(fgets(input, sizeof input, stdin))
The issue was really simple and such a beginner mistake I feel shameful for even asking the question.
The semicolon after the while loop.
Thanks all for helping me out.
char input[MAXSIZE] = { 0 }; // initialise input!
// otherwise you get to here and access an uninitialised variable:
while(*(input) != 0); // <--- and a semicolon right there!!! Remove that!
In fact I think the loop you want is while (fgets(input, sizeof input, stdin) && strcmp(input, "0\n"))... note that I've hoisted the fgets into the loops control expression.
You should probably do a check after calling fgets to ensure a newline is read, for example
while (fgets(input, sizeof input, stdin) && strcmp(input, "0\n")) {
size_t n = strcspn(input, "\n");
if (input[n] == '\n') input[n] = '\0';
else assert(input[n] == '\0'), // #include <assert.h>
fscanf(stdin, "%*[^\n]"),
fgetc(stdin);
There's no undefined behaviour associated with reading unsigned integers when using fscanf, so if you only plan on using positive values you can use that instead of fgets if you wish, i.e.
unsigned dice_count, dice_sides;
while (fscanf(stdin, "%ud%u", &dice_count, &dice_sides) == 2) {
printf("You chose to roll %u times with dice that contain %u sides\n", dice_count, dice_sides);
}

C Program - How to deny any non-numerical input

I've just started learning the language of C, and would love your help in cleaning up / simplifying my code if you know a better way to reach the following.
I want a program to ask for a number, and if that is found then proceed to print and end, however if anything else is put in (e.g. a letter key), then I want the program to loop asking for a number until one is given.
I started off by using a simple scanf input command, but this seemed to go into an infinite loop when I tried to check if a valid number (as we define them) was put in.
So instead I have ended up with this, from playing around / looking online, but I would love to know if there is any more efficient way!
//
// Name & Age Program
// Created by Ben Warren on 1/3/18.
//
#include <stdio.h>
int main (void)
{
//Setting up variables
int num;
char line[10]; /* this is for input */
//Collecting input
printf("Please enter any number? \t");
scanf("%d", &num);
//If Invalid input
while (num==0)
{
printf("\nTry again:\t");
fgets(line, 10, stdin); //turning input into line array
sscanf(line, "%d",&num); //scaning for number inside line and storing it as 'num'
if (num==0) printf("\nThat's not an number!");
}
//If Valid input
{
printf("\n%d is nice number, thank you! \n\n", num);
*}*
return 0;
}
Instead of checking if the value is different to 0, check the return value of
sscanf. It returns the number of conversions it made. In your case it should be 1. Unless the return value is 1, keep asking for a number.
#include <stdio.h>
int main(void)
{
int ret, num;
char line[1024];
do {
printf("Enter a number: ");
fflush(stdout);
if(fgets(line, sizeof line, stdin) == NULL)
{
fprintf(stderr, "Cannot read from stdin anymore\n");
return 1;
}
ret = sscanf(line, "%d", &num);
if(ret != 1)
fprintf(stderr, "That was not a number! Try again.\n");
} while(ret != 1);
printf("The number you entered is: %d\n", num);
return 0;
}
That is not a bad approach for someone new to C. One small improvement would be to actually check the return value of scanf(), since it returns the number of arguments successfully retrieved. Then you could get away from relying on num being 0 to indicate the input was valid. Unless you do want to specifically flag 0 as invalid input.
int ret = scanf("%d", &num);
ret == 1 would mean an integer was succesffully read into num, ret == 0 would mean it was not.
Consider using strtol to parse a string for a long int. This also allows you to detect trailing characters. In this example if the trailing character is not a newline, the input can be rejected. strtol can also detect overflow values. Read the documentation to see how that works.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
//Setting up variables
long int num = 0;
char line[40] = ""; /* this is for input */
char *parsed = NULL;
printf("Please enter any number? \t");
fflush ( stdout);
while ( fgets(line, 40, stdin))
{
parsed = line;//set parsed to point to start of line
num = strtol ( line, &parsed, 10);
if ( parsed == line) {//if parsed equals start of line there was no integer
printf("Please enter a number? \t");
printf("\nTry again:\t");
fflush ( stdout);
continue;
}
if ( '\n' != *parsed) {//if the last character is not a newline reject the input
printf("Please enter only a number? \t");
printf("\nTry again:\t");
fflush ( stdout);
}
else {
break;
}
}
if ( !parsed || '\n' != *parsed) {
fprintf ( stderr, "problem fgets\n");
return 0;
}
printf("\n%ld is nice number, thank you! \n\n", num);
return 0;
}
0 (zero) is a number...
But I see what you want to do...
You can check for a valid number, using isdigit or a combination of similar functions
I think its also important to follow the advice of other answers to use the return value from scanf using code such as:
int ret = scanf("%d", &num);
and examining ret for success or failure of scanf.

How to read a integer followed by a string in C? [duplicate]

This question already has an answer here:
How to read / parse input in C? The FAQ
(1 answer)
Closed 6 years ago.
I am trying to write a simple program which will read two input lines, an integer followed by a string. However, it doesn't seem to work for me.
int main()
{
int i;
char str[1024];
scanf("%d", &i);
scanf("%[^\n]", str);
printf("%d\n", i);
printf("%s\n", str);
return 0;
}
Immediately after entering the integer and pressing "Enter", the program prints the integer. It doesn't wait for me to enter the string. Whats wrong? Whats the correct way to program this?
What you need to know
The problem with %[^\n] is that it fails when the first character to be read is the newline character, and pushes it back into the stdin.
The Problem
After you enter a number for the first scanf, you press Enter. %d in the first scanf consumes the number, leaving the newline character ('\n'), generated by the Enter keypress, in the standard input stream (stdin). %[^\n] in the next scanf sees this \n and fails for the reason given in the first paragraph of this answer.
Fixes
Solutions include:
Changing scanf("%d", &i); to scanf("%d%*c", &i);. What %*c does is, it scans and discards a character.
I wouldn't recommend this way because an evil user could trick the scanf by inputting something like <number><a character>\n, ex: 2j\n and you'll face the same problem again.
Adding a space (any whitespace character will do) before %[^\n], i.e, changing scanf("%[^\n]", str); to scanf(" %[^\n]", str); as #Bathsheba mentioned in a comment.
What the whitespace character does is, it scans and discards any number of whitespace characters, including none, until the first non-whitespace character.
This means that any leading whitespace characters will be skipped when inputting for the second scanf.
This is my recommendation: Clear the stdin after every scanf. Create a function:
void flushstdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
and call it after every scanf using flushstdin();.
Other issues:
Issues unrelated to your problem include:
You don't deal with the case if scanf fails. This can be due to a variety of reasons, say, malformed input, like inputting an alphabet for %d.
To do this, check the return value of scanf. It returns the number of items successfully scanned and assigned or -1 if EOF was encountered.
You don't check for buffer overflows. You need to prevent scanning in more than 1023 characters (+1 for the NUL-terminator) into str.
This can be acheived by using a length specifier in scanf.
The standards require main to be declared using either int main(void) or int main(int argc, char* argv[]), not int main().
You forgot to include stdio.h (for printf and scanf)
Fixed, Complete Program
#include <stdio.h>
void flushstdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
int main(void)
{
int i;
char str[1024];
int retVal;
while((retVal = scanf("%d", &i)) != 1)
{
if(retVal == 0)
{
fputs("Invalid input; Try again", stderr);
flushstdin();
}
else
{
fputs("EOF detected; Bailing out!", stderr);
return -1;
}
}
flushstdin();
while((retVal = scanf("%1023[^\n]", str)) != 1)
{
if(retVal == 0)
{
fputs("Empty input; Try again", stderr);
flushstdin();
}
else
{
fputs("EOF detected; Bailing out!", stderr);
return -1;
}
}
flushstdin();
printf("%d\n", i);
printf("%s\n", str);
return 0;
}
This simply, will work:
scanf("%d %[^\n]s", &i, str);
Instaed of scanf() use fgets() followed by sscanf().
Check return values of almost all functions with a prototype in <stdio.h>.
#include <stdio.h>
int main(void) {
int i;
char test[1024]; // I try to avoid identifiers starting with "str"
char tmp[10000]; // input buffer
// first line
if (fgets(tmp, sizeof tmp, stdin)) {
if (sscanf(tmp, "%d", &i) != 1) {
/* conversion error */;
}
} else {
/* input error */;
}
// second line: read directly into test
if (fgets(test, sizeof test, stdin)) {
size_t len = strlen(test);
if (test[len - 1] == '\n') test[--len] = 0; // remove trailing ENTER
// use i and test
printf("i is %d\n", i);
printf("test is \"%s\" (len: %d)\n", test, (int)len);
} else {
/* input error */;
}
return 0;
}

Use "while" to check if there is a blank line C

The code is to check if there is a blank line. I thought when I enter some text, it will keep doing the printf(), because it is stuck in the loop. But in fact, it just does the printf() once, and waits for another line of text. Why? Is it because the input will be wiped after the gets() function?
Here is the code
int main(){
char input[257];
char *ptr;
puts("Enter text a line at a time, then press Enter");
puts("Enter a blank line when done");
while( *(ptr= gets(input)) != NULL){
printf("You've entered: %s\n", input);
}
puts("Thank you and goodbye\n");
return 0;
}
this while should do the trick
while( (ptr= gets(input)) != NULL && input[0]!='\0')

Resources