1

I have just recently started working on scanf and printf in general, and in my research and general screwing around I have run into the problem in my code multiple times so I decided to make a test program and have successfully replicated the error.

#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;
}

when I attempt to compile the code it throws me an error coming from line 10

error:

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

source:

scanf("%s", name);

I have tried both name.c_str and &name and they both don't work, name.c_str makes the if statement bug out and not work but &name just crashes altogether, although I have found that &<variable> only works with integers so far.

What am i doing wrong?

8
  • 1
    if(strcmp(name.c_str(), "donald") == 1){ Nope. Commented Feb 6, 2016 at 6:14
  • 4
    C or C++. Pick one, leave the other. If you want C++, try cout and cin. Commented Feb 6, 2016 at 6:14
  • 1
    Decide whether you are coding in C or C++. If C, scanf is cool but forget string. If C++, string is fine, but no more scanf: std:cin >> name; Commented Feb 6, 2016 at 6:18
  • 1
    This is C++, scanf is probably better to use when programming in C Commented Feb 6, 2016 at 6:22
  • 1
    This post appears to be contrived. Commented Feb 6, 2016 at 6:27

3 Answers 3

6

If you are trying to write C++ code then use the following

#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;
}

You were doing some things "wrong" in your code above.

  1. scanf and printf are C functions and should be used with cstrings not string objects. If you are using std::string, then you are programming in C++ and you should use the functionality provided by the C++ standard library header <iostream>
  2. Using goto in your code is usually a bad idea.
Sign up to request clarification or add additional context in comments.

Comments

2

What am i doing wrong?

The primary issue is you are mixing apples and oranges (or C and C++) in this case. While it is possible to mix C/C++ I/O, it is not recommended for a number of reasons. Your declaration std::string name; attempts to declare a C++ string object which is not the same as a fundamental char * type. Thus when you attempt to fill the C++ string object with a basic C scanf you get the error. Why? Because scanf expects a simply char * pointer for name and you are providing a C++ string object. So it is best to either stick with apples or oranges and not attempt to mix C++ objects with standard C functions.

If you are attempting to write C code to investigate the scanf family of functions, then you will want something similar to the following:

#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;
}

Example Use/Output

$ ./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')

If you are going to work with scanf (or any of that family of functions), then it is well worth the time spent to carefully read and digest the manual pages for the functions. There are a number of subtle caveats to the format-string and format specifiers that can bite you if you do not understand them fully. The scanf family of functions have their place, but consider using line-oriented input functions when taking input from users (e.g. fgets or getline in C) which are much less prone to subtle I/O issues.

Comments

-5

scanf doesn't support any C++ classes. If you want to read into a C++ string, you can do something similar to:

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

This doesn't explain, however, why you don't want to use cin.

3 Comments

scanf("%*s --> "An optional assignment-suppressing character *.", --> no &str[0], str.size().
This is mixing C and C++ strings. I do not agree with this at this instance
Works with some string implementations, but not others. Use with caution. Best to not use at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.