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

C++中使用scanf读取std::string时程序结果不符合预期,是否是scanf的问题?

Hey there! You were spot-on about the issue being tied to using scanf with std::string — let's break down exactly what's wrong and how to fix your code.

The Core Problem: scanf Doesn't Play Nice with std::string

When you call s.c_str() on an empty std::string, it returns a read-only const char* pointing to an empty buffer (or unallocated memory, depending on the implementation). Using scanf("%s", s.c_str()) tries to write data into this read-only/underallocated space, which is undefined behavior. This can cause crashes, garbage output, or totally unpredictable results — exactly what you're seeing.

On top of that, std::string::find() returns a size_t (an unsigned integer type), not -1. Comparing -1 (a signed value) to an unsigned size_t will lead to weird logic errors even if you fix the input issue.

Fix 1: Use C++'s cin (The Cleanest Approach)

cin is designed to work seamlessly with std::string — it handles memory allocation automatically, so you don't have to worry about buffer sizes or read-only pointers. Here's your revised code:

#include <iostream>
#include <string>
using namespace std;

int main(){
    string s, t;
    cin >> s >> t; // Let cin handle the string reading
    
    size_t match_pos = s.find(t);
    while(match_pos != string::npos){ // Use string::npos instead of -1
        s.erase(match_pos, t.length());
        match_pos = s.find(t);
    }
    
    cout << s << endl;
    return 0;
}

Note that string::npos is the official way to check if find() failed — it's a special value defined for exactly this purpose.

Fix 2: Stick with scanf (If You Really Need To)

If you have to use scanf for some reason, you need to pre-allocate space in the std::string first, then use a writable pointer to that space. C++11 and later guarantee that std::string stores characters in a contiguous buffer, so &s[0] gives you a valid writable pointer:

#include <cstdio>
#include <string>
#include <cstring> // For strlen()
using namespace std;

int main(){
    // Pre-allocate enough space for your input (adjust the size as needed)
    string s(1024, '\0');
    string t(1024, '\0');
    
    scanf("%s", &s[0]);
    scanf("%s", &t[0]);
    
    // Trim the extra null characters from the end of the strings
    s.resize(strlen(s.c_str()));
    t.resize(strlen(t.c_str()));
    
    size_t match_pos = s.find(t);
    while(match_pos != string::npos){
        s.erase(match_pos, t.length());
        match_pos = s.find(t);
    }
    
    printf("%s\n", s.c_str());
    return 0;
}

This works, but it's more verbose and error-prone than using cin.

Bonus: A More Efficient Way to Remove Substrings

If you're working with very long strings, repeatedly calling erase() can be slow (it has to shift characters around in memory every time). Here's a faster approach using a temporary string to build the result in one pass:

#include <iostream>
#include <string>
using namespace std;

int main(){
    string s, t;
    cin >> s >> t;
    string result;
    
    const size_t t_len = t.length();
    if(t_len == 0){ // Edge case: empty substring, return original string
        cout << s << endl;
        return 0;
    }
    
    size_t pos = 0;
    while(pos <= s.size() - t_len){
        if(s.substr(pos, t_len) == t){
            pos += t_len; // Skip over the matched substring
        } else {
            result += s[pos];
            pos++;
        }
    }
    
    // Add any remaining characters that didn't match
    result += s.substr(pos);
    
    cout << result << endl;
    return 0;
}

This avoids the repeated memory shifts from erase() and is much more efficient for large inputs.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:18:11