簡體   English   中英

不了解sscanf()函數的工作方式

[英]Don't understand how sscanf() function works

我不明白如何在C ++中使用sscanf()從文件中讀取。

我正在開發一個程序,該程序從文件中讀取跑步者的三個名字,以及他們五個最好的時間。 我想平均每個跑步者的時間,並說出最佳跑步者是誰。 我在文件IO方面絕對是最艱難的時刻。

Cplusplus.com幫助了一些人,但並沒有真正說出如何閱讀,將char *(名稱)與浮點數(時間)分開等。在其他地方,我無法逃避專業術語和過於技術性的解釋。

一位朋友向我展示了此代碼段以進行解釋。

while(file>>str) {
    sscanf (str.c_str(),"%d",&myint);
}    

有人介意向我解釋閱讀方式嗎?

使用sscanf()被認為有點老套了,但它可能非常有益並且值得精通。 我認為您正在尋找類似的東西:

sscanf(input, "%s %f", name, &time);

input是文件中的一行。 一些基本知識是基本字符串的%s和浮點數的%f

享受開始編程的樂趣; 它只會隨着您獲得經驗而變得更好。

總體而言, sscanf()函數用於在格式字符串的指導下將(C)字符串轉換為程序變量中的一系列值,該格式字符串描述了將在字符串中找到的值。

剖析引用的代碼:

while (file >> str)
{
    sscanf(str.c_str(), "%d", &myint);
}

我們可以假設file是輸入流,而str是字符串。 while循環在每次迭代時從輸入中讀取一個“單詞”到字符串中,其中“單詞”是一系列非空白字符,可能前面帶有一系列空白字符。

該示例中的sscanf()語句具有三個參數和一個返回值,該值將被忽略(這將帶來危險)。 第一個參數是C樣式字符串,因此通過str.c_str()調用將讀取的單詞轉換為C字符串。 第二個參數是格式字符串,它告訴sscanf()在字符串中期望什么。 在這種情況下, %d轉換說明符表示一個十進制整數。 第三個參數是指向相應類型的指針,轉換后的值將存儲在該類型中。 通常,格式字符串可以包含許多轉換說明符,並且每個分配的轉換說明符都需要一個指針參數(您可以通過抑制分配來跳過數據)。

sscanf()的返回值是成功分配轉換的次數。 在這種情況下,您應該檢查是否完成了一次轉換。

這是根據您的示例運行的微型程序:

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>

static void read_stuff(std::istream &file)
{
    std::string str;
    while (file >> str)
    {
        std::cout << "IN: <<" << str << ">>" << std::endl;
        int myint;
        if (sscanf(str.c_str(), "%d", &myint) != 1)
        {
            std::cerr << "Oops: sscanf() failed" << std::endl;
            std::exit(1);
        }
        std::cout << "GOT: " << myint << std::endl;
    }
}

int main()
{
    read_stuff(std::cin);
    return(0);
}

假設您輸入輸入行: 123 234 345 abc 然后程序產生:

IN: <<123>>
GOT: 123
IN: <<234>>
GOT: 234
IN: <<345>>
GOT: 345
IN: <<abc>>
Oops: sscanf() failed

請注意,如果您要處理的名稱包含名字和姓氏,可能帶有中間的首字母縮寫,並且有5個數字(全部在一行中),那么您可能需要一個不同的過程。 您可能會使用getline()讀取整行,然后嘗試使用sscanf()對其進行解析(或者您可能會使用stringstream代替)。 當然,您只需要處理少於5個數字即可。 I / O總是很棘手,特別是當您也必須處理錯誤數據時(並且必須始終准備好生產質量代碼來處理錯誤數據)。

scanf,如果與printf相反。

“ sscanf”中的第一個“ s”表示它掃描字符串。 “ fscanf”掃描文件,“ scanf”掃描標准輸入。

格式與printf相同。

如果sprintf(s, "%dx", 5) “ 5 x”打印到s中,則sscanf("5 x", "%dx", &n)將5放入n中。 總是與printf相反。

%s是例外。 printf中的%s打印每個字符串。 printf(“%s”,str); 不管str是什么,都會打印str。 在scanf中, %s是一個詞。 一個詞是沒有空格的東西。 因此讀%s只會讀一個字。

sscanf(str, "%d", &a); 表示str的格式為“%d”(一個十進制數字),並且您將該數字設置為a(因為&a是第二個參數)。

舉個例子

int a,b,c,d;
sscanf("10,20,30,40", "%d,%d,%d,%d", &a, &b, &c, &d);

將得出a = 10,b = 20,c = 30,d =40。每個%d都將讀取下一個參數,每個%d都將讀取一個十進制數字。

基本上,您可以在sscanf函數的第二個參數中指定字符串格式,以用占位符替換要解析的變量。

假設您知道文件包含以下幾行:

Father bought 8 bottles of rum on day 1.  
Father bought 11 bottles of rum on day 2.  
Father bought 5 bottles of rum on day 3.  
Father bought 19 bottles of rum on day 4. 

除了每天的瓶子數量外,您無需擔心該字符串中的任何內容。 您修復了不變的部分,即“父親在一天中購買了一瓶朗姆酒”,並為要從字符串中提取的部分指定一個占位符。

您的代碼如下所示:

int nDay, nBottles;
sscanf(str.c_str(), "Father bought %d bottles of rum on day %d", &nBottles, &nDay);
cout << "Day: " << nDay << ", bottles: " << nBottles << endl;

%后面的符號僅指定要解析的部分的變量類型。 d在這里表示十進制。

只需使用sscanf(str.c_str(), "%d", &myint)而不是sscanf(str, "%d", &myint)

我看到其他人對sscanf了解釋,但我認為您的問題有些不同。

sscanf是C函數,但是您可以在C ++中使用它,因為C ++包含sscanf基本采用字符串,將其按顯示方式進行分割,然后將這些部分分配給變量。 但是在C中沒有這樣的東西叫做string 。因此, sscanf將其參數作為char*char pointer ,它基本上與string進行相同的工作。

在C ++中,應使用c_str()函數將string轉換為char pointer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM