2013-05-04 3 views
0

Я пытаюсь создать вектор, который должен ввести strings (white space included), пока пользователь не войдет в '!'.Создание вектора строк: C++

Ниже мой код:

#include <iostream> 
#include <vector> 
#include <string> 
#include <iterator> 

using namespace std; 


int main() 
{ 

    char buffer[100]; 
    string temp; 
    vector <string> vec; 


    while(1)//Shows Segmentation fault error while running, 
    //compiles succesfully 
    { 
    cout << "Enter String : "; 
    cin.get(buffer,100,'\n');//To ensure that whitespaces are also input 
    cout << "@@@@ " << buffer << endl ;//Shows correct input 

    cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); 
    //Clearing cin stream for any residual characters 
    temp.assign(buffer);//Assigning string the input "phrase" 
    cout << "###" << temp << endl;//Shows correct output 

    if (temp == "!") //if input is '!' character do not push on the vector a 
    //come out of the loop 
    break; 

    vec.push_back(temp);//push on the vector 
    temp.assign(NULL); //flush temp string 

    } 


    vector <string>::iterator p = vec.begin(); 
    //display thre vector 
    while(p != vec.end()) 
    { 
     cout << *p << endl; 
     p++; 
     } 

    return 0; 
    } 

Он успешно компилируется, но во время выполнения бросков Segmentation fault ошибку.

Невозможно понять, почему? Может ли кто-нибудь указать?

Также более разумное решение для этого, оценивается вместе, указывая на то, что не так с моим кодом.

Благодаря

+1

Просто используйте 'std :: getline' для чтения строк с пробелами. Вам не нужно навязывать ненужную максимальную длину или беспокоиться о том, что ваша длина соответствует размеру вашего буфера. – chris

ответ

3

Это будет причиной:

temp.assign(NULL); 

, как std::string::assign() будет пытаться читать до нулевого терминатор не найден и разыменование NULL указателя является неопределенным поведением: в этом случае ошибка сегментации. Используйте temp.clear() или просто создайте новый объект на каждой итерации.

Использование std::getline(), который читает строки, включая пробелы и позволяет избежать необходимости прописывать массив фиксированного размера (т.е. buffer[100]):

std::string line; 
while (std::getline(std::cin, line) && line != "!") 
{ 
    vec.push_back(line); 
} 
1
while (getline(cin, temp) && temp != "!") 
{ 
    vec.push_back(temp); 
} 

Использование буферов, как это больше С, что нужно сделать, чем C++. В C++ обычно есть способ избежать такого явного управления памятью с помощью классов - это хороший пример.

+0

Больше похоже на 'while (getline (cin, temp) && temp! ="! ") {Vec.push_back (temp);}'. – chris

+0

@chris Спасибо за подсказку – nullptr

3

Другие проблемы несмотря на это, выполнение вашей программы в gdb (или возможно любой другой отладчик) показывает причину:

[email protected] ~$ g++ -o temp temp.cpp 
[email protected] ~$ gdb temp 
GNU gdb 6.3.50-20050815 (Apple version gdb-1822) (Sun Aug 5 03:00:42 UTC 2012) 
Copyright 2004 Free Software Foundation, Inc. 
GDB is free software, covered by the GNU General Public License, and you are 
welcome to change it and/or distribute copies of it under certain conditions. 
Type "show copying" to see the conditions. 
There is absolutely no warranty for GDB. Type "show warranty" for details. 
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries ... done 

(gdb) run 
Starting program: /Users/tikal/temp 
Reading symbols for shared libraries ++............................. done 
Enter String : asd 
@@@@ asd 
###asd 

Program received signal EXC_BAD_ACCESS, Could not access memory. 
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000 
0x00007fff9081e6b0 in strlen() 
(gdb) backtrace 
#0 0x00007fff9081e6b0 in strlen() 
#1 0x00007fff9857ab95 in std::string::assign() 
#2 0x0000000100001642 in main() 
(gdb) 

По существу, temp.assign(NULL) является плохой идеей. Вместо этого вы можете использовать temp.clear() или не утруждать его очисткой (вы просто переназначаете его позже).

+0

Кстати, вот одна ссылка для basic_string: http://www.sgi.com/tech/stl/basic_string.html - это подразумевается в документации здесь («Назначает нулевое завершение массив символов до * этого. "), который вы должны передать в массив символов с нулевым символом. NULL - это не так, поэтому я предполагаю, что это относится к неопределенному поведению. – leander

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