2016-02-06 2 views
1

Я только недавно начал работать над scanf и printf в целом, и в своих исследованиях и в общих чертах я несколько раз сталкивался с проблемой в своем коде, поэтому решил сделать тест и успешно реплицировали ошибку.scanf проблемы с использованием ввода строки и сравнения строк

#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 и &name, и оба они не работают, name.c_str м akes ошибка if if и не работает, но &name просто падает вообще, хотя я обнаружил, что &<variable> работает только с целыми числами.

Что я делаю неправильно?

+1

'if (strcmp (name.c_str()," donald ") == 1) {' Nope. – John3136

+4

C или C++. Выберите один, оставьте другой. Если вы хотите C++, попробуйте ['cout' и' cin'] (http://www.cplusplus.com/doc/tutorial/basic_io/). – e0k

+1

Определите, являетесь ли вы кодировкой на C или C++. Если C, scanf круто, но забудьте 'string'. Если C++, 'string' в порядке, но не более scanf:' std: cin >> name; ' – rici

ответ

6

Если вы пытаетесь писать 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++. <iostream>
  2. Использование goto в вашем коде - это, как правило, плохая идея.
-5

scanf не поддерживает любые классы C++. Если вы хотите читать в C++ string, вы можете сделать что-то подобное:

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

Это не объясняет, однако, почему вы не хотите использовать cin.

+2

Просто потому, что вы не можете означает, что вы должны ... – John3136

+1

'scanf ("% * s' -> "Необязательный символ подавления присваивания *.", -> no '& str [0], str.size()'. – chux

+0

Это смешение C и C++. Я не согласен с этим в этом случае. – Curious

2

What am i doing wrong?

Основной вопрос вы смешиваете яблоки и апельсины (или C и C++) в этом случае. Хотя возможно смешивать C/C++ I/O, это не рекомендуется по ряду причин. Ваше объявление std::string name; пытается объявить строковый объект C++, который не совпадает с основным типом char *. Таким образом, при попытке заполнить строковый объект C++ базовым C scanf вы получите ошибку. Зачем? Потому что scanf ожидает просто указатель char * для имени, и вы предоставляете строковый объект C++ . Поэтому лучше всего придерживаться яблок или апельсинов и не пытаться смешивать объекты 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-string и спецификаторов формата, которые могут вас укусить, если вы их не понимаете полностью. Семейство функций scanf имеет свое место, но рассмотрите с помощью ориентированных на линию входных функций при вводе данных от пользователей (например, fgets или getline в C), которые гораздо менее подвержены тонким проблемам ввода-вывода.

Смежные вопросы