您已将此问题标记为 C++。
这里我介绍两个版本。
t266a() 符合 c++ 和流,但仅使用 c-string(无 std::string)
t266b() 符合 c++ 和流,并使用 std::string(无 c-string)
我有意使用空格将代码与 c 字符串的部分对齐到代码与 std::strings,但您需要将其加载到功能强大的编辑器中以并排显示它们。
// 1 & 2 of 3 c++ includes
#include <iostream> // cout, cin, istream
#include <algorithm> // std::fill
// removed: include <cstring> - not needed
// forward
// c++, but limited to c-string, no std::string
int t266a(std::istream& ss);
// c++, using std::string
int t266b(std::istream& ss);
const int MAX_BUFF = (1024*1024); // for c-string, how big should this be?
// default stack size ubuntu 15.10 (64) is 8MB, so plenty of room
// ///////////////////////////////////////////////////////////////////////
size_t getLine (std::istream& ss, char* buff, size_t& buffLen)
{
size_t karCount = 0;
for (size_t i=0; i<MAX_BUFF; ++i) // limit read to MAX_BUFF chars
{
char kar = 0;
ss.read(&kar, 1); // binary stream read, 1 char at a time
if (ss.eof()) break;
if(ss.bad()) { // either fail or bad
std::cerr << "stream bad x " << std::endl;
break;
}
buff[i] = kar; // capture kar to buff
karCount += 1; // count kar's
if ('\n' == buff[i]) // end-of-line within stream
{
buffLen = i;
buff[i] = 0; // null-terminate in buff
break; // line complete
}
}
return(karCount);
}
// ///////////////////////////////////////////////////////////////////////
size_t buffFind(const char* buff, size_t buffLen, const char kar)
{
size_t commaAt = buffLen + 1; // not found
for (size_t i=0; i<buffLen; ++i)
{
if(kar == buff[i])
{
commaAt = i; // found comma
break;
}
}
return (commaAt);
}
// ///////////////////////////////////////////////////////////////////////
// c++, but limited to c-string, no std::string
int t266a(std::istream& ss)
{
std::cout << "t266a() C++, but limited to c-string, no std::string" << std::endl;
std::cout << "MAX_BUFF: " << MAX_BUFF << std::endl;
char buff[MAX_BUFF];
size_t buffCount = 0;
size_t buffLen = 0;
do
{
// buff[0] = '\0'; // a c-string terminates with the 1st 0 ... need to clear all?
// (void)::memset(buff, 0, MAX_BUFF); // from <cstring> lib. clear all c-style
std::fill(buff, buff+MAX_BUFF, '\0'); // from <algorithm> lib. clear all c++style
(void)getLine(ss, buff, buffLen); // local function
if(ss.eof()) break;
if(ss.bad()) { // either fail or bad
std::cerr << " " << ss.good()
<< " " << ss.eof()
<< " " << ss.fail()
<< " " << ss.bad()
<< std::endl;
break;
}
buffCount += 1;
if (ss.eof()) break;
//std::cout << " Input: " << buffCount << " (" << buffLen << ") '" << buff << "'" << std::endl;
// find comma
size_t commaAt = buffFind(buff, buffLen, ',');
if(commaAt > buffLen)
{
std::cerr << " Err: invalid input: no comma on line "<< std::endl;
break;
}
if(commaAt < 1)
{
std::cerr << " Err: invalid input: comma at beginning of line "<< std::endl;
break;
}
buff[commaAt] = 0; // take advantage of c-string
std::cout << " Output: "
<< &buff[commaAt+1] // Firstname Middlename [(where comma was) .. (end of buff)]
<< " "
<< &buff[0] // Surname [0..(where comma was)]
<< " (bufLen: " << buffLen << ")" << std::endl;
if (ss.eof()) { break;}
}while (true);
return(0);
} // int t266a(std::istream&)
// ///////////////////////////////////////////////////////////////////////
// 3 of 3 c++ includes
#include <sstream>
// ///////////////////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[] )
{
std::cout << "argc: " << argc << std::endl;
for (int i=0; i<argc; i+=1) std::cout << argv[i] << " ";
std::cout << std::endl;
setlocale(LC_ALL, "");
std::stringstream ssTest;
{
for (int i=1; i<=8; ++i) // 8 entries
{
ssTest << "Surname" << i << ", Firstname" << i << " Middlename" << i << "\n";
}
// add test cases here
// trailing spaces --------------------------------vv
// ssTest << " SurnameX, FirstnameX MiddlenameX \n" ;
// ^--leading spaces
// ssTest << "SnameY, FnameY MnameY\n" ;
// different size names
}
int retVal = 0;
{
std::stringstream ss (ssTest.str()); // load ss
std::cout << "\nistream (input): \n" << ss.str() << std::endl;
retVal += t266a(ss); // run c++ using c-strings
}
{
std::stringstream ss(ssTest.str()); // load ss
std::cout << "\n\nistream (input): \n" << ss.str() << std::endl;
retVal += t266b(ss); // run c++ using std::string
}
std::cout << "\n\nFINI " << std::endl;
return(retVal);
}
// ///////////////////////////////////////////////////////////////////////
// c++, but using std::string (no c-strings)
int t266b(std::istream& ss)
{
std::cout << "t266b() C++, using std::string (no c-strings)" << std::endl;
std::string buff; // buff grows as needed
size_t buffCount = 0; // line count
//size_t buffLen = 0; // now buff.size()
do
{
buff.clear();
(void)std::getline(ss, buff); // uses default delim ('\n')
if(ss.eof()) break;
if(ss.bad()) { // bad or fail bit set
std::cerr << " " << ss.good()
<< " " << ss.eof()
<< " " << ss.fail()
<< " " << ss.bad()
<< std::endl;
break;
}
buffCount += 1;
if (ss.eof()) break;
//std::cout << " Input: " << buffCount << " (" << buff.size() << ") '" << buff << "'" << std::endl;
// find comma
size_t commaAt = buff.find(',');
if(commaAt == std::string::npos)
{
std::cerr << " Err: invalid input: no comma " << std::endl;
break;
}
if(commaAt < 1)
{
std::cerr << " Err: invalid input: comma at beginning of line "<< std::endl;
break;
}
std::cout << " Output: "
<< buff.substr(commaAt+1) // Firstname Middlename [(where comma was) .. (end of buff)]
<< " "
<< buff.substr(0, commaAt) // Surname [0..(where comma was)]
<< " (buff.size(): " << buff.size() << ")" << std::endl;
if (ss.eof()) { break;}
}while (true);
return(0);
} // int t266b(std::istream&)