在一行最后一个单词之后立即退出While循环



我正在使用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;
    }
}

相关内容

  • 没有找到相关文章

最新更新