I'm trying to make a function to validate mobile entry, the mobile number MUST starts with 0 and is 11 numbers (01281220427 for example.)
I want to make sure that the program gets the right entry.
This is my attempt:
#include <stdio.h>
#include <strings.h>
void integerValidation(char x[15]);
int main(int argc, char **argv)
{
char mobile[15];
integerValidation(mobile);
printf("%s\n\n\n", mobile);
return 0;
}
void integerValidation(char x[15]){
char input[15];
long int num = -1;
char *cp, ch;
int n;
printf("Please enter a valid mobile number:");
while(num<0){
cp = fgets(input, sizeof(input), stdin);
if (cp == input) {
n = sscanf(input, "%ld %c", &num, &ch);
if (n!=1) {printf("ERROR! Please enter a valid mobile number:");
num = -1;
}
else if (num<0)
printf("ERROR! Please enter a valid mobile number:");
else if ((strlen(input)-1)>11 || (strlen(input)-1)<11 || strncmp(&input[0], "0", 1) != 0){
printf("ERROR! Please enter a valid mobile number:");
num = -1;
}
}
}
long int i;
i = strlen(input);
//Because when I try to print it out it prints a line after number.
strcpy(&input[i-1], "");
strcpy(x, input);
}
Now, if I don't use
strcpy(&input[i-1], "");
the array prints a new line after the number, what would be a good fix other than mine? and how can I make this function optimized and shorter?
Thanks in advance!
Edit:
My question is: 1. Why does the input array prints a new line in the end?
2. How can I make this code shorter?
End of edit.
If you insist on using sscanf(), you should change the format this way:
int integerValidation(char x[15]) {
char input[15], c;
printf("Please enter a valid mobile number:");
while (fgets(input, sizeof(input), stdin)) {
if (sscanf(input, "%11[0123456789]%c", x, &c) == 2
&& x[0] == '0' && strlen(x) == 11 && c == '\n') {
// number stored in `x` is correct
return 1;
}
printf("ERROR! Please enter a valid mobile number:");
}
x[0] = '\0'; // no number was input, end of file reached
return 0;
}
%12[0123456789] parses at most 11 characters that must be digits.
%c reads the following character, which should be the trailing '\n'.
I verify that both formats have been matched, and the number starts with 0 (x[0] == '0') and it has exactly 11 digits.
You're seeing the newline, since fgets() reads until an EOF or a newline is received. The newline is stored in the buffer, and after that the string is terminated with '\0'.
An alternative would be to directly overwrite the newline with another null-byte: input[i-1] = '\0' (which basically does the same thing as your solution, but saves a function call).
The same goes for the check with strncmp with length 1, you can directly check input[0] == '0'. Note that you have to compare against '0' (char) here, not "0" (string).
A few other things I'm seeing:
You can also spare the %c in the format string for sscanf (you're never evaluating it anyway, since you're checking for 1 as return value), which also eliminates the need for char ch.
Also, you're passing char x[15] as argument to your function. This is a bit misleading, because what actually gets passed is a pointer to a char array (try using sizeof(x), your compiler will most likely issue a warning about the size of char * being returned by sizeof()).
What you could do is to ditch the char array input, which you're using as temporary buffer, and use the buffer which was handed over as argument. For this to be save, you should use a second funcion parameter to specify the size of the buffer which was handed to the function, which would result in a function header like as follows:
void integerValidation(char *input, size_t len);
With this, you'd have to use len instead of sizeof(input). The following question provides more detail why: C: differences between char pointer and array
Since you're not using a temporary buffer anymore, you can remove the final call to strcpy().
There are also a lot of checks for the number length/format. You can save a few:
If you use %lu instead of %ld no signed numbers are being converted, which saves you the check for num < 0.
You're checking whether the length of the read number is <11 or >11 - why not just check for !=11?
You're calling strlen() three times on the input-buffer (or still twice with the reworked check for lengh 11) - it makes sense to call it once, save the length in a variable and use that variable from then on, since you're not altering the string between the calls.
There is already an accepted answer, but for what it's worth, here is another.
I made several changes to your code, firstly avoiding "magic numbers" by defining the phone number length and an arbitrarily greater string length. Then there is no point passing an array x[15] to a function since it pays no regard to its length, might as well use the simpler *x pointer. Next, I return all reasons for failure back to the caller, that's simpler. And instead of trying to treat the phone number as a numeric entry (note: letters, spaces, hyphens, commas and # can sometimes be a part of phone number too) I stick to a character string. Another reason is that the required leading zero will vanish if you convert the entry to an int of some size. I remove the trailing newline that fgets() reads with the input line, and the result is this.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXLEN 11
#define STRLEN (MAXLEN+10)
int integerValidation(char *x);
int main(int argc, char **argv)
{
char mobile[STRLEN];
while (!integerValidation(mobile)) // keep trying
printf("Invalid phone number\n");
printf("%s\n\n\n", mobile); // result
return 0;
}
int integerValidation(char *x)
{
int i, len;
printf("Please enter a valid mobile number:");
if(fgets(x, STRLEN, stdin) == NULL) // check bad entry
return 0;
x [ strcspn(x, "\r\n") ] = 0; // remove trailing newline etc
if((len = strlen(x)) != MAXLEN) // check length
return 0;
if(x[0] != '0') // check leading 0
return 0;
for(i=1; i<len; i++) // check all other chars are numbers
if(!isdigit(x[i]))
return 0;
return 1; // success
}
Related
Hi I'm having a really hard time reading user input in C a specific way...
I want to read a users input, in which case my program will verify the first three characters as characters and the last four digits as digits.
And I don't know how to make sure that their input is 7 characters in total (3 chars, 4 ints) ex: ULI0788.
I don't want to use arrays, ex arr[12];
Currently I am at the point where I'm learning memory allocation & pointers, thus I am encouraged to use this rather than arrays if possible
for example
char itemID;
printf("Enter an ID of ITEM. (max 3 characters, 4 digits)");
scanf("%s", itemID);
I've done some googling and tried user suggestions but none do both of what I'm looking for, verifying each character/digit and setting a max of 7 total characters/digits. Or I just don't understand properly how to use the suggestions
googled
googled2
googled3
googled4
googled5
googled6
googled7
googled8
googled9
googled10
"I want to read a users input, in which case my program will verify the first three characters as characters and the last four digits as digits. And I don't know how to make sure that their input is 7 characters in total (3 chars, 4 ints)...I don't want to use arrays"
Without the ability to use C strings, the above is constrained to simply inputting a series of characters, then treating and testing them as discrete items:
bool test7char(void)
{
int Char;
for(int i=0;i<7;i++)
{
Char = getc(stdin);
if(i<3)
{
if(!isalpha(Char)) return false;
}
else if(!isdigit(Char)) return false;
}
return true;
}
Usage:
int main(void)
{
printf("Enter an ID of ITEM. (max 3 characters, 4 digits)");
while(!test7char())
{
printf("Mistake - Re-enter an ID of ITEM. (max 3 characters, 4 digits)");
}
return 0;
}
EDIT - "I am just trying to figure out how to answer my question using memory allocation & maybe pointers"
Using pointer: (In memory, this pointer will point to a series of alphanumeric characters, terminated by \0, i.e. a string.)
#define STR_SIZE 7 + 1
BOOL test7char(const char *str);
int main(void)
{
char *str = calloc(STR_SIZE, 1);
if(str)
{
printf("Enter an ID of ITEM. (max 3 characters, 4 digits)");
if(fgets(str, STR_SIZE, stdin))
{
while(!test7char(str))
{
printf("\nMistake - Re-enter an ID of ITEM. (max 3 characters, 4 digits)");
if(!fgets(str, STR_SIZE, stdin))
{
//message user of error
break;
}
}
}
free(str);
}
return 0;
}
bool test7char(const char *str)
{
if(!str) return false;
if(strlen(str) != STR_SIZE -1) return false;
for(int i=0;i<7;i++)
{
if(i<3)
{
if(!isalpha(str[i])) return false;
}
else if(!isdigit(str[i])) return false;
}
return true;
}
I would advise you to use both fgets and sscanf:
fgets allows you to read a certain number of characters (which can be read from stdin).
sscanf allows you to read formatted input from a string (which you got from fgets).
By combining those, you can read 7 characters from standard input (8 if you add the \0) and then parse those to get the two values you're looking for.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
// 8 chars long for string and terminating `\0`
char *ID = calloc(8, 1);
// extra char for same reason as above
char *IDchar = calloc(4, 1);
int IDnum, processed;
// get the string and verify it's 7 characters long
if (fgets(ID, 8, stdin) && strlen(ID) == 7)
sscanf(ID, "%3s%4d%n", IDchar, &IDnum, &processed);
if (processed == 7)
printf("success");
else
printf("failure");
}
The %n will collect the number of characters processed by the sscanf, ensuring you parsed the right number of characters.
note that this is a VERY dangerous parameter, and you should always verify your input length before using it.
Edit:
If you do not want to use arrays at all, and only want to verify the input format without storing or reusing it, you can use getc to read the characters one at a time and verify their value:
#include <stdio.h>
#include <ctype.h>
int isEnd(int c)
{
return c == '\n' || c == EOF;
}
void main()
{
int tmp;
int valid = 1;
//check the first 3 characters
for(int v = 0; v < 3 && valid; v++)
{
// read a char on standard input
tmp = fgetc(stdin);
// check if tmp is a letter
valid = islower(tmp) || isupper(tmp);
}
//check the next 4 characters
for(int v = 0; v < 4 && valid; v++)
{
// read a char on standard input
tmp = fgetc(stdin);
// check if tmp is a numeral
valid = isdigit(tmp);
}
if (valid)
{
printf("format OK\n");
// Check that the input is finished (only if format is OK)
tmp = fgetc(stdin);
if (isEnd(tmp))
printf("length OK\n");
else
printf("length KO: %d\n", tmp);
}
else
{
printf("format KO\n");
}
}
As I said before, this will only check the validity of the input, not store it or allow you to reuse it. But it does not use arrays.
Edit 2:
Another thing to watch out for with fgetc or getc is that, though it will manage longer inputs properly, it will get stuck waiting for the chars to be provided if there aren't enough. Thus make sure to exit the moment you read an incorrect character (if it's an end-of-line char, there won't be any more coming)
Edit 3:
Of course I'd forgotten malloc.
Edited the first answer.
(Sorry for my bad english !)
I wrote a program that asks you to type a password no longer than a certain number, eight characters in this case. The characters that pass the limit will be cut out from the array:
#include <stdio.h>
#define MAXCHAR 8
main()
{
char password[MAXCHAR];
int i;
char c;
printf("Insert password: MAX 8 CHARS!\n\n");
for(i = 0; i <= MAXCHAR; i++){
c = getchar();
if(i == MAXCHAR){
break;
}
else{
password[i] = c;
}
}
printf("%s\n", password);
}
So the program works BUT there is a "strange" problem. If the limit IS EIGHT and I type a password longer than eight characters
(Example: P455w0rds98)
the output will be like this:
P455w0rd☺
So it puts a smiley at the end and I don't know why. It happens only if a the limit is established at eight.
You must specify the length to print or terminate the string. Otherwise, you will invoke undefined behavior. Try this, in which the latter method is implemented.
#include <stdio.h>
#define MAXCHAR 8
int main(void)
{
char password[MAXCHAR + 1]; /* allocate one more element for terminating null-character */
int i;
char c;
printf("Insert password: MAX 8 CHARS!\n\n");
for(i = 0; i <= MAXCHAR; i++){
c = getchar();
if(i == MAXCHAR){
break;
}
else{
password[i] = c;
}
}
password[MAXCHAR] = '\0'; /* terminate the string */
printf("%s\n", password);
}
Some people say that the if(i == MAXCHAR){ break; } part doesn't look good, so here is another code example:
#include <stdio.h>
#define MAXCHAR 8
int main(void)
{
char password[MAXCHAR + 1]; /* allocate one more element for terminating null-character */
int i;
printf("Insert password: MAX 8 CHARS!\n\n");
/* read exactly 8 characters. To improve, breaking on seeing newline or EOF may be good */
for(i = 0; i < MAXCHAR; i++){
password[i] = getchar();
}
password[MAXCHAR] = '\0'; /* terminate the string */
getchar(); /* to match number of call of getchar() to the original: maybe for consuming newline character after 8-digit password */
printf("%s\n", password);
}
All C-style strings have a terminal \0 character (value 0). This is unique from any other character value, so it can be used to signal the end of the string. The smiley face you observe is just a part of some neighboring memory block that happens to have a null character after the first byte (hence there being only one extra character). The printf function reads bytes from the string given to it, until it sees the \0. To solve your problem, you can either write
password[MAXCHAR] = '\0';
(You will need to reserve one additional byte in your array, for the \0).
Or you can zero-out your array from the get-go:
char password[MAXCHAR + 1] = { };
Or using memset:
memset(password, '\0', sizeof password);
Apart from the answer you already received from MikeCAT, an alternate approach would be to make use of fgets() to read the user input.
In that case , you don't need to keep a count on each character input, you can specify the max size and get done with it. Something like
fgets(password, MAXCHAR, stdin);
can get the job done for you, minus the looping and assignment for each element.
One thing to remember, however, for shorter inputs than the given length, fgets() reads and stores the trailing newline also, you may need to get rid of that manually. Read the linked man page for more ideas.
That said, main() is a very bad and almost non-standard for hosted environments. You should use int main(void), at least to conform to the standards.
This program essentially asks for a secret string, then asks a user to repeatedly guess single chars of that string until he guesses it all. It works however every second time the while loop is run it skips user input for the guessed char. How do I fix this?
int main(){
char guess;
char test2 [50];
char * s = test2;
char output [50];
char * t = output;
printf("Enter the secret string:\n");
fgets(test2, 50, stdin);
for (int i=0;i<49;i++){ //fills ouput with _ spaces
*(output +i)='_';
while(strcmp(s,t) != 0){
printf("Enter a guess:");
scanf("%c",&guess);
printf("You entered: %c\n", guess);
showGuess(guess,s, t ); // makes a string "output" with guesses in it
printf("%s\n",t);
}
printf("Well Done!");
}
For a quick and dirty solution try
// the space in the format string consumes optional spaces, tabs, enters
if (scanf(" %c", &guess) != 1) /* error */;
For a better solution redo your code to use fgets() and then parse the input.
As pointed out in some other answers and comments, you need to "consume" the "newline character" in the input.
The reason for that is that the input from your keyboard to the program is buffered by your shell, and so, the program won't see anything until you actually tell your shell to "pass the content of its buffer to the program". At this point, the program will be able to read the data contained in the previous buffer, e.g. your input, followed by one the character(s) used to validate your input in the shell: the newline. If you don't "consume" the newline before you do another scanf, that second scanf will read the newline character, resulting in the "skipped scanf" you've witnessed. To consume the extra character(s) from the input, the best way is to read them and discard what you read (what the code below does, notice the
while(getc(stdin) != '\n');
line after your scanf. What this line does is: "while the character read from stdin is not '\n', do nothing and loop.").
As an alternative, you could tell your shell to not buffer the input, via the termios(3) functions, or you could use either of the curses/ncurses libraries for the I/O.
So here is what you want:
int main(){
char guess;
char test2 [50];
char * s = test2; // 3. Useless
char output [50];
char * t = output; // 3. Useless
int i; // 8. i shall be declared here.
printf("Enter the secret string:\n");
fgets(test2, 50, stdin);
for (i=0;i<50;i++) if (test2[i] == '\n') test2[i] = '\0'; // 4. Remove the newline char and terminate the string where the newline char is.
for (int i=0;i<49;i++){ // 5. You should use memset here; 8. You should not declare 'i' here.
*(output +i)='_';
} // 1. Either you close the block here, or you don't open one for just one line.
output[49] = '\0'; // 6. You need to terminate your output string.
while(strcmp(s,t) != 0){ // 7. That will never work in the current state.
printf("Enter a guess:");
scanf("%c",&guess);
while(getc(stdin) != '\n');
printf("You entered: %c\n", guess);
showGuess(guess,s, t );
printf("%s\n",t);
}
printf("Well Done!");
return 0; // 2. int main requires that.
}
Other comments on your code:
You opened a block after your for loop and never closed it. That might be causing problems.
You declared your main as a function returning an integer... So you should at least return 0; at the end.
You seem to have understood that char * t = output; copies output's value and uses t as a name for the new copy. This is wrong. You are indeed copying something, but you only copy the address (a.k.a reference) of output in t. As a result, output and t refer to the same data, and if you modify output, t will get modified; and vice versa. Otherwise said, those t and s variables are useless in the current state.
You also need to remove the newline character from your input in the test2 buffer. I have added a line after the fgets for that.
Instead of setting all the bytes of an array "by hand", please consider using the memset function instead.
You need to actually terminate the output string after you "fill" it, so you should allocate a '\0' in last position.
You will never be able to compare the test2 string with the output one, since the output one is filled with underscores, when your test2 is NULL terminated after its meaningful content.
While variables at the loop scope are valid according to C99 and C11, they are not standard in ANSI C; and it is usually better to not declare any variable in a loop.
Also, "_ spaces" are called "underscores" ;)
Here is a code that does what you want:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 50
int main()
{
char phrase[LEN];
char guessed[LEN];
char guess;
int i, tries = 0;
puts("Please enter the secret string:");
if(fgets(phrase, LEN, stdin) == NULL)
return 1;
for(i = 0; i < LEN && phrase[i] != '\n'; i++); // Detect the end of input data.
for(; i < LEN; i++) // For the rest of the input data,
phrase[i] = '_'; // fill with underscores (so it can be compared with 'guessed' in the while loop).
phrase[LEN - 1] = '\0'; // NULL terminate 'phrase'
memset(guessed, '_', LEN); // Fill 'guessed' with underscores.
guessed[LEN - 1] = '\0'; // NULL terminate 'guessed'
while(strcmp(phrase, guessed) != 0) // While 'phrase' and 'guessed' differ
{
puts("Enter a guess (one character only):");
if(scanf("%c", &guess) != 1)
{
puts("Error while parsing stdin.");
continue;
}
if(guess == '\n')
{
puts("Invalid input.");
continue;
}
while(getc(stdin) != '\n'); // "Eat" the extra remaining characters in the input.
printf("You entered: %c\n", guess);
for(i = 0; i < LEN; i++) // For the total size,
if(phrase[i] == guess) // if guess is found in 'phrase'
guessed[i] = guess; // set the same letters in 'guessed'
printf("Guessed so far: %s\n", guessed);
tries++;
}
printf("Well played! (%d tries)\n", tries);
return 0;
}
Feel free to ask questions in the comments, if you are not getting something. :)
Newline character entered in the previous iteration is being read by scanf. You can take in the '\n' by using the getc() as follows:
scanf("%c",&guess);
getc(stdin);
..
This changed worked for me. Though the right explanation and c leaner code is the one given by #7heo.tk
Change
scanf("%c",&guess);
with
scanf(" %c",&guess);
It should ignore '\n'.
I have this code to validate user input. Condition: value entered should be a zero or positive number only. Negative values and alphabetic characters are not accepted.
Here is my code for this, that just keeps on looping:
#include <stdio.h>
int main ()
{
int a, b, c, d;
printf ("enter value for a:");
do {
b = 0;
scanf ("%d", &a);
if (!isdigit(a)) {
printf("Number must be numeric!:\n");
b++;
}
else if (a < 0) {
printf ("number must be postive\n");
b++;
} else {
printf("\neverything is goood\n");
}
} while (b != 0);
}
isdigit() is expecting an ASCII encoded character, however scanf with the %d argument is converting an ASCII encoded number (a string) into an actual number.
ie. If you input '1', with the ASCII code of 0x31, scanf("%d",... will convert this to the value 1. The ASCII code of 1 is not numeric.
To fix this, either:
Make a type char and use the scanf format specifier %c, then isdigit() will do what you want it to.
Use strtol to read in more than one character and perform your own error checking with the char **endptr argument.
Also, you should turn up your compiler warnings and include the header file that contains the isdigit() function, ctype.h.
Once a user makes a mistake, b is always > 0. You need to add a line that sets b = 0 after correct information is entered (i.e. after your printf("\neverything is good\n"); statement. Just be certain to add { & } to the else statement preceding it, so that the printf & new b = 0; statement will be included in that branch)
Here are few issues with your code that I can spot:
You use scanf with %d format specifier that already parses an input as integer value. Thus, there is no need to check if it is numeric with isdigit. In fact, isdigit is checking a decimal digit character, so your usage is incorrect.
You never check for scanf return. You should. In case there was an error (i.e. value was non-numeric), the input is not removed from the stream. In other words, you will get stuck trying to parse the same bad value over and over.
You have unused variables and forgot to include certain header files. But these are minor things in your case (but could be major in certain situations!).
That being said, here is some code that might work out for you:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
static void skip_input(FILE *stream)
{
int c;
do {
c = fgetc (stream);
} while (c != EOF && c != '\n');
}
int main()
{
int a;
int r;
printf("Please enter a value: ");
for (;;) {
r = scanf("%d", &a);
if (r == EOF)
return EXIT_FAILURE;
if (r != 1) {
printf("Number must be numeric!\n");
skip_input(stdin);
} else if (a < 0) {
printf("Number must be postive\n");
skip_input(stdin);
} else {
printf("Everything is goood\n");
break;
}
}
return EXIT_SUCCESS;
}
Hope it helps.
You are using b as your error flag.
In the "everything is good block", try setting b=0;
Additionally, if you do that, you can get rid of the b++; lines, and simply initialize b=1;
You should only be doing b++ if you need to report how many times the user messed up, which I am presuming you don't need?
There are a couple of problems here.
The first is that the return value of scanf() isn't being checked. If input is available then scanf returns the number of variables that were assigned, which can be 0 or 1 in this case (because you're only attempting to assign one variable). If the user enters a non-numeric character then the loop will execute repeatedly without ever waiting for more user input because there's input available but it'll never match your "%d" conversion. If you want to use scanf() then you'll have to check the return value. If the return value is zero then a non-numeric value was entered, which means that you'll have to clear that value out of the input buffer by reading until the end of the line. If the return value is equal to EOF then either an I/O error occurred or you reached the end of the stream. If the return value is 1 then you know that the value was numeric, which brings me to the next problem.
The routine, isdigit(), takes an integer argument, but it expects that integer value to represent a character. Since you're using scanf() to convert the input to an integer, the value stored in a no longer represents a character; it represents an actual number. Because of this, the call to isdigit() will only return a true value if the user enters a number that corresponds to a digit character. In my locale, that means that the validation will only succeed if the user enters a number between 48 and 57, inclusive. If you're using scanf() then the isdigit() check is not necessary because scanf() will return a value of 1 only if the user entered a numeric value.
To be honest, however, I wouldn't use scanf() to read in user input if I could avoid it precisely because of the need to flush the input buffer if the user enters something wrong. I'm not entirely sure what your requirements are, but I'll assume that you're supposed to read a positive integer from the command line and that the number of digits doesn't matter.
In this case, you'll probably want to use fgets() to read the user input then use strtol() to convert the value to a signed long integer and perform the validation at the same time:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
int main () {
long result;
long len;
int is_valid = 0;
char buf[128];
char *arg;
char *end;
while (!is_valid) {
/* Prompt the user for the integer. */
printf("Enter a non-negative integer: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
printf("Giving up so soon?\n");
break;
}
/* Verify that the input doesn't exceed our buffer length. */
len = strlen(buf);
if (buf[len] != '\n') {
printf("Input buffer length exceeded - aborting.\n");
exit(1);
}
/* Skip any leading whitespace. */
for (arg = buf; isspace(*arg); arg++);
/* Attempt to convert the argument. */
errno = 0;
result = strtol(arg, &end, 10);
if (errno == EINVAL) {
printf("Please enter a numeric value.\n");
continue;
}
if (errno == ERANGE) {
printf("Numeric value out of range.\n");
continue;
}
/* Check for non-whitespace characters after the end of the integer. */
for (; isspace(*end); end++);
if (*end != '\0') {
printf("Please enter a numeric value.\n");
continue;
}
/* Verify that the number is non-negative. */
if (result < 0) {
printf("Please enter a positive value.\n");
continue;
}
/* The number is valid. */
printf("Excellent!\n");
is_valid = 1;
}
return 0;
}
This isn't perfect; aborting if the input buffer length is exceeded isn't exactly user-friendly. It should take care of the validation problem, however.
I don't know how to work with scanf and get the input of it for the entry of the function readBigNum I want to make array until the user entered the Enter and also I want to write a function for assigning it into an array and return the size of the large number
I want readBigNum to exactly have the char *n but I can not relate it in my function
#include <stdio.h>
int readBigNum(char *n)
{
char msg[100],ch;
int i=0;
while((ch=getchar())!='\n')
{
if(ch!='0'||ch!='1'||ch!='2'||ch!='3'||ch!='4'||ch!='5'||ch!='6'||ch!='7'||ch!='8'||ch!='9')
return -1;
msg[i++]=ch;
}
msg[i]='\0';
i=0;
return i;
}
int main()
{
const char x;
const char n;
n=scanf("%d",x);
int h=readBigNum(&n);
printf(h);
}
If I understand your question correctly, you want to implement a function that will read numbers from stdin storing them in a buffer. If a non-number is encountered, you want to return -1. If a new-line is encountered, you want to return the number of characters that were read. If that's correct, you'll probably want your code to look something like the following:
#include <stdio.h>
int readBigNum(char* n)
{
char ch;
int i=0;
while ((ch = getchar()) != '\n') {
if (ch < '0' || ch > '9') {
return -1;
}
n[i++] = ch;
}
n[i] = '\0';
return i;
}
int main(void) {
char buf[100];
int bytes = readBigNum(buf);
printf("%s\n", buf);
printf("%d\n", bytes);
};
The main differences from your implementation
The array to be populated is initialized in main and passed to the readBigNum function. This is a little simpler than having the function control the memory, in which case you would need likely need to deal with malloc and free. Even with this, you run the risk of a buffer overrun and will likely want to take additional precautions to prevent that.
The function does not set i to 0 before returning it. The original code could never return a value other than -1 (on error) or 0, which didn't appear to be the intent.
This code doesn't use scanf. Given your description of what you wanted to accomplish, using scanf didn't appear to be a good fit, however if you provide more information on why you were calling it might help to inform this answer.
The printf call was incorrect, it has been updated to print the number of bytes returned, and an additional printf call was added to print the updated buffer.
Remember that getchar() returns type int, not char. This is because the function may return EOF (which is defined as a negative integer with no particular value).
Also, for functions that deal with buffers, it is always a good idea to take an extra argument that describes the size of the array. This helps reduce buffer overruns because you know how far you can go. With your existing function, if the user types more than 100 characters, your buffer is overrun.
#include <stdio.h>
#include <ctype.h>
int readBigNum(char *n, size_t len)
{
int ch;
int i = 0;
// we make sure 'i' is less than 'len - 1' to leave space for '\0'
while((ch = getchar()) != EOF && i < (len - 1))
{
if (ch == '\n') // stop on linefeed
break;
else if (!isdigit(ch))) // abort on invalid character
return -1;
else
n[i++] = (char) ch;
}
msg[i] = '\0';
return i;
}
int main(void)
{
char buf[100];
int result = readBigNum(buf, sizeof buf);
if (result > 0)
printf("Length %d : %s\n", result, buf);
else
printf("Invalid number!\n");
}