我正在使用fgets从文件中读取以下行:
#C one two three four five six seven eight nine ten eleven
每个单词(除了#C)都是一个列标题。我的文件中有11列。
我的目的是将这一行划分为每个单词的标记。此外,我需要计算有11个列标题。(列标题可以多于或少于11个)
我的问题是这一行末尾的空格。下面是我使用的代码:
while(1){
fgets(buffer,1024,filename);
if (buffer[1] == 'C'){
char* str = buffer+2;
char* pch;
pch = strtok(str," ");
while(pch != NULL){
pch = strtok (NULL, " ");
if (pch == NULL)break; //without this, ncol contains +1 the
//amount of columns.
ncol++;
}
break;
}
}
这段代码给出了ncol = 11。而且效果很好。(请注意,在我正在阅读的行末尾有一个空格)
然而,如果我在行尾没有空格,那么它给出ncol = 10,并且不读取最后一列。
我的目标是得到ncol =11,不管是否有空格在not的末尾。我只想读最后一个单词,检查是否还有单词,如果没有,然后退出
如果你改变这个循环:
while(pch != NULL){
pch = strtok (NULL, " ");
if (pch == NULL)break; //without this, ncol contains +1 the
//amount of columns.
ncol++;
}
:
while(pch != NULL){
char *keep = pch;
pch = strtok (NULL, " ");
if (pch == NULL)
{
if (strlen(keep))
{
ncol++;
}
break; //without this, ncol contains +1 the
}
//amount of columns.
ncol++;
}
所以,如果字符串中还有东西,当pch
为NULL时,那么你有另一个字符串,所以在if中增加ncol
。[您可能会发现,如果输入文件不是"格式良好"的if (strlen(keep))
需要更彻底,但我假设您的输入是"好的"]
您可以检查是否设置了标记:
if (pch == NULL || *pch == ' ') break;
另一种解决方案,更灵活,需要c++11支持
#include <iostream>
#include <string>
#include <vector>
template <typename Result, typename StringType>
void split(StringType const& contents, Result &result, StringType const& delimiters = "n")
{
typedef typename Result::value_type value_type;
static_assert(std::is_same<value_type, StringType>::value, "std::is_same<value_type, StringType>::value == false,n"
"The value_type of Result should be the same as StringType");
typename StringType::size_type pos, last_pos = 0;
while(true)
{
pos = contents.find_first_of(delimiters, last_pos);
if(pos == StringType::npos)
{
pos = contents.length();
if(pos != last_pos)
result.emplace_back(contents.data() + last_pos, pos - last_pos);
break;
}
else
{
if(pos != last_pos)
result.emplace_back(contents.data() + last_pos, pos - last_pos );
}
last_pos = pos + 1;
}
}
int main()
{
std::string const input = "#C one two three four five six seven eight nine ten eleven";
std::vector<std::string> results;
split(input, results, std::string(" "));
for(auto const &data : results){
std::cout<<data<<std::endl;
}
return 0;
}
由于函数fgets
包含它从文件中读取的换行符,因此您将得到末尾有空格和没有空格的不同计数。
因此,当行尾有空格时,换行符被认为是一个单独的标记。
要克服这个问题,你应该包括换行字符'r' &将'n'放入提供给strtok
函数的令牌中,并远程if (pch == NULL)break;
行。
所以代码是;
while(1){
fgets(buffer,1024,filename);
if (buffer[1] == 'C'){
char* str = buffer+2;
char* pch;
pch = strtok(str," rn");
while(pch != NULL){
pch = strtok (NULL, " rn");
//amount of columns.
ncol++;
}
break;
}
}