我需要每个单词的第一个和最后一个字母是大写的,其余的是小写的,但是函数convertFirstAndLastLetter只做句子的第一个和最后一个。
void convertFirstAndLastLetter(char wrd[])
{
size_t last = strlen(wrd) - 1;
size_t first = 0;
wrd[first] = toupper(wrd[first]);
wrd[last] = toupper(wrd[last]);
for(int i = first + 1 ; i < last - 1; i++)
{
wrd[i] = tolower(wrd[i]);
}
}
int main ()
{
float val;
cout << "ent ";
cin >> val;
if (val == 4)
{
char wrd[256];
cin.ignore();
cin.getline(wrd,256);
convertFirstAndLastLetter(wrd);
cout << wrd;
return 0;
}
}
现在你将一整行传递给你的函数,所以第一个和最后一个字符是所有被改变的。
要解决这个问题,您需要将一行拆分为单词,这可以通过使用std::cin >> word
一次读取一个单词来完成,或者读取整行,然后使用std::stringstream
将其拆分。两者基本相同,但我使用了stringstream。
接下来,如果我没看错的话,你想让每个单词的第一个和最后一个"字母"大写,其余的小写。这意味着如果单词前后有标点符号,我们需要找到第一个和最后一个字母。
一旦确定了第一个和最后一个,就很容易将它们大写,其余的小写。
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
void convertFirstAndLastLetter(std::string& word)
{
if(!word.empty())
{
size_t first = 0;
size_t last = word.size() - 1;
//Find first alpha character
while(first < word.size() && !std::isalpha(word[first]))
{
++first;
}
//If the position is valid, uppercase it
if(first < word.size())
{
word[first] = static_cast<char>(std::toupper(word[first]));
}
//Find last alpha character
while(last > first && !std::isalpha(word[last]))
{
--last;
}
//If the position is valid, uppercase it
if(last > first)
{
word[last] = static_cast<char>(std::toupper(word[last]));
}
for(size_t i = first + 1; i < word.size() && i < last; ++i)
{
if(std::isalpha(word[i]))
{
word[i] = static_cast<char>(std::tolower(word[i]));
}
}
}
}
int main()
{
float val;
std::cout << "ent ";
std::cin >> val;
std::cin.ignore();
if(val == 4)
{
std::string line;
if(std::getline(std::cin, line))
{
std::string word;
std::stringstream ss(line);
while(ss >> word)
{
convertFirstAndLastLetter(word);
std::cout << word << " ";
}
std::cout << "n";
}
}
return 0;
}
请记住,这将丢弃每行开头和结尾的任何额外空格以及单词之间的任何额外空格。我打印它们的方式也会在每行的末尾增加一个额外的空格。你在问题中没有提到对这些事情的担忧,所以我不担心。
现在使用较少重复的代码:
#include <algorithm>
#include <iostream>
#include <string>
template<typename It>
void upperFirstAlpha(It begin, It end)
{
auto first = std::find_if(begin, end, isalpha);
if (first != end)
*first = toupper(*first);
}
int main()
{
for (std::string s; std::cin >> s;) {
std::transform(s.begin(), s.end(), s.begin(), tolower);
upperFirstAlpha(s.begin(), s.end());
upperFirstAlpha(s.rbegin(), s.rend());
std::cout << s << ' ';
}
}
正如@Retired Ninja指出的,第一个版本不支持标点符号,这个版本是否是你想要的取决于你输入的内容。
此函数
void convertFirstAndLastLetter(char wrd[])
{
size_t last = strlen(wrd) - 1;
size_t first = 0;
wrd[first] = toupper(wrd[first]);
wrd[last] = toupper(wrd[last]);
for(int i = first + 1 ; i < last - 1; i++)
{
wrd[i] = tolower(wrd[i]);
}
}
是错误的。例如,如果字符数组为空,即它只有终止零,那么表达式strlen(wrd) - 1
将为类型为size_t
的对象提供最大值,并在下一个语句
wrd[last] = toupper(wrd[last]);
您将尝试更改数组以外的内存。
如果你使用标准函数strlen
,那么你必须包含标题<cstring>
。
实际上没有必要使用strlen函数。代码可以写得更简单
#include <cctype>
//...
void convertFirstAndLastLetter( char wrd[] )
{
if ( *wrd )
{
*wrd = std::toupper( *wrd );
if ( *++wrd )
{
while ( *( wrd + 1 ) )
{
*wrd = std::tolower( *wrd );
++wrd;
}
*wrd = std::toupper( *wrd );
}
}
}
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
void convertFirstAndLastLetter(char wrd[])
{
size_t last = strlen(wrd) - 1;
size_t first = 0;
wrd[first] = toupper(wrd[first]);
wrd[last] = toupper(wrd[last]);
for(int i = first + 1 ; i < last; i++)
{
wrd[i] = tolower(wrd[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
float val;
cout << "ent ";
cin >> val;
if (val == 4)
{
char wrd[256];
cin.ignore();
cin.getline(wrd,256);
convertFirstAndLastLetter(wrd);
cout << wrd;
return 0;
}
}