C language: check if scanf user input is integer only - c

So i need to get number from user and i want to check if the number is int:
char temp;
int num;
int res = scanf("%d%c", &num, &temp);
if (res == 2)
{
}
else
{
}
The problem is that even if the input is double for example 2.2 the if executed.
I also try this:
int n = atoi(&temp);

scanf is difficult to use if you want a very strict validation of the input typed by the user.
Instead you could you use getc to read the input char-by-char and do the validation and value calculation yourself.
Another approach could be fgets combined with sscanf. That could be something like:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 8
int main(void) {
char str[MAX_LEN];
int d, n;
int flag = 0; // Assume it isn't an int
if (fgets(str, MAX_LEN, stdin)) // Read into str
{
size_t l = strlen(str);
if (l > 0) // Check that we did read something
{
if (str[l-1] == '\n') // Last char must be new line
{
if (sscanf(str,"%d%n", &d, &n) == 1) // Try to scan the str into an int
{
if (n == l-1) // Check that all chars was used
{
flag = 1; // It is an int so set the flag
}
}
}
}
}
if (flag)
{
printf("%d\n", d);
}
else
{
printf("Not an int\n");
}
return 0;
}

Related

C getchar loop to get integer input from user - [how to improve]

Is there more elegant way to do this task?
Program asks user for integer and repeats if non-digital characters are entered.
To exit loop two conditions expected:
a) all entered characters are digits
b) last character is '\n'
Short solutions like scanf don’t work properly, other approaches require lots of variables loops and if else conditions. User input is common task and I would like to have proper reusable template.
Subjective opinions are appreciated. Way to simplify this function or advice on another solution. Improve formatting. Reading for more systematic understanding.
#include <stdio.h>
int getIntOnly();
int main() {
int x = 0;
x = getIntOnly();
printf("\nvalue entered is: %d \n", x);
}
int getIntOnly() {
int ch, num, quit, abc;
do {
num = 0;
ch = 0;
quit = 0;
abc = 0;
printf("Enter the input: ");
do {
ch = getchar();
if (ch >= 48 && ch <= 57) {
num = num * 10 + (ch - 48);
}
else if (ch == '\n') {
quit = 1;
}
else {
abc = 1;
}
}
while (quit == 0);
}
while (quit == 0 || abc == 1);
return (num);
}
Using fgets() means you'll get the full text at once.
You can then examine it (and convert it too) to suit your needs.
int getIntOnly( void ) {
int value = 0, i = 0;
char buf[ 64 ];
do {
printf( "Enter integer value: " );
fgets( buf, sizeof( buf ), stdin );
value = 0;
for( i = 0; '0' <= buf[i] && buf[i] <= '9'; i++ )
value = value * 10 + buf[i] - '0';
} while( buf[i] != '\n' ); // good! reached end of line
return value;
}
May be better? Add some validity checks for the result of fgets() and strtol() according to your original code.
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
int getIntOnly();
int main() {
int x = 0;
x = getIntOnly();
printf("\nvalue entered is: %d \n", x);
}
bool isDigit(char ch) {
return (ch >= '0' && ch <= '9')? true : false;
}
bool isAllDigit(char *buf) {
int i;
for (i = 0; buf[i] != '\n'; i++) {
if (isDigit(buf[i]) == false) {
return false;
}
}
return true;
}
bool isVaildInt(long int number) {
return (number >= INT_MIN && number <= INT_MAX)? true : false;
}
int getIntOnly() {
char buf[100];
long int num;
bool done = false;
do {
/* read line-by-line */
fgets(buf, 100, stdin);
if (isAllDigit(buf) == false)
continue;
num = strtol(buf, NULL, 10);
/* strtol() returns long int */
if (isVaildInt(num) == false)
continue;
done = true;
} while (done == false);
return num;
}

How can I check the input in C

I'm trying to write a function that checks input. I've seen some code like this but they didn't get the input until it got int. My function should get the input and check it. It should be used like "check(input)";
Here is something I tried and failed;
char n[10];
fgets(n, sizeof(n), stdin);
strtol(n, NULL, 10);
int i;
for (i = 0; i < strlen(n); i++) {
while(! isdigit(n[i])) {
if (n[i] != '.') {
printf("Wrong! Enter again:");
fgets(n, sizeof(n), stdin);
}
}
}
return buf;
If you simply want to make sure that the input is a valid floating point number, strtod is your friend:
#include <stdlib.h>
#include <errno.h>
double check(const char input[])
{
char* p;
errno = 0;
double n = strtod(input, &p);
if (errno == ERANGE)
;//range error, the input doesn't fit on the type
if (p == input)
;//fail, not a number
return n;
}
There are some cases which pass through this test, but you may not want to, such as nan, or hexadecimal notation, so you need to take care of that.
Thank you so much!
I added a little bit to your solution. Please let me know if there is anything unnecessary or useless.
double check(const char input[]) {
char *p;
errno = 0;
double n = strtod(input, &p);
if (errno == ERANGE) {
//range error, the input doesn't fit on the type
return 0;
} else if (p == input) {
//fail, not a number
return 0;
} else if (*p && *p != '\n' && *p != '.' && *p != ',') {
// *endptr is neither end of string nor newline,
// so we didn't convert the *whole* input
return 0;
}
return n;
}

How to output my results all the way at the end of my program versus at the end of each iteration? (Updated version of previous query)

So my program takes a string, and then outputs it as a marquee sign. I have a for loop so that it may take multiple strings and then outputs each of the strings as a sign.
My problem is: after each iteration, it outputs the sign, and then continues to prompt me for the next string when I want it to just take in all my inputs at once, and then output every sign at the very end. Here is what I'm talking about:
Current Input:
3
Hello World!
5
Sign #1: (This is the output)
[Hello]
[ello ]
[llo W]
[lo Wo]
[o Wor]
[ Worl]
[World]
[orld!]
[rld! ]
[ld! H]
[d! He]
[! Hel]
[ Hell]
Activist
10
Sign #2: (This is the output)
[Activist ]
LOL
2
Sign #3: (This is the output)
[LO]
[OL]
[L ]
[ L]
This is what I want it to do:
Input:
3
Hello World!
5
Activist
10
LOL
2
Output:
Sign #1:
[Hello]
[ello ]
[llo W]
[lo Wo]
[o Wor]
[ Worl]
[World]
[orld!]
[rld! ]
[ld! H]
[d! He]
[! Hel]
[ Hell]
Sign #2:
[Activist ]
Sign #3:
[LO]
[OL]
[L ]
[ L]
Here is my ORIGINAL code:
#include <stdio.h>
#include <string.h>
void ignoreRestOfLine(FILE *fp) {
int c;
while ((c = fgetc(fp)) != EOF && c != '\n');
}
int main() {
int num_times, count = 0;
int marq_length, sign = 0;
scanf("%d ", &num_times);
char s[100];
for (count = 0; count < num_times; count++) {
if (fgets(s, sizeof(s), stdin) == NULL) {
// Deal with error.
}
if (scanf("%d", &marq_length) != 1) {
// Deal with error.
}
ignoreRestOfLine(stdin);
size_t n = strlen(s) - 1;
int i, j;
if (s[strlen(s)-1] == '\n')
s[strlen(s)-1] = '\0';
printf("Sign #%d:\n", ++sign);
if (n <= marq_length) {
printf("[%-*s]\n", marq_length, s);
} else {
for (i = 0; i < n + 1; i++) {
putchar('[');
for (j = 0; j < marq_length; j++) {
char c = s[(i + j) % (n + 1)];
if (!c)
c = ' ';
putchar(c);
}
printf("]\n");
}
}
}
return 0;
}
Here is my UPDATED code, where I added the part of my code that actually outputs the string in a marquee sign into a function. I just don't know how to properly call it back to the main function so it can output all the signs at the very end:
#include <stdio.h>
#include <string.h>
void ignoreRestOfLine(FILE* fp){
int c;
while ( (c = fgetc(fp)) != EOF && c != '\n');
}
char getSign(char s[100], int marq_length);
char getSign(char s[100], int marq_length){
int count =0;
int sign =0;
//char s[100];
if ( fgets(s, sizeof(s), stdin) == NULL )
{
// Deal with error.
}
if ( scanf("%d", &marq_length) != 1 )
{
// Deal with error.
}
ignoreRestOfLine(stdin);
size_t n = strlen(s)-1;
int i,j;
if(s[strlen(s)-1] == '\n')
s[strlen(s)-1] = '\0';
printf("Sign #%d:\n", ++sign);
if (n <= marq_length) {
printf("[%-*s]\n", marq_length, s);
} else {
for (i = 0; i < n + 1; i++) {
putchar('[');
for (j = 0; j < marq_length; j++) {
char c = s[(i + j) % (n + 1)];
if (!c)
c = ' ';
putchar(c);
}
printf("]\n");
}
}
}
int main(){
int i, num_times, sign_length;
char string[100];
scanf("%d", &num_times);
//char *results=malloc(num_times * sizeof(char));
for(i=0 ;i<num_times;i++){
scanf("%s", string);
scanf("%d", &sign_length);
printf((getSign(string, sign_length)));
}
return 0;
}
I think it is good to read all input and then print results because input is short and these size are easy to predict.
Your main() function should be like this
int main(void){
int i, num_times, *sign_length;
char (*string)[100];
/* read number of test cases */
scanf("%d", &num_times);
/* allocate buffer to store input */
sign_length = malloc(sizeof(*sign_length) * num_times);
string = malloc(sizeof(*string) * num_times);
if (sign_length == NULL || string == NULL) {
free(sign_length);
free(string);
return 1;
}
/* read input */
for(i=0 ;i<num_times;i++){
scanf("%99s", string[i]);
scanf("%d", &sign_length[i]);
}
/* process and print */
for(i=0 ;i<num_times;i++){
getSign(string[i], sign_length[i]);
}
/* cleanup */
free(string);
free(sign_length);
return 0;
}
and the part that are trying to destroy the input in getSign()
if ( fgets(s, sizeof(s), stdin) == NULL )
{
// Deal with error.
}
if ( scanf("%d", &marq_length) != 1 )
{
// Deal with error.
}
ignoreRestOfLine(stdin);
have to be deleted.
#include <stdlib.h> have to be added to the head of your code to use malloc() and free().
UPDATE: Here is a program with problems fixed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getSign(char s[100], int marq_length, int case_number);
void getSign(char s[100], int marq_length, int case_number){
size_t n = strlen(s)-1;
size_t i,j;
if (strlen(s) < n) n = 0;
if(s[n] == '\n')
s[n] = '\0';
else
n++;
printf("Sign #%d:\n", case_number);
if (n <= (size_t)marq_length) {
printf("[%-*s]\n", marq_length, s);
} else {
for (i = 0; i < n + 1; i++) {
putchar('[');
for (j = 0; j < (size_t)marq_length; j++) {
char c = s[(i + j) % (n + 1)];
if (!c)
c = ' ';
putchar(c);
}
printf("]\n");
}
}
}
int main(void){
int i, num_times, *sign_length;
char (*string)[100];
/* read number of test cases */
if(scanf("%d", &num_times) != 1) return 1;
/* allocate buffer to store input */
sign_length = malloc(sizeof(*sign_length) * num_times);
string = malloc(sizeof(*string) * num_times);
if (sign_length == NULL || string == NULL) {
free(sign_length);
free(string);
return 1;
}
/* read input */
for(i=0 ;i<num_times;i++){
int dummy;
while((dummy = getchar()) != '\n' && dummy != EOF); /* skip rest of previous line */
if(scanf("%99[^\n]%d", string[i], &sign_length[i]) != 2) {
free(sign_length);
free(string);
return 1;
}
}
/* process and print */
for(i=0 ;i<num_times;i++){
getSign(string[i], sign_length[i], i + 1);
}
/* cleanup */
free(string);
free(sign_length);
return 0;
}
The approach I'd take here is to either store the input until all input is read and only then to generate the output, or to store the output and defer it's printing until the end.
The first is IMHO opinion the better approach, because the amount of data to store is less. OTOH is storing the output a good first step to parallelize taking input and generating output. I go with the later as this is closer to the wording in your question.
OK, your output is basically a C string. So you need to store one of these for each input that you get. Luckily you know even before the first iteration how many inputs you'll get, so you can just allocate the correct amount of space beforehand:
char const ** outputs; // A pointer to (an array of) constant C strings
outputs = malloc(sizeof(*outputs) * numInputs);
Then, you read input as you do it and generate your output into a C string. You've been using a stack allocated (constant size) buffer for that. To be able to reuse that buffer in each iteration you need to copy your result out of it:
char * result = malloc(strlen(sign) + 1);
strcpy(result, sign);
And the store that into your array of outputs:
outputs[currentIteration] = result;
Finally, at the end you print each output and free the allocated memory when done with it:
for (size_t o = 0; o < numOutputs; ++o) {
printf("%s\n", outputs[o]);
free(outputs[o]);
}
At the end, don't forget to also free the array that has been allocated for the outputs:
free(outputs);
Notes: You should check each and every allocation whether it succeeded. Moreover, using a constant sized buffer (on the stack) is OK only if you make absolutely sure that this buffer will never overflow! You should try to pack as much of the above and your sign generation in (small) functions.
Sketch of the overall code:
int main() {
// read how many inputs you'll get
// allocate outputs
// iterate, so that for each input:
// you read the input
// generate the sign
// copy the result into the outputs array
// iterate over all outputs
// print output
// free allocated memory of that output
// free memory for outputs
}
Reading the input and generating the sign should be done in two distinct functions (so its neither the original nor the updated code). Basically I think having these functions should give you a reasonable code structure:
// Read both the string and length, allocating memory for the string
bool read_input(char **string, unsigned * marq_length);
// Could alternatively be done with a fixed buffer
bool read_input(char * string, size_t max_string_size, unsigned * marq_length);
// Note: for bool include stdbool, or use a char instead
And one to generate the sign:
// Store the result in the fixed size buffer at dest, check for overflow!
void generate_sign(char * dest, size_t max_dest_size, char const * input, unsigned marq_length);
Things like printing the outputs could be done directly in main, or in a dedicated function.

How to put text from file into array

I need to read text from a file (text of few sentences) and then write down all unique characters. To do that I need to use an array. I wrote this code but it gives me nothing.
#include <stdio.h>
int main(void) {
int i;
FILE *in = fopen("test.txt", "r");
if (in) {
char mas[50];
size_t n = 0;
int ch;
while ((ch = getc(in)) != EOF) {
mas[n++] = (char)ch;
}
fclose(in);
}
for (i = 0; i < 50; i++) {
printf("%c", mas[i]);
printf("\n");
}
return 0;
}
//low level input output commands method
#include <fcntl.h>
int main()
{
int x,i,n,v=1;
char s[256],str;
for (i=1;i<=255;i++)
s[i]='0';
x=open("out.txt",O_RDONLY);
if (x==-1)
{
printf("Invalid file path");
return 0;
}
while (n!=0)
{
n=read(x,&str,1);
s[(int)str]='1';
v=0;
}
close(x);
for (i=1;i<=255;i++)
if (s[i]=='1')
printf("%c",(char)i);
if (v)
printf("Blank file!");
close(x);
return 0;
}
You have a problem with scope. mas was declared within your if block of code and has no visibility outside the if block. Move the declaration for mas outside the block. You need to keep n outside as well i.e.:
int i;
char mas[50];
size_t n = 0;
Next you fail to limit your read to less than 50 chars and will easily overflow mas. Add a check on n:
while ((ch = getc(in)) != EOF && n < 50) {
Finally limit your write of characters to the number read n:
for(i=0;i<n;i++)
That will compile and run. If you had compiled with warnings enabled, the compiler would have identified the scope problem for you. Always compile with -Wall -Wextra at a minimum.
If you intend to read some char's to your array and print out unique one's check the below code
#include <stdio.h>
int main(void)
{
int i,j,flag;
char mas[50];
size_t n = 0;
FILE *in = fopen("test.txt", "r");
if (in) {
int ch;
while ((ch = getc(in)) != EOF && n < 50) {
mas[n++] = (char)ch;
}
fclose(in);
}
for(i=0;i<n;i++)
{
flag = 0;
for(j=i+1;j<n;j++)
{
if( mas[i] == mas[j])
{
flag = 1;
break;
}
}
if(!flag)
{
printf("%c\n",mas[i]);
}
}
return 0;
}

Convert a set of chars to int from a file

I'm reading:
22:5412:99:00 (...)
From a text file using (ch=fgetc(fp)) != EOF because I don't have only those numbers to read.
Identifying a number is easy with if(ch >= 48 && ch <= 57) but the thing is I want to put those numbers 22, 5412 into an array of integers. However when I read a char it reads part of number since each number is char.
It gets 2 (and not 22 like I want to) and in the next iteration reads the other 2. How can I save each set of numbers into it's own integer?
I hope I was clear enough, thanks!
My idea is to read in each char, and if it is a digit append it to a buffer. Whenever we get a non-digit, we just read the contents of the buffer as a string using sscanf, and clear the buffer for the next value.
#include <stdio.h>
#include <stdlib.h>
int read_buffer(char* buffer, int* sz)
{
int ret;
if (*sz==0) return 0;
buffer[*sz]='\0'; //end the string
sscanf(buffer,"%d", &ret); //read the contents into an int
*sz=0; // clear the buffer
return ret;
}
int main()
{
char buffer[1000];
int sz=0;
char ch;
FILE* input=fopen("input.txt","r");
// "input.txt" contains 22:5412:99:00
while ((ch=fgetc(input))!=EOF)
{
int number;
if (isdigit(ch))
{
buffer[sz++]=ch; // append to buffer
}
else
{
printf("Got %d\n",read_buffer(buffer,&sz)); // read contents of buffer and clear it
}
}
if (sz) // check if EOF occured while we were reading a number
printf("Got %d\n",read_buffer(buffer,&sz));
fclose(input);
return 0;
}
You would need to store the numbers as a string or a char* and use atoi to actually convert it to a number. http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
Assuming your pattern is of the type NN:NNNN:NN:NN, parse on the delimiter, feeding characters into a buffer:
int idx = 0, nIdx = 1;
int firstN, secondN, thirdN, fourthN;
char buf[5];
...
while ((ch=fgetc(fp)) != EOF) {
if (ch != ':') {
buf[idx++] = ch;
}
else {
buf[idx] = '\0';
idx = 0;
switch (nIdx++): {
case 1: firstN = atoi(buf); break;
case 2: secondN = atoi(buf); break;
case 3: thirdN = atoi(buf); break;
}
}
}
buf[idx] = '\0';
fourthN = atoi(buf);
...
I did a full program out of the previous post -- and some testing :-)
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
/* fill `array` with at most `siz` values read from the stream `fp` */
/* return the number of elements read */
size_t fillarray(int *array, size_t siz, FILE *fp) {
int ch;
size_t curr = 0;
int advance_index = 0;
while ((ch = fgetc(fp)) != EOF) {
if (isdigit((unsigned char)ch)) {
array[curr] *= 10;
array[curr] += ch - '0';
advance_index = 1;
} else {
if (advance_index) {
advance_index = 0;
curr++;
if (curr == siz) { /* array is full */
break;
}
}
}
}
return curr + advance_index;
}
int main(void) {
int array[1000] = {0};
int n, k;
n = fillarray(array, 1000, stdin);
if (n > 0) {
printf("%d values read:\n", n);
for (k=0; k<n; k++) {
printf(" %d", array[k]);
}
puts("");
} else {
fprintf(stderr, "no data read\n");
}
return 0;
}
And a test run
$ ./a.out
24555:76423 foobar 76235 jgfs(8) jhg x86-64 passw0rd RS232
[CTRL+D]
8 values read:
24555 76423 76235 8 86 64 0 232

Resources