C++ 在一行中的最后一个单词之后立即退出While循环
我正在使用fgets从文件中读取以下行:C++ 在一行中的最后一个单词之后立即退出While循环,c++,strtok,C++,Strtok,我正在使用fgets从文件中读取以下行: C 12345678910十一 每个单词(C除外)都是一个列标题。因此,我的文件中有11列 我的目标是将这一行划分为每个单词的标记。另外,我需要计算有11个列标题。(列标题可以多于或少于11个) 我的问题是这行末尾的空格。以下是我正在使用的代码: while(1){ fgets(buffer,1024,filename); if (buffer[1] == 'C'){ char* str = buffer+2; char* pch;
<代码> C 12345678910十一
每个单词(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++;
}
致:
因此,如果字符串中还剩下一些内容,那么当
pch
为空时,就有另一个字符串,因此在if中增加ncol
。[您可能会发现,如果输入文件不是“格式良好的”if(strlen(keep))
需要更彻底,但我假设您的输入是“良好的”]您可以检查是否设置了令牌:
if (pch == NULL || *pch == '\0') 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;
}
#包括
#包括
#包括
模板
无效拆分(StringType常量和内容、结果和结果、StringType常量和分隔符=“\n”)
{
typedef typename结果::值\类型值\类型;
静态断言(std::is_same::value,“std::is_same::value==false,\n”
“结果的值_类型应与StringType相同”);
typename StringType::size\u-type-pos,last\u-pos=0;
while(true)
{
pos=内容。查找(分隔符,最后一个pos)中的第一个;
if(pos==StringType::npos)
{
pos=contents.length();
如果(位置!=最后位置)
result.emplace_back(contents.data()+last_pos,pos-last_pos);
打破
}
其他的
{
如果(位置!=最后位置)
result.emplace_back(contents.data()+last_pos,pos-last_pos);
}
最后一个位置=位置+1;
}
}
int main()
{
STD::String const输入=“γC 12345678910十一”;
std::矢量结果;
拆分(输入、结果、标准::字符串(“”);
用于(自动常量和数据:结果){
std::cout由于函数包含它从文件中读取的换行符,因此在结尾处有空格和没有空格的计数不同
因此,当行尾有空格时,换行符被视为一个单独的标记
为了克服这一问题,您应该在提供给strtok
函数的令牌中包含换行符“\r”和“\n”,并远程调用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;
}
}
NULL和\0之间有什么区别@Philip@detraveller:NULL
是一个指针值,'\0'
是一个字符。实际上,您的编译器将int0
从两者中提取出来,因此这只是为了澄清。*pch=='\0'
是检查字符串长度是否为0的最快方法。
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;
}
}