我正在使用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,无论最后是否有空格。我只想阅读最后一个单词,检查是否有更多单词,如果没有,则退出。
答案 0 :(得分:0)
如果你改变这个循环:
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))
需要更加彻底,但我假设你的输入是“很好”]
答案 1 :(得分:0)
您可以检查是否设置了令牌:
if (pch == NULL || *pch == '\0') break;
答案 2 :(得分:0)
另一种解决方案,更灵活,需要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;
}
答案 3 :(得分:0)
您最终会获得带有和不带空格的不同计数,因为函数fgets
包含从文件中读取的换行符。
因此,当行尾有空格时,换行符被视为一个单独的标记。
要解决此问题,您应该添加换行符'\ r'&amp; '\ 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," \r\n");
while(pch != NULL){
pch = strtok (NULL, " \r\n");
//amount of columns.
ncol++;
}
break;
}
}