【问题标题】:scanf problems involving string input and string comparison涉及字符串输入和字符串比较的scanf问题
【发布时间】:2016-02-06 06:10:59
【问题描述】:

我最近才开始研究一般的 scanf 和 printf,在我的研究和一般情况下,我多次在我的代码中遇到问题,所以我决定制作一个测试程序并成功地复制了错误。

#include <string>
#include <string.h>
#include <stdio.h>

int main(){
    std::string name;
    std::string name2;

    printf("Print donald or larry: ");
    scanf("%s",name);

if(strcmp(name.c_str(), "donald") == 1){
    printf("You entered donald");
    goto stop;


}else{
    printf("You entered larry");
    goto stop;
}



stop:
return 0;
}

当我尝试编译代码时,它会抛出来自第 10 行的错误

错误:

error: cannot pass objects of non-trivially-copyable type 'std::string {aka
class std::basic_string<char>}' through '...'|

来源:

scanf("%s", name);

name.c_str&amp;name 我都试过了,它们都不起作用,name.c_str 使 if 语句出错并且不起作用,但 &amp;name 完全崩溃了,尽管我发现 &amp;&lt;variable&gt;到目前为止只适用于整数。

我做错了什么?

【问题讨论】:

  • if(strcmp(name.c_str(), "donald") == 1){ 不。
  • C 或 C++。选择一个,留下另一个。如果你想要 C++,试试cout and cin
  • 决定你是用 C 还是 C++ 编码。如果是 C,scanf 很酷但忘记string。如果是 C++,string 很好,但没有更多 scanf:std:cin &gt;&gt; name;
  • 这是 C++,在 C 中编程时使用 scanf 可能更好
  • 这篇文章似乎是做作的。

标签: c++ c c++11


【解决方案1】:

如果您正在尝试编写 C++ 代码,请使用以下代码

#include <iostream>
using std::cout;
using std::endl;
using std::cin;
#include <string>
using std::string;

int main(){

    // declare the string object
    std::string name;

    // output prompt and get input
    cout << "Print donald or larry: ";
    cin >> name;

    if (name == "donald") {
        cout << "You entered donald" << endl;
    }
    else if (name == "larry") {
        cout << "You entered larry" << endl;
    }

    return 0;
}

您在上面的代码中做了一些“错误”的事情。

  1. scanf 和 printf 是 C 函数,应与 cstrings 而不是 string 对象一起使用。如果您使用的是std::string,那么您正在使用 C++ 进行编程,您应该使用 C++ 标准库头文件 &lt;iostream&gt; 提供的功能
  2. 在代码中使用 goto 通常是个坏主意。

【讨论】:

    【解决方案2】:

    我做错了什么?

    主要问题是您在这种情况下混合了 applesoranges(或 C 和 C++)。虽然可以混合 C/C++ I/O,但出于多种原因不建议这样做。您的声明 std::string name; 试图声明一个与基本 char * 类型不同的 C++ 字符串对象。因此,当您尝试使用基本 C scanf 填充 C++ 字符串对象时,您会收到错误消息。为什么?因为scanf 需要一个简单的char * 指针作为名称,而您提供的是一个C++ 字符串对象。所以最好还是坚持使用 applesoranges,不要尝试将 C++ 对象与标准 C 函数混合。

    如果您尝试编写 C 代码来研究 scanf 系列函数,那么您将需要类似于以下内容:

    #include <stdio.h>
    #include <string.h>
    
    enum { MAXCHR = 64 };
    
    int main (void) {
    
        char name[MAXCHR] = {0};  /* simple character array initialized to 0 */
    
        printf ("Print donald or larry: ");
        if (scanf ("%63[^\n]%*c",name) != 1) {  /* check the return of scanf */
            fprintf (stderr, "error: insufficient input.\n");
            return 1;
        }
    
        if (strcmp (name, "donald") == 0)       /* string comparisons */
            printf ("You entered donald\n");
        else if (strcmp (name, "larry") == 0)
            printf ("You entered larry\n");
        else
            printf ("You entered '%s' (neither 'donald' or 'larry')\n", name);
    
        return 0;
    }
    

    使用/输出示例

    $ ./bin/scanf_name
    Print donald or larry: donald
    You entered donald
    
    $ ./bin/scanf_name
    Print donald or larry: larry
    You entered larry
    
    $ ./bin/scanf_name
    Print donald or larry: moe
    You entered 'moe' (neither 'donald' or 'larry')
    

    如果您打算使用scanf(或任何该系列的函数),那么花时间仔细阅读和消化这些函数的手册页是非常值得的。 format-stringformat specifiers 有许多微妙的警告,如果你不完全理解它们,它们可能会咬你。 scanf 系列函数有其一席之地,但在从用户那里获取输入时考虑使用面向行的 输入函数(例如 C 中的 fgetsgetline),这些函数不太容易产生微妙的影响I/O 问题。

    【讨论】:

      【解决方案3】:

      scanf 不支持任何 C++ 类。如果你想读入 C++ string,你可以做类似的事情:

      std::string str(256, ' ');
      if (1 == scanf("%*s", &str[0], str.size())) {
          // ...
      }
      

      但这并不能解释为什么你不想使用cin

      【讨论】:

      • scanf("%*s --> "一个可选的赋值抑制字符 *.", --> 没有 &amp;str[0], str.size().
      • 这是混合 C 和 C++ 字符串。在这种情况下我不同意这一点
      • 适用于某些字符串实现,但不适用于其他实现。谨慎使用。最好不要使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 2022-06-29
      • 2019-05-04
      • 2017-09-18
      • 1970-01-01
      相关资源
      最近更新 更多