2013-05-02 55 views
1

最後一個字後,我讀了下面的行使用與fgets文件:退出While循環立即在一條線上

#C one two three four five six seven eight nine ten eleven

每個字(除#C)是一列標題。所以我的文件中有十一列。

我的目標是將這一行分成每個單詞的標記。另外,我需要指出的是有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; 
} 
} 

此代碼給我的NcoI = 11,而正常工作(注意,是在該行我讀的最後一個空格)

然而,如果我在該行末尾沒有空格,那麼它會給出ncol = 10並且不讀取最後一列。

我的目標是讓ncol = 11,不管末尾是否有空格。我只想讀最後一個單詞,檢查是否有更多的單詞,如果沒有,然後退出。

回答

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,那麼你有另一個字符串,所以increement ncol中的if。 [您可能會發現,如果輸入的文件是不是「簡潔(wellformed)」的if (strlen(keep))需要更徹底的,但我假設你的輸入是「好」]

0

你可以只檢查標記設置:

if (pch == NULL || *pch == '\0') break; 
+0

NULL和\ 0有什麼區別? @Philip – detraveller 2013-05-02 15:05:32

+1

@detraveller:'NULL'是一個指針值,''\ 0''是一個字符。實際上,你的編譯器使得兩者都爲int,所以這只是爲了澄清。 '* pch =='\ 0''是檢查字符串長度爲0的最快方法。 – Philip 2013-05-02 15:09:42

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; 
} 
0

你有和沒有在最後空間越來越不同的計數,因爲函數fgets包括它從文件中讀取換行符。

因此,當行尾有空格時,換行符會被視爲單獨的令牌。

爲了解決這個問題,您應該在提供給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; 
    } 
}