我试图创建一个验证移动入口的功能,手机号码必须从0开始,并且是11个数字(例如01281220427)。
我想确保程序获得正确的输入。
这是我的尝试:
setInterval
现在,如果我不使用
#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);
}
数组在数字后打印一个新行,除了我的之外还有什么好处?以及如何使此功能优化和缩短?
提前致谢!
修改 我的问题是:1。为什么输入数组最后会打印一个新行? 2.如何缩短此代码? 编辑结束。
答案 0 :(得分:1)
如果您坚持使用sscanf()
,则应以这种方式更改格式:
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]
解析最多11个必须为数字的字符。
%c
读取以下字符,该字符应为尾随'\n'
。
我验证两种格式都已匹配,并且号码以0
(x[0] == '0'
)开头,并且正好有11位数字。
答案 1 :(得分:0)
您正在查看换行符,因为fgets()会一直读取,直到收到EOF或换行符。换行符存储在缓冲区中,之后字符串以'\0'
终止。
另一种方法是直接使用另一个空字节覆盖换行符:input[i-1] = '\0'
(基本上与解决方案完全相同,但保存函数调用)。
对于长度为1的strncmp检查也是如此,您可以直接检查input[0] == '0'
。请注意,您必须与&#39; 0&#39;进行比较。 (char)在这里,不是&#34; 0&#34; (字符串)。
我看到的其他一些事情:
您还可以在sscanf的格式字符串中保留%c
(无论如何您都不会评估它,因为您要检查1作为返回值),这也消除了对char ch
。
此外,您将char x[15]
作为参数传递给您的函数。这有点误导,因为实际传递的是一个指向char数组的指针(尝试使用sizeof(x)
,您的编译器很可能会发出关于sizeof()返回的char *大小的警告。 / p>
你可以做的是抛弃你使用的char数组输入作为临时缓冲区,并使用作为参数移交的缓冲区。为了保存这个,你应该使用第二个funcion参数来指定传递给函数的缓冲区的大小,这将产生如下函数头:
void integerValidation(char *input, size_t len);
有了这个,你必须使用len而不是sizeof(输入)。以下问题提供了更详细的原因:C: differences between char pointer and array 由于您不再使用临时缓冲区,因此可以删除对strcpy()的最终调用。
还有很多检查数字长度/格式。你可以节省一些: 如果您使用%lu而不是%ld,则不会转换任何已签名的数字,从而节省了对num&lt; 0。 您正在检查读取的数字的长度是否为&lt; 11或&gt; 11 - 为什么不检查!= 11?
你在输入缓冲区上调用了strlen()三次(或者仍然使用了返工11的返工检查两次) - 调用它一次是有意义的,将长度保存在变量中并使用该变量从那时起,因为你没有改变通话之间的字符串。
答案 2 :(得分:0)
已经有一个公认的答案,但是对于它的价值,这是另一个答案。
我对您的代码进行了一些更改,首先通过定义电话号码长度和任意更大的字符串长度来避免“魔术数字”。然后没有必要将数组x[15]
传递给函数,因为它不考虑它的长度,也可以使用更简单的*x
指针。接下来,我将失败的所有原因归还给调用者,这更简单。而不是试图将电话号码视为数字条目(注意:字母,空格,连字符,逗号和#有时也可能是电话号码的一部分)我坚持使用字符串。另一个原因是,如果将条目转换为某个大小的int
,则所需的前导零将消失。我删除newline
使用输入行读取的尾随fgets()
,结果就是这样。
#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
}