判断String中是否包含制定的子字符串

本文介绍如何利用String类的indexOf方法快速判断一个字符串中是否包含特定的子字符串,提供了一个简单且实用的字符串操作技巧。通过实例演示,帮助读者理解并掌握这一方法的应用,特别适用于在编程中进行字符串查找的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里用一个非常巧妙的方法来判断一个String中是否包含一个子字符串:

如:

String A="abcd";

String B="bc";

利用A.indexOf(B),如果返回值等于-1,证明A不包含B;如果返回值不等与-1,证明A包含B;

关于indexOf()方法的具体解释,请自行参考JDK_API 。








注:尊重作者的劳动成果,如需转载文章或非个人学习使用,请注明文章出处,谢谢!

<think>好的,我现在需要帮用户解决一个关于C语言字符串校验的问题。用户提供的字符串例子是“+000.00 +34.5 2497.19 00”,需要编写校验代码。首先,我需要明确用户的需求到底是什么。 用户之前已经询问过关于密码校验的程序,现在给出的这个字符串看起来像是一组数值,可能涉及正数、小数、可能有前导零或符号。所以,用户可能需要验证这个字符串是否符合某种数值格式的规则,比如每个部分都是有效的数字格式,可能有多个数值用空格分隔。 首先,我需要分析用户提供的例子。例子中的字符串由四个部分组成:“+000.00”、“+34.5”、“2497.19”、“00”。看起来每个部分都是有效的数值,包含正号、前导零、小数点和可能的整数或小数。可能的校验规则包括: 1. 整个字符串由多个以空格分隔的数值组成。 2. 每个数值必须符合以下格式: a. 可选的正号(+)或负号(-)。 b. 整数部分可以有前导零,或者没有整数部分直接以小数点开头(但这种情况在例子中没有出现,可能需要确认)。 c. 小数部分可选,如果有,必须有小数点后至少一位数字。 d. 整个数值不能为空,即至少有一个数字(比如“.5”是否允许,或者是否需要整数部分)。 不过,根据用户提供的例子,像“00”这样的纯整数是允许的,而“+000.00”有符号、前导零和小数部分。因此,可能需要允许前导零,允许正负号,必须包含至少一个数字,小数点后必须有一位以上数字,且每个数值不能是空字符串。 接下来,我需要考虑如何用C语言实现这样的校验。可能的步骤包括: 1. 将整个字符串按空格分割成多个子字符串(数值)。 2. 对每个子字符串进行校验,判断是否符合数值格式。 对于分割字符串,可以使用strtok函数。然后,对每个子字符串进行逐个字符的检查,确保符合以下规则: - 开头可以是+或-,可选。 - 之后可以是数字,或者如果是小数点开头,则后面必须跟数字。 - 如果包含小数点,则只能有一个,且小数点前后至少有一个数字(例如允许“123.”吗?或者需要后面必须有数字?根据例子中的情况,例如“+34.5”和“2497.19”都是正确的小数,而“00”是整数。但例子中没有出现“123.”这样的情况,可能需要用户确认是否允许。但根据常规数值格式,通常小数点后需要至少一位数字,所以“123.”可能无效,而“.5”有效吗?根据例子中的情况,用户可能需要允许这种情况,但需要明确。不过用户提供的例子中没有这种情况,所以可能需要进一步假设。 可能的校验规则细化: 每个数值必须符合: - 可选的正负号开头。 - 至少包含一个数字。 - 可以有小数点,但如果有的话,小数点前后至少有一个数字(即允许“.5”或“123.”,或者必须两边都有数字?需要根据例子判断。用户例子中的数值都是两边有数字的,比如“+000.00”整数部分三个零,小数部分两位;“+34.5”整数两位,小数一位;“2497.19”整数四位,小数两位;“00”整数两位。所以可能用户要求小数点前后都必须有数字?或者至少其中之一? 或者可能允许像“.5”或“123.”这样的格式?这需要进一步明确,但用户没有说明。因此,可能需要假设小数点前后至少有一个数字,但允许其中之一。例如,“123.”可能被视为无效,而“.5”视为有效?或者两者都有效?需要根据常见情况判断。比如,在编程中,像“.5”通常被解析为0.5,而“123.”被视为123.0,所以可能允许。但用户的需求可能不同。 为了保险起见,可能需要要求数值必须至少有一个数字,小数点前或后必须至少有一个数字,但不能只有小数点。例如,不允许单独的“.”,但允许“+123.45”、“-0.78”、“123”、“.5”、“123.”等形式。不过,根据用户提供的例子,可能要求小数点前后都必须有数字。例如,用户例子中的每个数值都有小数点后两位,或者没有小数点。但“00”没有小数点,而“+34.5”小数点后一位。因此,可能允许小数点后至少一位,但小数点前可以没有数字?或者必须有? 此时,可能需要用户进一步澄清,但根据问题描述,用户希望校验类似给出的例子中的字符串,所以需要根据例子中的情况制定规则。 总结可能的规则: 每个数值部分必须满足: 1. 可选的正号或负号开头。 2. 整数部分可以包含多个数字,允许前导零,或可以省略整数部分(即允许以小数点开头)。 3. 如果有小数点,则必须有至少一个数字在小数点前或后,但至少其中之一不能全为空。例如: - “123.45” 有效 - “.45” 有效 - “123.” 有效 - “.” 无效 4. 整个数值不能为空,即必须有至少一个数字。 此外,整个字符串必须由这样的数值组成,用空格分隔,且每个数值都是有效的。 现在,我需要将这些规则转化为C代码。 步骤: 1. 分割字符串为多个子字符串,使用空格分隔。 2. 对每个子字符串校验是否符合上述规则。 校验单个数值的函数: 函数原型可能为int isValidNumber(const char *str)。 在该函数中,需要: - 检查首字符是否为+或-,如果是,跳过。 - 遍历剩余字符,检查是否符合数字或小数点,并且小数点只能出现一次。 - 确保至少有一个数字。 - 如果有小数点,则小数点前后至少有一个数字(即不能是单独的小数点,或者像“+”这样的符号后直接接小数点而没有数字)。 例如: - “+000.00” 有效:符号,整数部分三位,小数点,两位小数。 - “+34.5” 有效:符号,整数两位,小数点,一位小数。 - “2497.19” 有效:整数四位,小数点,两位小数。 - “00” 有效:两位整数,无小数点。 - “.5” 有效:无符号,无整数部分,小数点后一位。 - “123.” 有效:整数三位,小数点后无,但根据之前的例子,用户可能允许? 但用户例子中没有这种情况,可能需要进一步考虑。 但用户提供的例子中没有这种情况,所以可能需要明确是否允许。如果用户希望允许,则需要在代码中处理,否则可能不允许。例如,如果数值是“123.”,是否有效?可能根据需求,但此处可能需要允许,因为小数点后可以没有数字,但前面必须有数字。或者,小数点后必须至少一位? 例如,在C语言中,strtod函数会解析“123.”为123.0,所以可能允许。但用户的需求可能要求小数点后必须有一位数字。例如,用户提供的例子中的每个数值如果有小数点,后面都有数字。比如“+000.00”有两位小数,“+34.5”有一位,“2497.19”两位。所以可能要求小数点后至少一位数字,而小数点前可以有零或多个数字,但整体至少有一个数字。 因此,调整规则: 每个数值必须满足: - 可选的正负号。 - 后面是: a. 至少一个数字,可能包含一个小数点,且小数点后至少一位数字;或者 b. 小数点后至少一位数字(如“.5”)。 或者,更准确地说: 数值的格式为: [+-]? ( [0-9]+(.[0-9]*)? | .[0-9]+ ) 即: - 可选的正负号。 - 然后是: - 至少一个数字,后面可以跟一个小数点和零或多个数字(允许“123”或“123.45”或“123.”) - 或者一个小数点后跟至少一个数字(如“.45”) 这样,“123.”是允许的,而“.45”也是允许的,但“.”不被允许。 现在,如何用C代码实现这个校验? 可以逐个字符检查,记录是否遇到了小数点,符号是否出现在首位,是否有至少一个数字,以及其他条件。 步骤: 1. 初始化变量:has_sign(是否遇到符号),dot_count(小数点数量,必须<=1),digit_count(数字的数量,必须>=1),part_before_dot(小数点前是否有数字),part_after_dot(小数点后是否有数字)。 2. 处理符号:如果第一个字符是+或-,has_sign置1,指针后移。 3. 遍历剩余字符: a. 如果是小数点: - 如果已经有过小数点(dot_count >=1),返回无效。 - 否则,dot_count++ b. 如果是数字: - digit_count++ - 如果当前在小数点前,part_before_dot=1 - 如果在小数点后,part_after_dot=1 c. 其他字符:返回无效。 4. 最终检查: - digit_count >=1 - 如果存在小数点: - part_before_dot或part_after_dot必须至少有一个为真(即不能同时前后都没有数字) - 但根据之前的正则表达式,如果小数点存在,则要么前面有数字,要么后面有数字,或者两者都有。 但根据正则表达式,两种情况: - 数字+可选的小数点和更多数字,例如“123”或“123.45”或“123.” - 或者小数点后必须至少一个数字,例如“.45” 所以,在代码中,如果有小数点,那么必须满足: (part_before_dot >=1 或 part_after_dot >=1) 但根据正则表达式,当有小数点时: - 要么前面有数字(如“123.”或“123.45”) - 或者后面有数字(如“.45”) 所以,小数点不能单独存在,前后必须至少有一个数字。 因此,最终的校验条件是: digit_count >=1 并且,如果dot_count ==1: 则 part_before_dot || part_after_dot 必须为真。 或者更简单的方式,如果有小数点,那么必须满足: (part_before_dot && part_after_dot) 或者 (part_before_dot && !part_after_dot) 或者 (!part_before_dot && part_after_dot) 但实际上,只要小数点存在,并且至少有一个部分有数字即可。 比如,在代码中: if (dot_count > 0) { if ( (part_before_dot + part_after_dot) < 1 ) { 无效; } } 所以,现在将这些条件转化为代码。 可能的实现: 函数isValidNumber: int isValidNumber(const char *str) { if (*str == '\0') return 0; // 空字符串无效 int has_sign = 0; int dot_count = 0; int digit_count = 0; int part_before_dot = 0; int part_after_dot = 0; const char *p = str; // 处理符号 if (*p == '+' || *p == '-') { has_sign = 1; p++; } // 遍历剩余字符 while (*p != '\0') { if (*p == '.') { if (dot_count >= 1) { return 0; // 多个小数点 } dot_count++; p++; } else if (isdigit(*p)) { digit_count++; if (dot_count == 0) { part_before_dot = 1; } else { part_after_dot = 1; } p++; } else { // 非法字符 return 0; } } // 必须至少有一个数字 if (digit_count == 0) { return 0; } // 如果有小数点,必须至少有一个部分有数字 if (dot_count > 0) { if (!part_before_dot && !part_after_dot) { return 0; } } return 1; } 这个函数会检查: - 是否为空字符串。 - 是否有符号。 - 是否有多个小数点。 - 是否有非法字符。 - 是否有至少一个数字。 - 如果有小数点,前后是否有至少一个部分有数字。 测试例子: "+000.00" 有效:符号,整数3位,小数点,小数两位。 "+34.5" 有效:符号,整数2,小数1。 "2497.19" 有效:整数4,小数2。 "00" 有效:整数两位,无小数点。 ".5" 有效:无符号,小数部分1位。 "123." 有效:整数3,小数部分0位?根据代码,part_before_dot=1,part_after_dot=0,所以满足条件,因为part_before_dot存在。所以有效。 而单独的"."无效,因为没有数字。 "+" 无效:没有数字。 "abc" 无效:非法字符。 现在,用户提供的例子中的每个部分都应该被这个函数视为有效。 接下来,主函数需要将整个字符串分割为多个部分,并逐个校验。 使用strtok分割字符串,空格为分隔符。 在main函数中: 读取输入字符串,分割,然后对每个部分调用isValidNumber。 如果所有部分都有效,则整体有效,否则输出错误信息。 可能的代码结构: #include <stdio.h> #include <string.h> #include <ctype.h> int isValidNumber(const char *str) { // 如上实现 } int validateString(const char *input) { char *str = strdup(input); // 复制字符串,因为strtok会修改原字符串 if (str == NULL) { return 0; // 内存分配失败 } char *token = strtok(str, " "); int allValid = 1; while (token != NULL) { if (!isValidNumber(token)) { printf("无效数值: %s\n", token); allValid = 0; } token = strtok(NULL, " "); } free(str); return allValid; } int main() { char input[100]; printf("请输入需要校验的字符串:"); fgets(input, sizeof(input), stdin); input[strcspn(input, "\n")] = '\0'; // 去除换行符 if (validateString(input)) { printf("校验通过!所有数值格式正确\n"); } else { printf("校验未通过\n"); } return 0; } 注意:strdup不是标准C库函数,可能需要使用malloc和strcpy来复制字符串,或者在支持的环境下使用。例如: 在validateString函数中: char *copy = malloc(strlen(input) + 1); if (copy == NULL) { return 0; } strcpy(copy, input); // 使用strtok处理copy // 最后free(copy) 这样修改后的validateString: int validateString(const char *input) { char *copy = malloc(strlen(input) + 1); if (copy == NULL) { return 0; } strcpy(copy, input); char *token = strtok(copy, " "); int allValid = 1; while (token != NULL) { if (!isValidNumber(token)) { printf("无效数值: %s\n", token); allValid = 0; } token = strtok(NULL, " "); } free(copy); return allValid; } 这样就能处理输入字符串的分割和校验。 现在,测试用户提供的例子:“+000.00 +34.5 2497.19 00” 应该被分割为四个部分,每个部分都有效,所以校验通过。 另一个测试用例,如“+00a0.00”会因为有字符'a'而被标记为无效。 现在,需要确认代码是否满足用户的需求。用户可能希望校验字符串中的每个部分是否符合数值格式,而此代码正是如此。 可能的遗漏: - 处理多个空格的情况,比如中间有多个空格,strtok会正确处理,因为分隔符是" ",但连续的多个空格会被视为一个分隔符。 - 空字符串的情况:如果输入为空,validateString会分割不出任何token,因此循环不执行,返回allValid初始值1,认为校验通过。这可能不是用户期望的。需要处理空字符串的情况,比如在validateString中检查是否有至少一个token。 例如,在validateString中,如果没有任何token(即输入为空或全是空格),则返回无效。 修改validateString: int validateString(const char *input) { char *copy = malloc(strlen(input) + 1); if (copy == NULL) { return 0; } strcpy(copy, input); char *token = strtok(copy, " "); int allValid = 1; int tokenCount = 0; while (token != NULL) { tokenCount++; if (!isValidNumber(token)) { printf("无效数值: %s\n", token); allValid = 0; } token = strtok(NULL, " "); } free(copy); if (tokenCount == 0) { printf("错误:字符串为空或仅包含空格\n"); return 0; } return allValid; } 这样,如果输入为空或全是空格,会输出错误信息。 此外,可能还需要处理像“ +000.00 +34.5 ”这样的前后空格情况,strtok会自动忽略开头和结尾的空格,分割出正确的token。 现在,整个代码应该能够正确校验用户提供的字符串是否符合数值格式要求。</think>以下是根据需求编写的C语言字符串校验程序,用于验证由空格分隔的多个数值格式的字符串(如示例中的"+000.00 +34.5 2497.19 00"): ```c #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> /* 校验单个数值格式的函数 * 允许格式:[+/-][整数部分][.小数部分] 或 [+/-][.小数部分] * 例如:+123.45, -.78, 123., .5, 100 */ int isValidNumber(const char *str) { if (*str == '\0') return 0; // 空字符串直接返回无效 int has_sign = 0; int dot_count = 0; int digit_count = 0; int part_before_dot = 0; // 小数点前是否有数字 int part_after_dot = 0; // 小数点后是否有数字 const char *p = str; // 处理开头的正负号 if (*p == '+' || *p == '-') { p++; has_sign = 1; } // 遍历所有字符 while (*p != '\0') { if (*p == '.') { if (dot_count >= 1) return 0; // 多个小数点 dot_count++; } else if (isdigit(*p)) { digit_count++; // 记录小数点前后的数字存在性 if (dot_count == 0) part_before_dot = 1; else part_after_dot = 1; } else { return 0; // 出现非法字符 } p++; } // 必须包含至少一个数字 if (digit_count == 0) return 0; // 如果有小数点,必须前后至少有一个数字 if (dot_count > 0 && !part_before_dot && !part_after_dot) { return 0; } return 1; } /* 整体字符串校验函数 * 参数:input - 待校验的完整字符串 * 返回值:1表示全部格式正确,0表示存在错误 */ int validateString(const char *input) { // 复制字符串用于分割(strtok会修改原始字符串) char *copy = strdup(input); if (!copy) return 0; char *token = strtok(copy, " "); int allValid = 1; int tokenCount = 0; while (token) { tokenCount++; if (!isValidNumber(token)) { printf("无效数值: \"%s\"\n", token); allValid = 0; } token = strtok(NULL, " "); } free(copy); // 处理空字符串或纯空格的情况 if (tokenCount == 0) { printf("错误:未检测到有效数值\n"); return 0; } return allValid; } int main() { char input[100]; printf("请输入需要校验的字符串:"); fgets(input, sizeof(input), stdin); input[strcspn(input, "\n")] = '\0'; // 去除换行符 if (validateString(input)) { printf("校验通过!所有数值格式正确\n"); } else { printf("校验未通过\n"); } return 0; } ``` 代码结构说明: 1. **核心校验逻辑** `isValidNumber` - 允许前导正负号 - 严格限制单小数点 - 支持三种数值格式: - 纯整数(如`100`) - 整数+小数(如`123.45`) - 纯小数(如`.5`) - 禁止非法字符和空数值 2. **字符串处理** `validateString` - 使用`strtok`分割字符串 - 处理连续空格和首尾空格 - 支持动态内存分配复制字符串 - 统计有效数值数量 3. **输入安全处理** - 使用`fgets`防止缓冲区溢出 - 去除换行符的规范操作 测试案例: 输入:`+000.00 +34.5 2497.19 00` 输出:`校验通过!所有数值格式正确` 输入:`12.3.4 ++5 . 123a` 输出: ``` 无效数值: "12.3.4" 无效数值: "++5" 无效数值: "." 无效数值: "123a" 校验未通过 ``` 该程序可扩展性: 1. 修改数值格式规则(如禁用前导零) 2. 调整允许的特殊符号集合 3. 添加数值范围限制 4. 修改分隔符(如改为逗号分割)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值