C 检查表示数字的字符串的有效性
我需要编写一个函数来检查字符串的一些属性:C 检查表示数字的字符串的有效性,c,C,我需要编写一个函数来检查字符串的一些属性: 字符串必须表示正整数(>0) 整数所需内存不得超过32位 字符串中没有字母 如果满足这些条件,它应该将字符串作为int返回,如果不满足这些条件中的任何一个,它应该返回-1 目前,该功能无法处理以下2个输入: 4y 13.4 如果我的isDigit()循环按预期工作,它将能够检查它们。为什么循环不起作用 int convert(const char length[]) { long input = atol(length); if (inpu
4y
13.4
isDigit()
循环按预期工作,它将能够检查它们。为什么循环不起作用
int convert(const char length[]) {
long input = atol(length);
if (input >= 2147483648 || input <= 0) {
return -1;
}
int chkr = 0;
while (chkr < strlen(length)) {
if (isdigit(length[chkr++]) == 0) {
return -1;
}
else {
return atoi(length);
}
}
input = atol(length);
if (length[0] == '0') {
return -1;
}
if (strlen(length) < 3) {
return -1;
}
else {
return atoi(len gth);
}
}
int转换(常量字符长度[]){
长输入=atol(长度);
如果(输入>=2147483648 | |输入,则只检查第一个字符,然后立即返回
input = atol(length);
无法访问。请检查此循环:
while (chkr < strlen(length)) {
if (isdigit(length[chkr++]) == 0) {
return -1;
}
else {
return atoi(length);
}
}
在那之后,这条线在这里
input = atol(length);
不需要。输入仍然具有该值。但不会造成任何伤害。int convert(const char length[]){
int convert(const char length[]) {
if (atol(length) >= 2147483648 || atol(length) <= 0)
return -1;
int chkr = 0;
while (chkr < strlen (length)) {
if (isdigit(length[chkr++]) == 0)
return -1;
}
return atoi(length);
}
if(atol(length)>=2147483648 | | atol(length)如前面所述,而
循环在第一次迭代后返回
使用sscanf
而不是atol
或atoi
。这是最好的选择,因为您可以检测错误:
int convert(const char *length){
int err, sz;
unsigned rtn;
/*%u reads an unsigned integer (mostly 32 bit) >= 0*/
err = sscanf(length, "%u%n", &rtn, &sz);
/*check reading error occured*/
if(err == 0){
return -1;
}
/*check if there is no whitespace/sign*/
if(!isdigit(length[0])){
return -1;
}
/*check if 0 < rtn <= INT_MAX*/
if(rtn <= 0 || rtn > INT_MAX){
return -1;
}
/*check everything got read*/
/*=> no letters*/
if(sz != strlen(length)){
return -1;
}
return rtn;
}
你的函数非常复杂而且错误
改为使用此选项,并让C库完成脏工作:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
// The function you're interested in
int convert(const char string[]) {
char *endptr;
if (!isdigit((unsigned char)string[0]))
return -1;
errno = 0; // need to set errno to 0 (see errno documentation)
long value = strtol(string, &endptr, 10);
if (errno != 0 || value <= 0 || value > 2147483647 || *endptr != 0)
{
return -1;
}
return value;
}
int main() {
// Test different cases:
struct {
const char *input;
int expected;
} testcases[] =
{
// OK cases
"123", 123,
"1234", 1234,
"2147483647", 2147483647,
// fail cases
"-1234", -1, // number is negatif
"12.3", -1, // contains non digit '.'
"123y", -1, // contains non digit 'y'
"2147483648", -1, // out of range
" 123", -1, // starts with a space
// wrong test case on purpose
"1234", 1245,
};
// Test all test cases
for (int i = 0; i < sizeof(testcases) / sizeof(testcases[0]); i++)
{
int value = convert(testcases[i].input);
if (value != testcases[i].expected)
{
printf("convert(\"%s\") failed, returned value = %d, expected value = %d\n", testcases[i].input, value, testcases[i].expected);
}
else
{
printf("convert(\"%s\") passed\n", testcases[i].input);
}
}
return 0;
}
为此,我宁愿使用strtol
。还请展示一些有效和无效字符串的示例,并告诉我们“3整数字符串”是什么。我建议length
通常不是字符串的好名称-当然是在提供的代码上下文中。学会使用调试器。永远不要使用atol()
(或atoi()
或atol()
)。发件人:“…atoi()
未检测到错误。”那么,你为什么不让编译器为你做这项工作,编写'0'
而不是48
和'9'
而不是57
?糟糕的重新设计是一个非常错误的想法,充其量是一个想法。我只想感谢大家的讨论。感觉我已经学到了一个绝对的教训,我的问题已经解决了已解决!1)isdigit未正确编码字符<0。2)不接受“+123”。问题要求的是正整数。我也不接受+123。感谢您对整理代码的回复。虽然函数现在更简单,但它现在无法将任何输入字符串转换为输出数字…我只想对所有讨论的人说声谢谢。感觉我已经学会了一个绝对的shedload,我的问题就这么解决了lved!isdigit需要一个在无符号字符范围或EOF中的值。对于字符,代码风险为UB。“isdigit((无符号字符)长度[…])是谨慎的。这将在“4000000000”上失败。printf(“%d\n”,convert(“5000000000”))
返回705032704
,我希望OP想要-1
。重点是,在扫描文本以保存在未签名的中时,溢出是未定义的行为。%u
是合理的,但不可靠。
/*these fail*/
const char zero[] = "0";
const char spaceStart[] = " 84654";
const char spaceEnd[] = "84654 ";
const char negative[] = "-7869";
const char tooBig[] = "2147483648";
const char fitsInto32BitInt[] = "2147483647";
const char positive[] = "+7526";
const char withLetter[] = "4y";
const char withPoint[] = "13.4";
/*these work*/
const char one[] = "1";
const char fine[] = "746838";
const char fitsInto32BitInt[] = "2147483647";
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
// The function you're interested in
int convert(const char string[]) {
char *endptr;
if (!isdigit((unsigned char)string[0]))
return -1;
errno = 0; // need to set errno to 0 (see errno documentation)
long value = strtol(string, &endptr, 10);
if (errno != 0 || value <= 0 || value > 2147483647 || *endptr != 0)
{
return -1;
}
return value;
}
int main() {
// Test different cases:
struct {
const char *input;
int expected;
} testcases[] =
{
// OK cases
"123", 123,
"1234", 1234,
"2147483647", 2147483647,
// fail cases
"-1234", -1, // number is negatif
"12.3", -1, // contains non digit '.'
"123y", -1, // contains non digit 'y'
"2147483648", -1, // out of range
" 123", -1, // starts with a space
// wrong test case on purpose
"1234", 1245,
};
// Test all test cases
for (int i = 0; i < sizeof(testcases) / sizeof(testcases[0]); i++)
{
int value = convert(testcases[i].input);
if (value != testcases[i].expected)
{
printf("convert(\"%s\") failed, returned value = %d, expected value = %d\n", testcases[i].input, value, testcases[i].expected);
}
else
{
printf("convert(\"%s\") passed\n", testcases[i].input);
}
}
return 0;
}
convert("123") passed
convert("1234") passed
convert("2147483647") passed
convert("-1234") passed
convert("12.3") passed
convert("123y") passed
convert("2147483648") passed
convert("1234") failed, returned value = 1234, expected value = 1245