【问题标题】:С error "s1, s2 are used uninitialised in this function"С 错误“s1, s2 在此函数中未初始化”
【发布时间】:2020-01-07 14:05:49
【问题描述】:

这是我在第一节编程基础课后遇到的问题之一

gets() 工作正常(我认为),但“cin”拒绝工作

int main(void)
{
    char *s1, *s2;
    puts("Enter your name and surname for gets()");
    gets(s1);
    puts("Enter your name and surname for cin()");
    cin >> s2;
    cout << s1 << "! Hello from gets" << endl;
    cout << s2 << "! Hello from cin" << endl;
    return 0;
}

我希望 cin 输出您在控制台中输入的内容,但是在输入 programm 之后会等待一秒钟,然后一切都关闭了,根本没有任何输出。

屏幕截图是我们老师给我们的,但它不起作用

Screenshot

【问题讨论】:

  • 不要使用gets。它已被弃用,并已从 C 和 C++ 中删除。
  • C 还是 C++?您在标题中使用了 C,但使用 C++ 标记了您的问题。它们相同,正确答案也会不同。
  • 我认为你需要一位新老师。

标签: c++ string fgets getline c-strings


【解决方案1】:

您的程序有未定义的行为。

gets 需要一个指向足够有效内存来读取和存储输入的参数。在您发布的代码中,s1 不符合该要求。您对cins2 的使用也存在类似问题。

更重要的是,不要再使用gets。由于安全问题,这是一个已弃用的功能。使用std::stringstd::getline

int main(void)
{
   std::string s1;
   std::string s2;

   puts("Enter your name and surname");
   std::getline(std::cin, s1);

   puts("Enter your name and surname again");
   std::getline(std::cin, s2);

   // Use s1 and s2.
   return 0;
}

有用的阅读:Which functions from the standard library must (should) be avoided?

【讨论】:

    【解决方案2】:

    这些指针

    char *s1, *s2;
    

    具有自动存储持续时间的未初始化并且具有不确定的值。因此,程序具有未定义的行为。

    改用字符数组或std::string类型的对象。

    考虑到 C 标准不支持函数 gets。使用fgets 而不是gets

    或者因为这是一个 C++ 程序,所以使用 std::getline 或成员函数 std::cin.getline

    注意这句话

    cin >> s2;
    

    不允许输入以空格分隔的多个单词。

    这是一个演示程序。

    #include <iostream>
    #include <string>
    #include <cstdio>
    #include <cstring>
    
    int main() 
    {
        const size_t N = 100;
        char s1[N];
        std::string s2;
    
        std::ios_base::sync_with_stdio();
    
        std::printf( "Enter your name and surname for fgets(): " );
        std::fgets( s1, sizeof( s1 ), stdin );
        s1[std::strcspn( s1, "\n" )] = '\0';
    
        std::printf( "Enter your name and surname for std::cin: " );
        std::getline( std::cin, s2 );
    
        std::cout << s1 << "! Hello from fgets" << std::endl;
        std::cout << s2 << "! Hello from std::cin" << std::endl;
    
        return 0;
    }
    

    它的输出可能看起来像

    Enter your name and surname for fgets(): Bob Fisher
    Enter your name and surname for std::cin: Tomas Man
    Bob Fisher! Hello from fgets
    Tomas Man! Hello from std::cin
    

    【讨论】:

    • Спасибоконечно,скинуоднокурсникам,пускайпосмотрят,номынапервомкурсеиэтобылонашепервоезанятиепопрограммированию,иянепонял50%того,чтотынаписал。 Код, приложенный мною в скриншоте взят из методички, написанной преподавателем, и, получается, он не рабочий?
    • @freshman 培训手册中的代码不正确。正如我已经写过的,gets 函数不是标准函数。其次,句子cin >> s2;不允许您在一行中读取多个单词,因为它会读取到第一个空格字符。请记住,有一个俄语网站 ru.stackoverflow.com。
    • 虽然作为示例有效,但请确保不要在实际程序中混合 stdio 和 iostream,并且更喜欢使用 iostream 库,因为读入 std::string 会更安全。
    • @freshman 我认为程序中最困难的部分是这条语句 s1[std::strcspn( s1, "\n" )] = '\0';。问题是函数 fgets 可以将换行符附加到读取的字符串中。该语句允许从字符串中排除该字符。函数 strcspn 查找换行符的位置,然后将其替换为终止零字符 '\0';
    【解决方案3】:

    另外,请记住,声明/创建指针变量不会自动创建指向对象。您必须始终明确地这样做。

    char* s = new char[ N ];
    

    ...无论N 是什么值。在你想使用它之后,不要忘记在某个时候释放内存。

    delete [] s;
    

    也就是说,由于您使用的是 C++,因此通常可以避免直接处理指针,如果必须,请使用 std::unique_ptrstd::shared_ptr

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多