You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C语言sscanf校验<Name>,<Age>,<City>格式的用户输入?

Can sscanf handle strict input validation for ,, format?

Great question! The short answer is yes, you can use sscanf to fix this issue—your current code just isn't using a strict enough format string to catch those invalid cases. Let's walk through why your existing code misses errors, and how to adjust it properly.

Why your current code fails

Your format string "%[a-zA-Z -],%[0-9],%[a-zA-Z-]" has two critical flaws:

  1. It only matches valid prefixes: For input like Name1$#,20,NY, sscanf will happily read Name1 (the valid part of the name) into input[0], then match the comma, age, comma, and city. It ignores the trailing $# entirely, so num still equals 3, and your error check doesn't trigger.
  2. No checks for extra characters or field validity: You're not verifying if there's leftover garbage after the city, nor are you validating the age range or ensuring fields aren't empty.

Fixed implementation with sscanf

Here's an improved version that addresses all your validation requirements:

#include <stdio.h>
#include <ctype.h>

int main() {
    char input_str[150];
    char name[50] = {0};
    int age;
    char city[50] = {0};
    int match_count;
    char trailing_char;

    // Read input line
    if (fgets(input_str, sizeof(input_str), stdin) == NULL) {
        printf("ERROR: Failed to read input\n");
        return 1;
    }

    // Strict format string:
    // %49[a-zA-Z -] → Max 49 valid chars for name (avoids buffer overflow)
    // , → Exact comma separator
    // %d → Read age as integer (easier to validate range)
    // , → Exact comma separator
    // %49[a-zA-Z-] → Max 49 valid chars for city
    // %c → Catch any trailing character (to check for extra garbage)
    match_count = sscanf(input_str, "%49[a-zA-Z -],%d,%49[a-zA-Z-]%c", 
                        name, &age, city, &trailing_char);

    // Validate the match result and input rules
    if (match_count == 3) {
        // Case 1: Input ends exactly after city (no newline, e.g., EOF)
        if (name[0] == '\0' || city[0] == '\0') {
            printf("ERROR: Name or City cannot be empty\n");
        } else if (age < 18 || age > 120) {
            printf("ERROR: Age must be between 18 and 120\n");
        } else {
            printf("Valid input:\nName: %s\nAge: %d\nCity: %s\n", name, age, city);
        }
    } else if (match_count == 4) {
        // Case 2: Input has a trailing character (should be a newline from fgets)
        if (isspace((unsigned char)trailing_char)) {
            if (name[0] == '\0' || city[0] == '\0') {
                printf("ERROR: Name or City cannot be empty\n");
            } else if (age < 18 || age > 120) {
                printf("ERROR: Age must be between 18 and 120\n");
            } else {
                printf("Valid input:\nName: %s\nAge: %d\nCity: %s\n", name, age, city);
            }
        } else {
            printf("ERROR: Extra invalid characters found after the City field\n");
        }
    } else {
        // Case 3: Match failed (invalid separators, illegal starting chars, etc.)
        printf("ERROR: Invalid format. Use <Name>,<Age>,<City> where:\n");
        printf("- Name: Letters, spaces, hyphens (max 49 chars)\n");
        printf("- Age: Integer between 18-120\n");
        printf("- City: Letters, hyphens (max 49 chars)\n");
    }

    return 0;
}

Key improvements explained

  • Field length limits: %49[...] ensures we never write past the end of our 50-byte arrays (leaving space for the null terminator).
  • Age as integer: Reading age directly as an int lets us easily validate its range (18-120) without converting a string.
  • Trailing character check: The final %c catches any characters after the city. We only accept it if it's a whitespace character (like the newline from fgets)—any other character means there's invalid garbage in the input.
  • Empty field checks: We make sure name and city aren't empty (e.g., input like ,20,NY is rejected).

When to consider alternatives

While sscanf works perfectly here, if you ever need more flexible validation (like supporting optional whitespace around commas), you might want to split the input with strtok and validate each field manually. But for your exact requirements, this sscanf approach is clean and efficient.

内容的提问来源于stack exchange,提问作者N4D4V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:42:46