我正在尝试使用c-string(没有std:string允许这个字符串)创建程序,其中c-string的内容是格式化的名称:lastName,firstName middleName或者程序将处理的它是lastName,firstMiddleName。
我想要做的只是将格式切换为firstMiddleName lastName。
我想知道是否有一些优雅的方法可以通过使用索引来查找逗号以便将c-string的两个部分分开,然后只是类似于str.substr(0,index)为了轻松交换两个。这有可能吗?我觉得我已经用尽了所有关于此事的帖子
非常感谢任何帮助
答案 0 :(得分:1)
我认为最好为姓氏和名字的人创建struct
。
typedef struct {
char* firstname;
char* lastname;
} person_t;
要通过某个分隔符拆分字符串,您可以使用strtok
这样的函数
char* last = strtok(str, ",");
其中str
是源字符串,,
是分隔符。
现在您需要创建person_t
的实例并复制值
person_t create_person(char* firstname, char* lastname) {
person_t person;
int length;
length = strlen(firstname);
person.firstname = malloc(sizeof(char) * (length + 1));
person.firstname[length] = '\0';
length = strlen(lastname);
person.lastname = malloc(sizeof(char) * (length + 1));
person.lastname[length] = '\0';
strcpy(person.firstname, firstname);
strcpy(person.lastname, lastname);
return person;
}
现在您可以根据需要输出这些值。请参阅下面的完整代码
#include <stdio.h>
#include <string.h>
typedef struct {
char* firstname;
char* lastname;
} person_t;
person_t create_person(char* firstname, char* lastname) {
person_t person;
int length;
length = strlen(firstname);
person.firstname = malloc(sizeof(char) * (length + 1));
person.firstname[length] = '\0';
length = strlen(lastname);
person.lastname = malloc(sizeof(char) * (length + 1));
person.lastname[length] = '\0';
strcpy(person.firstname, firstname);
strcpy(person.lastname, lastname);
return person;
}
int main(void) {
char str[] = "Surname, Firstname Middlename";
char* last = strtok(str, ",");
char* first = strtok(NULL, ",") + 1;
person_t person = create_person(first, last);
printf("firstname: %s\nlastname: %s\n", person.firstname, person.lastname);
return 0;
}
上述代码的输出是
firstname:Firstname Middlename
姓氏:姓氏
另外别忘了清理;)
void remove_person(person_t person) {
free(person.firstname);
free(person.lastname);
}
答案 1 :(得分:0)
您已为C ++标记了此问题。
这里我提出了两个版本。
t266a()符合c ++和stream,但只使用c-string(没有std :: string)
t266b()符合c ++和stream,并使用std :: string(无c-string)
我故意使用空格来将code-with-c-strings的各个部分与code-with-std :: strings对齐,但是你需要将它加载到一个功能强大的编辑器中以便并排显示它们。 / p>
// 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&)