2012-12-24 50 views
4

我正在学习struct在C + +中,我不知道如何使它不跳过第一个问题。问题与C + +和cin.getline

如果我在struct中使用char,它只会复制第一个字,如果我尝试使用字符串,它会跳过第一个问题(忽略它)。

你能指导我吗?

后来编辑: 我使用Microsoft Visual C++ 2010 Express Edition的,并且是有std::getlinecin.getline之间的差异?

#include <iostream> 
#include <conio.h> 
#include <string> 


using namespace std; 


struct melodie{ 

char artist[50]; 
char titlu[50]; 
int an; 
int lungime; 

}; 

void main(){ 
int repetam; 
double rezultat; 
cout<<"Cate melodii ve-ti introduce: "; 
cin>>repetam; 
melodie *pointer = new melodie[repetam]; 
for(int i = 0; i<repetam; i++){ 
    cout<<endl; 
    cout<<"Introduceti artistul melodiei: ";  
    cin.get(pointer[i].artist); 
    cout<<"Introduceti titlul melodiei: "; 
    cin.getline(pointer[i].titlu); 
    cout<<"Introduceti anul melodiei: "; 
    cin>>pointer[i].an; 
    cout<<"Introuceti lungea melodiei (in secunde): "; 
    cin>>pointer[i].lungime; 


} 
cout<<"Lista melodiilor introduse este:"<<endl; 
for(int i =0; i<repetam; i++){ 
    cout<<"Artistul melodiei este: "<<pointer[i].artist<<endl 
     <<"Titlul melodiei este: "<<pointer[i].titlu<<endl 
     <<"Anul melodiei este: "<<pointer[i].an<<endl 
     <<"Lungimea melodiei (in secunde) este: "<<pointer[i].lungime<<endl; 
    cout<<endl; 
} 

cout<<"Melodiile care au aparut dupa anul 2000 si au lungimea mai mica de 180 de secunde sunt: "<<endl; 
for(int i = 0;i<repetam; i++){ 
    if(pointer[i].an>2000 && pointer[i].lungime<180){ 
     cout<<"Artist: "<<pointer[i].artist 
      <<endl 
      <<"Titlul: "<<pointer[i].titlu<<endl<<endl; 


    } 
} 



getch(); 
} 
+1

我强烈建议你使用'的std :: string',只是'CIN >> str'当你不想空间在你想要一整行的时候,或者'getline(cin,str)',记住在混合这两行时丢弃剩下的换行符。 – chris

+0

cin.ignore()将从输入中删除任何“剩菜”。此外,你应该检查你的cin >> repetam ;,或你的新的结果可能失败[例如重复没有被设置为任何有意义的东西]。还要检查*指针是不是NULL。 –

回答

2

首先,你可以不应该编译。有一些错误:

  • void main()是非标准的。 main()总是返回intmain()的唯一便携式声明是int main()int main(int argc, char* argv[])(或int main(int argc, char** argv),它与前一个相同;当然,这两个参数的名称可以自由选择)。
  • get()getline()您使用的成员函数至少需要一个附加参数:可用缓冲区的大小。

对于答案的其余部分,我假设这些错误是固定的。

当然,输入不是“跳过第一个问题”。相反,它会读取已经给出的输入,但您可能不会考虑这样的输入:使用>>的格式化输入会在其各自的格式完成(或失败)时立即停止读取。例如,当读取一个整数时,一旦遇到一个非数字就停止。因此,在读取intrepetam时,输入流在遇到用于完成此输入的换行符时的最后一位数字后停止读取。对get()的调用会读取一个字符串(包括)第一个换行符。当输入repetam时,输入了换行符,因此该字符串是get()停止的换行符。

的更一般的,当混合格式化输入(即,使用>>)和未格式化的输入(即,使用命名的功能get()getline()read()等)时,一般要除去不想要的字符。在您的例子中,你可能需要调用get()之前摆脱了第一个换行符的(你需要包括<limits>以访问std::numeric_limits):

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
std::cin.get(pointer[i].artist, 50); 

如果您artisti字符串不以任何空格字符开始,你可以使用

(std::cin >> std::ws).get(pointer[i].artist, 50); 

操纵std::ws跳过所有前导空格(它会跳过空格,制表符,换行符等),并在某种程度上更容易输入。当然,如果你需要经常忽略换行符,您可以创建一个操纵忽略字符,直到并包括换行符,以及:

std::istream& skipline(std::istream& in) 
{ 
    return in.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
} 
// ... 
(std::cin >> skipline).get(pointer[i].artist, 50); 

这么说,我猜,你没有真的要使用get()因为此功能在字符串中包含分隔字符(默认为'\n')。您可能需要使用getline()。此外,它是比较容易处理std::string s,而不是字符数组,即,我会用为struct不同的定义:

struct melodi 
{ 
    std::string artist; 
    std::string titlu; 
    int an; 
    int lungime; 
}; 

这样,字符串可以是任意大小,不限于49字符(在你的版本中需要空格来终止空字符)。要阅读std::string你需要一个非成员函数std::getline(),不过):

std::getline(std::cin >> skipline, artist); 
+0

嗯,很多事情我必须学习才能理解,但因为我喜欢它,所以我会很高兴地学习它。 1问题我有,我可以使用 - >使用命名空间标准?为std ::?并非常感谢你,现在我试图解决所有的问题,我会与反馈意见谢谢 –

+0

稍后编辑:非常感谢您的帮助,我现在了解该程序正在工作的错误,但我不得不使例如,当我使用std :: cin.ignore(std :: numeric_limits :: max(),'\ n'); std :: cin.get(pointer [i] .artist,50); std :: cin.get(pointer [i] .artist,50);在cin后给了我一个错误点,这是错误 - > C++ test project \ test \ test \ main.cpp(29):error C2664:'std :: basic_istream <_Elem,_Traits>&std :: basic_istream <_Elem ,_Traits> :: get(_Elem *,std :: streamsize)':不能将参数1从'std :: string'转换为'char *',但我用 –

+0

修复了我的最后一条评论,我用这个修复了 - > std :: getline(cin,pointer [i] .artist); –