NO53、表示数值的字符串(好题,可以再刷一遍)

判断字符串是否表示数值
53、表示数值的字符串 好题,可以再刷一遍

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

示例1
输入

"123.45e+6"

返回值

true

示例2
输入

"1.2.3"

返回值

false

1、看的写法,很好

 bool isNumeric(char* string)
    {
             // 正反标记符号、小数点、e是否出现过
	bool sign = false, decimal = false, hasE = false;
	for (int i = 0; i < strlen(string); ++i) {
		if (string[i] == 'e' || string[i] == 'E') {
			if (i == strlen(string) - 1) return false; // e后面一定要接数字
			if (hasE) return false;  // 不能同时存在两个e
			hasE = true;
		}
		else if (string[i] == '+' || string[i] == '-') {
			// 第二次出现+-符号,则必须紧接在e之后
			if (sign && string[i - 1] != 'e' && string[i - 1] != 'E') return false;
			// 第一次出现+-符号,且不是在字符串开头,则也必须紧接在e之后
			if (!sign && i > 0 && string[i - 1] != 'e' && string[i - 1] != 'E') return false;
			sign = true;
		}
		else if (string[i] == '.') {
			// e后面不能接小数点,小数点不能出现两次
			if (hasE || decimal) return false;
			decimal = true;
		}
		else if (string[i] < '0' || string[i] > '9') // 不合法字符
			return false;
	}
	return true;
        
    }
二刷:
1、还是不会

运行时间:2ms 占用内存:380k

1、e后面必须是数字 只能有一个e

2、正负号只能出现一次,即使出现第二次了,那他的前面也要是 e/ E ,出现第一次的话必须在开头或者在E的后面

3、小数点也只能出现一次,且不能再E的后面

4、合法字符的判断 除了 e ± . 以及数字之外 其余的字符都是错的。

bool isNumeric(char* string)
    {
        bool sign = false, decimal = false,hasE = false;//正负号 小数点 e
        int len = strlen(string);
        for(int i = 0; i < len; ++i){
            if(string[i] == 'e' || string[i] == 'E'){
                if( i == len - 1) return false;//e 的后面必须要出现数字 对应 12e
                if(hasE) return false;//只能有一个e
                hasE = true;
                
            }else if(string[i] == '+' || string[i] == '-'){                
                if(!sign && i>0 && string[i-1] !='e' && string[i-1] != 'E')// 12e+5 如果第一次出现,且不是在开头,那么也要紧跟在e/E之后
                    return false;
                if(sign && string[i-1] !='e' && string[i-1] !='E')// +5e-6  第二次出现,那也要跟在 e/E之后
                    return false;
                sign = true;
            }else if(string[i] == '.'){
                if(decimal) return false; 
                if(hasE) return false;// E后面不能跟小数点  12e+4.3
                
                decimal = true;
                
            }else if(string[i] < '0' || string[i] > '9')//不合法字符
                return false;
            
        }
        return true;
    }

美女帅哥们如果觉得写的还行,有点用的话麻烦点个赞或者留个言支持一下阿秀~
如果觉得狗屁不通,直接留言开喷就完事了。

需要该笔记PDF版本的去个人公众号【拓跋阿秀】下回复“阿秀剑指offer笔记”即可。

<think>嗯,我现在需要解决这个问:用C语言输入一个字符串,然后从中提取数字组成一个新的整数。让我仔细想想该怎么一步步实现这个功能。 首先,用户输入的是一个字符串,所以我要先读取这个字符串。在C语言中,可以用gets函数或者fgets来获取输入的字符串。不过gets可能会有缓冲区溢出的问,所以可能更安全的是用fgets,比如fgets(str, sizeof(str), stdin),这样指定长度更安全。不过可能目里不需要考虑太多安全性,简单处理的话用gets也可以。 接下来,我需要遍历这个字符串中的每一个字符,检查每个字符是否是数字。如果是数字字符,就把它提取出来。那怎么判断一个字符是不是数字呢?数字字符的ASCII码在&#39;0&#39;到&#39;9&#39;之间,所以可以用条件判断:如果字符c满足c >= &#39;0&#39;且c <= &#39;9&#39;,那么就是数字字符。 然后,把这些数字字符收集起来,组成一个新的整数。这里需要考虑的是如何将多个数字字符组合成一个整数。比如,假设字符串里有"a12b3",提取出来的数字字符是&#39;1&#39;,&#39;2&#39;,&#39;3&#39;,那么组合成123。这时候,我需要将每个字符转换为对应的数字值,然后按顺序乘以10的相应次方相加。比如,第一个数字是1,第二个是2,第三个是3,那么结果是1*100 + 2*10 +3 = 123。 但更简便的方法可能是在遍历每个字符的时候,维护一个结果变量,初始为0。当遇到一个数字字符时,先将当前结果乘以10,然后加上这个字符对应的数字。比如,初始结果是0,遇到&#39;1&#39;,0*10+1=1;遇到&#39;2&#39;,1*10+2=12;遇到&#39;3&#39;,12*10+3=123。这样依次处理每个数字字符,就能得到最终的整数。 需要注意的还有,字符串中可能包含多个连续的数字,比如"abc123def456",这时候需要把这些连续的数字全部提取出来,组合成一个整数。比如这里的例子应该是123456。所以遍历整个字符串,逐个检查字符,遇到数字就进行处理。 此外,还要考虑前导零的情况。比如,字符串是"0a0b123",这时候提取出来的数字是0,0,1,2,3,组合成00123,但是作为整数的话,前面的零会被忽略,所以最终应该是123。但是根据目要求,是否需要保留前导零呢?目里说是组成一个新的整数,而整数前面的零是没有意义的,所以应该自动忽略前面的零。例如,如果输入是"000123",结果应该是123。但如果是"0000",那么应该输出0。或者在字符串中没有其他数字的情况下,如何处理?可能需要考虑是否至少有一个非零数字出现,否则结果为0。例如,输入是"abc",那么提取不到任何数字,结果应该是0? 所以,在实现的时候,可能需要一个标志位,表示是否已经开始组合数字。比如,初始时还没有遇到第一个数字,这时候如果遇到0,可以暂时不处理,直到遇到第一个非零数字,才开始累积。或者,不管前导零,直接按顺序处理,但最后如果是全零的话,结果就是0。例如,处理"000"的话,结果是0。这可能需要更仔细的处理。 或者,另一个思路是,不管前导零,只要遇到数字字符就加入到结果中。例如,"a01b2"会得到012,即12。但整数前面的零会被自动省略,所以在这种情况下,如何处理呢?如果用户希望把所有的数字字符按顺序组成整数,包括前导零的话,比如输入"0023",组成的是23还是0023?但整数类型无法保存前导零,所以必须转换为23。或者,用户是否希望将数字字符提取出来作为字符串,然后转换为整数?不过目要求的是组成一个新的整数,所以最终结果应该是一个整型变量,所以前面的零会被自动忽略,但中间或后面的零会被保留。例如,"001203"变成1203。 不过,在代码中如何处理?比如,当字符串中的数字字符是多个0和其他数字时,如何处理。比如,输入是"0",输出应该是0;输入是"000",输出0;输入是"a0b1c0",则组成010,即10。但按照之前的累积方法,初始是0,遇到0的时候,0*10 +0=0;然后遇到1的时候,0*10 +1=1;然后遇到0的时候,1*10+0=10。这样结果正确。 所以,按照这个逻辑,无论是否有前导零,只要按顺序处理每个数字字符,结果都会是正确的。例如,原字符串中的每个数字字符都被视为整数的一部分,顺序处理,前面的零在形成整数时会被自动处理。比如,处理"0012"会得到12,但按照累积的方法,初始是0,遇到00*10+0=0,再遇到1:0*10+1=1,再遇到2:1*10+2=12。所以结果是正确的。这种情况下,不管前面的零有多少,结果都会正确。 那代码的大体结构应该是这样的: 1. 声明一个字符数组来存储输入的字符串。 2. 遍历这个数组的每个字符,直到遇到结束符&#39;\0&#39;。 3. 对于每个字符,检查是否是数字。 4. 如果是数字,就将结果变量乘以10,然后加上这个字符对应的数值(例如,字符&#39;5&#39;对应数值5)。 5. 最后输出结果变量。 现在需要考虑一些特殊情况: - 输入的字符串中没有数字字符:此时结果应该为0。 - 输入的字符串全为0:结果应该为0。 - 输入的字符串中有多个0和其他数字,例如"0a0b123",结果是00123,但代码处理后的整数是123,正确。 代码的步骤: 首先,读取输入字符串。比如: char str[100]; printf("请输入字符串:"); fgets(str, sizeof(str), stdin); // 使用fgets更安全,不过需要注意fgets会包括换行符。需要处理可能的换行符。 然后初始化结果变量为0: int result = 0; 然后循环每个字符: for (int i = 0; str[i] != &#39;\0&#39;; i++) { if (str[i] >= &#39;0&#39; && str[i] <= &#39;9&#39;) { int digit = str[i] - &#39;0&#39;; result = result * 10 + digit; } } 这样处理后,如果字符串中有数字,就会组成整数。但是如果字符串中没有数字的话,result还是0,所以正确。 例如,输入是"abc",result是0;输入是"123",结果是123;输入是"a1b2c3",结果是123;输入是"000",结果是0;输入是"0a0b0",结果是0000,但在处理过程中,第一个00,第二个00*10+0=0,第三个00*10+0=0。所以最终结果是0。 这样看来,这个方法是可行的。 但需要测试一下代码是否正确。例如: 测试用例1:输入"abc",输出0。 测试用例2:输入"a1b2c3",输出123。 测试用例3:输入"0", 输出0。 测试用例4:输入"0123", 输出123? 按照上面的代码,输入"0123"的处理过程是: 初始result=0。 第一个字符是&#39;0&#39;,处理为0*10+0=0。 第二个字符是&#39;1&#39;,处理为0*10+1=1。 第三个字符是&#39;2&#39;,处理为1*10+2=12。 第四个字符是&#39;3&#39;,处理为12*10+3=123。 所以结果是123,但原字符串中的前导0被保留了吗?在整数中,前导0会被忽略,所以这个结果是正确的,因为原字符串中的数字是0,1,2,3,组合成0123,但作为整数是123。但用户可能期望的是0123转换为123,所以结果正确。 如果用户希望保持前导零的话,可能需要将数字作为字符串存储,而不是整数。但目要求组成一个新的整数,所以这种情况下,整数无法保存前导零,所以必须转换为数值形式,即123。所以代码的处理是正确的。 那这个方法是否满足目要求? 是的。因此,这样的代码应该可以解决问。 那现在需要考虑如何处理输入中的换行符。例如,当用fgets时,输入的字符串可能包含换行符。例如,用户输入"abc123\n",则str的内容是"abc123\n\0"。在遍历时,换行符会被检查是否是数字,显然不是,所以不影响。所以在代码中不需要额外处理换行符。 另外,如果用户输入超过数组长度,比如声明的是char str[100],而输入超过99个字符(因为fgets读取sizeof(str)是100的话,会读取99个字符,加上末尾的&#39;\0&#39;),但这可能超出目范围,目可能不需要处理这种情况。 所以综上,代码的大致结构是: #include <stdio.h> int main() { char str[100]; int result = 0; printf("请输入字符串:"); fgets(str, sizeof(str), stdin); for (int i = 0; str[i] != &#39;\0&#39;; i++) { if (str[i] >= &#39;0&#39; && str[i] <= &#39;9&#39;) { int digit = str[i] - &#39;0&#39;; result = result * 10 + digit; } } printf("提取后的整数为:%d\n", result); return 0; } 现在测试几个例子: 例子1:输入是"hello123world45",提取的数字是1,2,3,4,5 → 12345,输出12345。 例子2:输入是"0000",结果是0。 例子3:输入是"no numbers here",结果是0。 例子4:输入是"a1b2c30",结果是1230。 例子5:输入是"123abc456",结果是123456。 这样看来,代码是正确的吗? 但是有一个问:如果字符串中有多个零在中间,比如输入是"0010",则处理后的结果是10。对吗? 是的,因为第一个00*10+0=0;第二个00*10+0=0;第三个1→0*10+1=1;第四个0→1*10+0=10。所以结果是10,符合预期。 那这个方法是正确的。 综上,这个代码应该可以满足目要求。</think>在C语言中,从字符串提取数字并组成整数的步骤如下: --- ### **1. 读取输入字符串** 使用`fgets`函数安全地获取用户输入的字符串: ```c char str[100]; printf("请输入字符串:"); fgets(str, sizeof(str), stdin); // 避免缓冲区溢出 ``` --- ### **2. 遍历字符串并提取数字** 初始化一个整数变量`result`,遍历每个字符,若为数字则累加到结果中: ```c int result = 0; for (int i = 0; str[i] != &#39;\0&#39;; i++) { if (str[i] >= &#39;0&#39; && str[i] <= &#39;9&#39;) { int digit = str[i] - &#39;0&#39;; // 将字符转换为数字(如 &#39;5&#39; → 5) result = result * 10 + digit; // 按位累加 } } ``` --- ### **3. 处理特殊情况** - **无数字时**:`result`保持初始值`0`。 - **前导零**:代码自动忽略(如输入`"0012"`输出`12`)。 - **全零**:结果为`0`(如输入`"000"`输出`0`)。 --- ### **4. 输出结果** ```c printf("提取后的整数为:%d\n", result); ``` --- ### **完整代码** ```c #include <stdio.h> int main() { char str[100]; int result = 0; printf("请输入字符串:"); fgets(str, sizeof(str), stdin); for (int i = 0; str[i] != &#39;\0&#39;; i++) { if (str[i] >= &#39;0&#39; && str[i] <= &#39;9&#39;) { int digit = str[i] - &#39;0&#39;; result = result * 10 + digit; } } printf("提取后的整数为:%d\n", result); return 0; } ``` --- ### **示例测试** - 输入 `"a1b2c3"` → 输出 `123` - 输入 `"0test000"` → 输出 `0` - 输入 `"abc"` → 输出 `0` - 输入 `"12-34"` → 输出 `1234` 通过逐字符处理,代码能正确提取所有数字并按顺序组合成整数。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拓跋阿秀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值