C语言提取字符串中COLOR="n"格式数字:scanf问题及替代方案
Hey there! Let's tackle your problem head-on. To answer your first question: scanf is not the right tool for this job—it’s designed for simple, predictable input formats, and struggles with cases where you need to target a specific pattern (like COLOR="n") amidst other unpredictable content (like extra quotes or numbers).
Your initial format strings ("%*[^"]"%2d[^"]"" and "%*[^"]COLOR="%2d[^"]"") fail because %*[^"] greedily reads everything until the first quote—even if that quote has nothing to do with your COLOR tag. If there’s any quote before your target tag, scanf will stop there and never find the COLOR=" part. Plus, scanf’s matching is strict; any deviation from the format string breaks the whole process.
Better Solutions
1. Use strstr + strtol (Simple & Reliable)
This is the most straightforward approach for your specific case. First, locate the exact COLOR=" substring with strstr, then extract the number from there using strtol (which handles trailing non-digit characters automatically).
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char buf[1000] = "Hello World - this is a line of textCOLOR=\"4\""; int colorNumber = 1; // Default value if tag is missing/invalid // Find the start of the COLOR tag char* colorTag = strstr(buf, "COLOR=\""); if (colorTag != NULL) { // Skip past "COLOR=\"" to get to the digits colorTag += strlen("COLOR=\""); // Extract the number (strtol ignores non-digit characters like the closing quote) colorNumber = strtol(colorTag, NULL, 10); // Optional: Enforce 1-56 range if (colorNumber < 1 || colorNumber > 56) { colorNumber = 1; } } printf("Extracted color number: %d\n", colorNumber); return 0; }
This works even if there are other quotes or numbers in the string—because we’re explicitly targeting the COLOR=" pattern, not just any quote.
2. Use POSIX Regular Expressions (For Complex Patterns)
If you need to handle more flexible scenarios (like varying whitespace around the tag, or multiple occurrences), regular expressions are a powerful option. Use the POSIX regcomp and regexec functions:
#include <stdio.h> #include <regex.h> #include <stdlib.h> #include <string.h> int main() { char buf[1000] = "Hello \"random quote\" - COLOR=\"12\" more text here"; int colorNumber = 1; regex_t regex; regmatch_t matches[2]; // Index 0 = full match, Index 1 = captured digits // Regex pattern to match COLOR="n" where n is 1-56 (we'll validate the range later) const char* pattern = "COLOR=\"([1-9][0-9]?)\""; // Compile the regex if (regcomp(®ex, pattern, REG_EXTENDED) != 0) { fprintf(stderr, "Failed to compile regex\n"); return 1; } // Execute the match if (regexec(®ex, buf, 2, matches, 0) == 0) { // Extract the captured digit substring char numStr[3]; strncpy(numStr, buf + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); numStr[matches[1].rm_eo - matches[1].rm_so] = '\0'; // Null-terminate the string colorNumber = atoi(numStr); // Enforce 1-56 range if (colorNumber < 1 || colorNumber > 56) { colorNumber = 1; } } regfree(®ex); // Clean up regex resources printf("Extracted color number: %d\n", colorNumber); return 0; }
Final Takeaway
Stick with strstr + strtol for your simple case—it’s lightweight, easy to debug, and avoids the pitfalls of scanf. Reserve regex for when you need to handle more complex, variable patterns.
内容的提问来源于stack exchange,提问作者Cody Maxie

