【发布时间】:2014-07-02 09:47:44
【问题描述】:
我对从字符串到整数的转换有疑问。 我通过函数 fgets 得到一个字符串,然后我使用 strtol 函数将其转换为 int。 这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
int main(void)
{
char buf[BUFSIZ];
char *p = NULL;
long int val;
int numero;
int temp;
do
{
temp=0;
printf ("Enter a number: ");
if (fgets(buf, sizeof(buf), stdin) != NULL)
{
val = strtol(buf, &p, 10);
if(buf==p)
{
printf(" no digits \n");
temp=1;
}
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0))
{
perror("strtol");
temp=1;
}
if (*p != '\0')
{
printf("you have insert any char character \n");
temp=1;
}
}
else
{
printf("Error\n");
temp=1;
}
}
while(temp == 1);
/* If we got here, strtol() successfully parsed a number */
numero=(int)val;
printf("***** The number is : %d ******* \n",numero);
return 0;
}
这个代码不起作用,但是如果我替换这个控件,它就可以工作
if (*p != '\0')
{
printf("you have insert any char character \n");
temp=1;
}
有了这个:
if (*p != '\n')
{
printf("you have insert any char character \n");
temp=1;
}
你知道为什么吗? :)
编辑: 这是我最终功能版本的代码 :) 感谢所有 :) 现在看来一切正常:
int readIN(int *numero)
{
long int val;
char buf[BUFSIZ];
char *p = NULL;
if (fgets(buf, sizeof(buf), stdin) != NULL)
{
val = strtol(buf, &p, 10);
if(buf==p)
{
return 1;
}
if ( (val > INT_MAX || val < 0) || (errno != 0 && val == 0))
{
return 1;
}
if (*p != '\n' && *p != '\r' && *p != '\0')
{
return 1;
}
}
else
{
return 1;
}
*numero=(int)val;
return 0;
}
【问题讨论】:
-
fgets将\n留在缓冲区中。strtol将p留在它成功处理的最后一个数字之后的下一个字符处,如果您输入了一些数字并按 Enter,则为\n。 -
并且因为我使用 fgets 来获取字符串,如果一切正常,因此 strtol 留在 p \n 中!在 man strtol 我读到:“如果 endptr 不是 NULL,strtol() 将第一个无效字符的地址存储在 *endptr。如果根本没有数字,strtol() 将 nptr 的原始值存储在 *endptr (并返回 0)。特别是,如果 *nptr 不是 '\0' 但 **endptr 在返回时是 '\0',则整个字符串都是有效的。”而且我认为 strtol 留在 p '\0' 而不是它成功处理的最后一个数字之后的下一个字符! :D
-
第一个无效字符是
\n。strtol不改变任何字符,它使p指向您输入中的某个位置 -
1) 在
strtol()呼叫之前需要errno = 0。小问题:2)if (errno == ERANGE)就足够了,不需要测试返回值。 3) 不确定为什么您的最终代码使用val < 0而不是val < INT_MIN, just want non-negative numbers? 4)(errno != 0 && val == 0)` 可能是错误的。建议(errno)。