注意:(getline不是问题所在)C++getline()停止在用户定义的函数中工作,但在主函数中工作

NOTE:(getline was not the issue) C++ getline() stops working in user defined function but works in main function

本文关键字:函数 工作 定义 用户 C++getline getline 问题 注意      更新时间:2023-10-16

注意:已解决,问题不是getline(),而是用数组填充不正确!

在发布自己的问题之前,我已经查了几个问题,但我找不到问题的答案。这是我发布的第一个问题,但在发布自己的问题之前,我确实做了一些研究,并尝试了其他问题的其他解决方案。所以我不完全确定这不是重复的。我很抱歉!感谢您的提前理解!

我正在尝试使用getline()(c++)来获取用户输入。它在我的main中运行良好,但在我的用户定义函数中不起作用。我认为这可能与缓冲区有关,所以我使用了cin.ignore(),如中所建议的那样

C++getline方法不工作

我检查了一下:

getline如何与cin合作?

以确保我正确理解getline()。然而,我的程序仍然不能正常工作。

我的程序将英文文本作为用户输入(控制台输入)的字符串,并将其转换为莫尔斯电码,并将结果作为字符串输出(控制台输出)。

基本上我的问题是:

getline在我的主函数中既适用于字符串,也适用于空格为"This"answers"This Code"的字符串。

然而,在我的用户定义函数中,它只适用于没有空格的字符串,例如:"This"。

谢谢你的帮助!下面的代码片段!

#include <iostream>;
#include <stdio.h>;
#include <ctype.h>;
using namespace std;

string textToMorse(const string alphabet, const string morseAlphabet[]);
int main()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?";
const string morseAlphabet[39] = {".-","-...","-.-.","-..",".","..-.","--.","....","
..",".---","-.-",".-..","--","-.","---",".--.",
"--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---",
"...--","....-",".....",
"-....","--...","---..","----.",".-.-.-","--..--","..--.."};
int userSelection;
string resultString;

cout << "TEXT TO MORSE CODE or MORSE CODE TO TEXT program" << endl << endl;
cout << "Please select an option by typing the integer shown: " << endl << endl;
cout << "Type(Selects option) 1 to decode Morse code to English text" << endl;
cout << "Type(Selects option) 2 to encode English text to Morse code" << endl;
cout << "Type(Select option) any other integer that is NOT 1 or 2 to QUIT" << endl << endl;
cin >> userSelection;
while(userSelection == 1 || userSelection == 2)
{
if(userSelection == 1)
{
resultString = textToMorse(alphabet, morseAlphabet); // function where I use 
// getline() but does not work
cout << endl << "This is the Morse code decoded to English text: " << endl << endl;
cout << resultString << endl << endl << endl << endl;
}
}
return 0;
}
// does not work
string textToMorse(const string alphabet, const string morseAlphabet[])
{
string userInput;
cout << endl << "Enter English text to encode to Morse code,
with only a space between words: " << endl << endl;
cin.ignore();
getline(cin,userInput); //code works with strings without spaces, 
//but breaks with others. ex: "This" works as input
//but "This code" breaks and the console seems to freeze
// then crashes out
cin.clear();
// rest of code, but program breaks before this.
string encodedEnglishText = "";
for(int i = 0; i < userInput.length(); i++)
{
userInput[i] = toupper(userInput[i]);
}
for(int i = 0; i < userInput.length(); i++)
{
encodedEnglishText += morseAlphabet[alphabet.find(userInput[i])];
encodedEnglishText += " "; // extra spacing added for output clarity
if(userInput[i] == ' ')
{
encodedEnglishText += "  "; // extra spacing added for output clarity
}
}
return encodedEnglishText;
}

但是,如果我编辑代码,从main中获取输入并将其作为参数传入,它就可以工作了。

#include <iostream>;
#include <stdio.h>;
#include <ctype.h>;
using namespace std;

string textToMorse(const string alphabet, const string morseAlphabet[], string userInput);
int main()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?";
const string morseAlphabet[39] = {".-","-...","-.-.","-..",".","..-.","--.","....","
..",".---","-.-",".-..","--","-.","---",".--.",
"--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---",
"...--","....-",".....",
"-....","--...","---..","----.",".-.-.-","--..--","..--.."};
int userSelection;
string resultString;

cout << "TEXT TO MORSE CODE or MORSE CODE TO TEXT program" << endl << endl;
cout << "Please select an option by typing the integer shown: " << endl << endl;
cout << "Type(Selects option) 1 to decode Morse code to English text" << endl;
cout << "Type(Selects option) 2 to encode English text to Morse code" << endl;
cout << "Type(Select option) any other integer that is NOT 1 or 2 to QUIT" << endl << endl;
cin >> userSelection;
while(userSelection == 1 || userSelection == 2)
{
if(userSelection == 1)
{
string userInput;
cout << endl << "Enter English text to encode to Morse code,
with only a space between words: " << endl << endl;
cin.ignore();
getline(cin,userInput); //code works with both "This" and "This code"
cin.clear();
resultString = textToMorse(alphabet, morseAlphabet, userInput); //function modified 
     //to take one more
     //parameter
cout << endl << "This is the Morse code decoded to English text: " << endl << endl;
cout << resultString << endl << endl << endl << endl;
}
}
return 0;
}
string textToMorse(const string alphabet, const string morseAlphabet[], string userInput)
{
//code, but program works.
string encodedEnglishText = "";
for(int i = 0; i < userInput.length(); i++)
{
userInput[i] = toupper(userInput[i]);
}
for(int i = 0; i < userInput.length(); i++)
{
encodedEnglishText += morseAlphabet[alphabet.find(userInput[i])];
encodedEnglishText += " "; // extra spacing added for output clarity
if(userInput[i] == ' ')
{
encodedEnglishText += "  "; // extra spacing added for output clarity
}
}
return encodedEnglishText;
}

我没有包括所有的代码,只是我觉得与问题相关的部分。

我的意思是:

getline成功接受输入。当在main函数中使用时,getline成功地将诸如"this"answers"this code"之类的字符串分配给变量userInput。

当在我的用户定义函数中使用时,它只成功地分配了不带空格的字符串,比如"this"。在该函数中,由于某种原因,当我输入像"this code"这样的字符串或中间有空格的任何字符串时,它都不起作用。

注意:程序还没有完成,因为我计划添加其他方法来完成相反的操作(如代码额外的用户选项,但这些选项尚未实现或定义,代码仍在运行和编译以解决我面临的问题。

问题是空间没有莫尔斯电码。

进行验证:

int n = alphabet.find(userInput[i]);
encodedEnglishText += (n == string::npos) ? "  ":  morseAlphabet[n];

然后它就会起作用。

当您在alphabet字符串中查找输入字符时,不会发现' 'std::string::find()返回std::string::npos(通常-1转换为类型std::string::size_type,但不保证值)。使用这个值来索引morseAlphabet不会有多大好处:它是未定义的行为。当只输入一个字符串时不会出现此问题,因为所有字符都在alphabet中找到。

处理这种情况的正确方法是寻找角色并捕捉结果。在使用结果之前,您需要测试输入,例如:

std::string::size_type pos(alphabet.find(userInput[i]));
if (pos == std::string::npos) {
// deal with the character not being part of the alphabet
}
else {
encodedEnglishText += morseAlphabet[pos];
}

请注意,您的程序还有一些其他问题:

  1. 选项的选择应该在循环内!进入(例如2)的实现方式会导致无限循环。

  2. std::toupper()char一起使用也可能导致未定义的行为!问题是CCD_ 12期望值CCD_ 13的非负值,但是CCD_。为了避免这个问题,您应该将<cctype><ctype.h>中的任何函数与unsigned char:一起使用

    userInput[i] = toupper[static_cast<unsigned char>(userInput[i]));
    
  3. 如果用户没有输入整数,但是,例如,foo读取userSelection将失败,并且流将进入失败状态,在输入std::cin.clear()之前它什么都不做。处理这种情况的最佳方法是在做任何事情之前测试读取值的结果。如果输入失败,您可以通过清除状态并跳过有问题的字符来从这种情况中恢复,例如:

    if (std::cin >> userSelection) {
    // use the selection
    }
    else {
    std::cout << "ignoring invalid inputn";
    std::cin.clear();
    std::cin.ignore();
    }
    

    请注意,应该需要使用std::cin.clear()。此外,您应该验证您使用std::getline()读取的输入是否成功:通常,所有用户输入都应该进行成功测试。

  4. 如果在读取userSelection时在整数后面输入空格字符,则对std::cin.ignore()的调用将忽略此空格而不是换行符!为了避免这个问题,您可以读取第一个换行符之前的所有字符,也可以跳过非空白字符之前的所有空白字符:

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n'); // all till newline
    std::cin >> std::ws; // skip all whitespace to first non-whitespace character
    
  5. 不要使用std::endl!它不仅创建了一个换行符,而且还刷新了流。这很容易造成性能问题。

  6. 您可能应该通过引用而不是通过值传递std::string参数。通过值传递参数alphabet会创建一个具有的副本,这是低效的(morseAlphabet参数是通过指针传递的,尽管它看起来像一个数组)。

  7. 一些字符串文字似乎被拆分为多行。这样做是非法的(然而,我想这个问题是在将代码粘贴到上面的问题时引入的)。