【问题标题】:string input not printed correctly on the screen字符串输入未正确打印在屏幕上
【发布时间】:2022-01-23 17:59:09
【问题描述】:

我正在尝试从用户输入中读取字符串,然后将其打印在屏幕上。但是,当在控制台上打印字符串时,它有点乱码。有趣的是,它在 Visual Studio 中工作,而不是在 CodeBlocks 中。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main() {
    int i, num_bytes;
    char sentence[] = "";
    std::cout << "Please enter your name: ";
    //fgets(sentence, 100, stdin);
    //scanf("%[^\n]%*c", sentence);
    //scanf("%[^\n]", sentence);
    std::cin >> sentence;
    num_bytes = strlen(sentence);

    LPVOID ptr = VirtualAlloc(NULL, num_bytes, MEM_RESERVE, PAGE_READWRITE);
    ptr = VirtualAlloc(ptr, num_bytes, MEM_COMMIT, PAGE_READWRITE);

    if (ptr) {
        char* char_ptr = static_cast<char*>(ptr);

        for (i = 0; i < num_bytes; i++) {
            char_ptr[i] = sentence[i];
        }

        std::cout << "Allocated Memory Address: " << (void *)ptr << std::endl;

        std::cout << "Press Enter to print out the characters.\n";
        getchar();

        for (i = 0; i < num_bytes; i++) {
            std::cout << char_ptr[i];
        }

        std::cout << "\nPress Enter to clear memory." << std::endl;
        getchar();

        VirtualFree(ptr, 0, MEM_RELEASE);
    } else {
        std::cout << "Could not allocate " << num_bytes << " of memory." << std::endl;
    }

    std::cout << "\nPress Enter to continue." << std::endl;
    getchar();
}

【问题讨论】:

  • 您是否期望编译器在sentence 下提供无限量的可写存储空间?请改用std::string,忘记预先预留存储空间。
  • char sentence[] = ""; 为 0 个字符 + 空终止符提供空间。这是一个编译时大小的数组,永远不会从这个大小扩展。
  • 使用 std::string 而不是 char[N]。但这就是 VirtualAlloc/VirtualFree 的全部内容。你在做什么?
  • 在您扩大数组以接受超过 0 个字符后,您确定输入的人不会输入空格字符吗?请记住,std::cin &gt;&gt; sentence; 将在输入的第一个空白字符处停止读取。
  • 是的,我假设输入将包含空格。那么,我该如何解决这个问题呢?

标签: c++ string winapi memory virtualalloc


【解决方案1】:

您应该明确指定字符串的内存大小。 该代码:

char sentence[] = "";

声明最大大小为 0 的句子(+1 零符号)。当然,您将更多数据写入非您的内存中。 试试这个:

char sentence[200] = "";

【讨论】:

  • 空格呢?它不会在第一次出现空格字符时终止吗?
  • 不明白你的问题:(。你将'sentence'声明为“”。它表示带有单个符号的字符数组:\0(零符号,它不是空格符号)。如果如果你想将字符串输入到那个变量中,你应该分配足够的大小:200 - 1000 - 5000。但是,无论如何,这样的代码是破解你的应用程序的方法。建议使用 std::string 而不是原始字符数组。
  • @nabsaw "它不会在第一次出现空格字符时终止吗?" - operator&gt;&gt; 会,是的。如果您需要读取带空格的字符串,请改用cin.getline()(或切换到std::stringstd::getline())。
【解决方案2】:

而不是这个:

    char sentence[] = "";
    std::cout << "Please enter your name: ";
    //fgets(sentence, 100, stdin);
    //scanf("%[^\n]%*c", sentence);
    //scanf("%[^\n]", sentence);
    std::cin >> sentence;
    num_bytes = strlen(sentence);

你最好这样写:

    constexpr std::streamsize BUFFER_SIZE { 100 };
    std::array<char, BUFFER_SIZE> sentence { }; // use the more modern std::array

    std::cout << "Please enter your name: ";
    std::cin.getline( sentence.data( ), BUFFER_SIZE ); // will only read 100 chars
                                                       // including spaces and tabs

    num_bytes = strlen(sentence.data( ));

其余的与您的代码相同。但是现在用户也可以输入空格字符并且它们不会导致缓冲区溢出,因为std::cin.getline 只会从标准输入流中读取有限数量的字符。

【讨论】:

  • cin.getline() 报告(通过cin.gcount())写入sentence 的字符数,因此您无需使用strlen() 来确定@​​987654328@。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-27
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多