主頁 > 移動端開發 > 從檔案中讀取逗號分隔的單詞

從檔案中讀取逗號分隔的單詞

2022-04-29 17:13:07 移動端開發

FILE* inp;
inp = fopen("wordlist.txt","r");        //filename of your data file
char arr[100][5];           //max word length 5
int i = 0;
while(1){
    char r = (char)fgetc(inp);
    int k = 0;
    while(r!=',' && !feof(inp)){    //read till , or EOF
        arr[i][k  ] = r;            //store in array
        r = (char)fgetc(inp);
    }
    arr[i][k]=0;        //make last character of string null
    if(feof(inp)){      //check again for EOF
        break;
    }
    i  ;
}

我正在讀取檔案單詞并將它們存盤在陣列中。我的問題是:如何隨機選擇其中 7 個單詞并將它們存盤在陣列中?

輸入檔案有以下內容:

https://ibb.co/LkSJ1SV

meal
cheek
lady
debt
lab
math
basis
beer
bird
thing
mall
exam
user
news
poet
scene
truth
tea
way
tooth
cell
oven

uj5u.com熱心網友回復:

首先,您的程式存在以下問題:

  1. 在您發布的輸入中,一些單詞有 5 個字符長,但您的陣列只有 4 個字符加上終止空字符的空間。
  2. 您發布的輸入中的單詞由換行符分隔,而不是逗號。因此,您搜索輸入流是沒有意義的','

在您的代碼中修復這兩個問題并添加一個函式main和所有必要的標頭后,它應該如下所示:

#include <stdio.h>

int main( void )
{
    FILE* inp;
    inp = fopen("wordlist.txt","r");        //filename of your data file
    char arr[100][6];           //max word length 5
    int i = 0;
    while(1) {
        char r = (char)fgetc(inp);
        int k = 0;
        while(r!='\n' && !feof(inp)) {   //read till , or EOF
            arr[i][k  ] = r;            //store in array
            r = (char)fgetc(inp);
        }
        arr[i][k]=0;        //make last character of string null
        if(feof(inp)){      //check again for EOF
            break;
        }
        i  ;
    }
}

在 C 中,通常使用該函式rand來生成 和 之間的隨機0RAND_MAX宏常數RAND_MAX保證至少為32767.

為了得到一個和之間的亂數0i不包括i它自己),你可以使用下面的運算式,它使用了取運算子:

rand() % i

這不會為您提供亂數的均勻分布,但對于大多數常見目的來說已經足夠了。

因此,為了選擇并列印一個隨機單詞,可以使用以下陳述句:

printf( "%s\n", rand() % i );

如果要選擇并列印 7 個隨機單詞,則可以回圈運行此陳述句 7 次。但是,可能會多次隨機選擇同一個單詞。如果您想防止這種情況發生,那么您將不得不使用更復雜的演算法,例如Fisher-Yates shuffle

但是,這將在您每次運行程式時列印相同的隨機單詞序列。如果您希望亂數生成器在每次運行程式時生成不同的亂數序列,那么您必須通過呼叫srand帶有一些隨機資料的函式來為亂數生成器播種。

最簡單的隨機性來源是當前時間。該函式time將回傳一個表示當前時間的整數,通常以秒為單位。

srand( (unsigned)time(NULL) );

但是,由于該函式time通常使用秒,這意味著如果您在同一秒內運行程式兩次,亂數生成器將以相同的值作為種子,因此它將生成相同的亂數序列。如果這是一個問題,那么您可能希望找到其他一些隨機性來源。

完成上述所有操作并添加必要的標頭后,您的程式應如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main( void )
{
    FILE* inp;
    inp = fopen("wordlist.txt","r");        //filename of your data file
    char arr[100][6];           //max word length 5

    srand( (unsigned)time(NULL) );

    int i = 0;
    while(1) {
        char r = (char)fgetc(inp);
        int k = 0;
        while(r!='\n' && !feof(inp)) {   //read till , or EOF
            arr[i][k  ] = r;            //store in array
            r = (char)fgetc(inp);
        }
        arr[i][k]=0;        //make last character of string null
        if(feof(inp)){      //check again for EOF
            break;
        }
        i  ;
    }

    //print 7 random words
    for ( int j = 0; j < 7; j   )
        printf( "%s\n", arr[rand()%i] );
}

對于輸入

meal
cheek
lady
debt
lab
math
basis
beer
bird
thing
mall
exam
user
news
poet
scene
truth
tea
way
tooth
cell
oven

該程式給了我以下(隨機)輸出:

user
mall
poet
lab
cheek
lab
beer

如您所見,其中一個隨機單詞是重復的。

如前所述,如果您想防止同一個單詞被選擇兩次,您可以使用Fisher-Yates shuffle對陣列進行洗牌。改組陣列后,您可以簡單地選擇并列印陣列的前 7 個元素,如果這是您要選擇的單詞數:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main( void )
{
    FILE* inp;
    inp = fopen("wordlist.txt","r");        //filename of your data file
    char arr[100][6];           //max word length 5

    srand( (unsigned)time(NULL) );

    int i = 0;
    while(1) {
        char r = (char)fgetc(inp);
        int k = 0;
        while(r!='\n' && !feof(inp)) {   //read till , or EOF
            arr[i][k  ] = r;            //store in array
            r = (char)fgetc(inp);
        }
        arr[i][k]=0;        //make last character of string null
        if(feof(inp)){      //check again for EOF
            break;
        }
        i  ;
    }

    //perform a Fisher-Yates shuffle on the array
    for ( int j = 0; j < i - 1; j   )
    {
        char temp[6];

        int k = rand() % ( i - j )   j;

        if ( j != k )
        {
            //swap both array elements
            strcpy( temp, arr[j] );
            strcpy( arr[j], arr[k] );
            strcpy( arr[k], temp );
        }
    }

    //print first 7 elements of the shuffled array
    for ( int j = 0; j < 7; j   )
    {
        //NOTE: This code assumes that i > 7, otherwise
        //it may crash.

        printf( "%s\n", arr[j] );
    }
}

現在,同一個詞不能再被選擇兩次:

meal
thing
news
user
mall
exam
tea

在上面的程式中,我對整個陣列進行了洗牌。但是,如果我只需要隨機化前 7 個單詞,那么在改組時只執行 7 次外回圈迭代就足夠了。

uj5u.com熱心網友回復:

重要的

該解決方案具有weak random distribution單詞選擇,但考慮any length了從檔案輸入的總單詞。

理念

  • 為了簡單起見,每個單詞的字符數最多為 256(包括 \0),因此對于小示例來說我們是安全的。
  • 要使用的陣列最終將具有您要保存的總字數的大小。那是因為不需要存盤所有單詞然后選擇7個。您可以在讀取檔案時隨機覆寫以前的單詞來選擇7個單詞。
  • 第一個 while 回圈將確保填充陣列,因此沒有空單元格。
  • 第二個 while 回圈將隨機覆寫以前的單元格。

解決方案

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define TOTAL_WORDS 7
#define CHARS_PER_WORD 256

void readWord(FILE* inp, char [TOTAL_WORDS][CHARS_PER_WORD], int i);

int main(int argc, char const *argv[]) {
    srand(time(NULL));

    char arr[TOTAL_WORDS][CHARS_PER_WORD] = { 0 };

    FILE* inp;
    inp = fopen("wordlist.txt","r");
    // make sure file opening did not fail
    if( inp == NULL ) {
        printf("Could not open file.\n");
        return 0;
    }

    int i = 0;

    while( i < TOTAL_WORDS && !feof(inp) )
        readWord(inp,arr,i  );

    while( !feof(inp) ) {
        if( (rand()%  2) == 1 )
            readWord(inp,arr,rand() % TOTAL_WORDS);
        else // consume the word without saving it
            while( fgetc(inp)!='\n' && !feof(inp) ) { } 
    }

    for( int i = 0; i<TOTAL_WORDS; i   ) 
        printf("%d: %s\n", i, arr[i]);

    return 0;
}

void readWord(FILE* inp, char arr[TOTAL_WORDS][CHARS_PER_WORD], int i) {
    int k = 0;
    char r = (char) fgetc(inp);
    while( r!='\n' && !feof(inp) ){
        arr[i][k  ] = r;
        r = (char) fgetc(inp);
    }
    arr[i][k]='\0';  
}

輸入檔案wordlist.txt包含:

meal
cheek
lady
debt
lab
math
basis
beer
bird
thing
mall
exam
user
news
poet
scene
truth
tea
way
tooth
cell
oven

結果之一是:

0: scene
1: truth
2: tooth
3: oven
4: way
5: user
6: cell

添加/更改說明

包含函式的C 庫,srand()用于隨機化內容。time()rand()

#include <stdlib.h>
#include <time.h>

定義我們想在最后保留多少單詞。如果我們想從更改為其他內容,這將很有用7每次我們想要參考我們想要保留多少個單詞時,7我們都會使用它,而不是到處使用。TOTAL_WORDS在同一個注釋中定義每個單詞有多少個字符。

#define TOTAL_WORDS 7
#define CHARS_PER_WORD 256

初始化函式 rand() 的種子。你可以在這里閱讀更多關于它的資訊

srand(time(NULL));

獲取我們陣列大小范圍內的數字。您可以在此處閱讀有關 rand() 函式的更多資訊

rand() % TOTAL_WORDS

對于avoid repeating兩個 while 回圈中的同一件事,你read a word from the file被封裝在一個函式中的部分。這使得主代碼更易于閱讀和維護。

void readWord(FILE* inp, char arr[TOTAL_WORDS][CHARS_PER_WORD], int i) {
    ...  
}

列印保存的單詞。

for( int i = 0; i<TOTAL_WORDS; i   ) 
    printf("%d: %s\n", i, arr[i]);

uj5u.com熱心網友回復:

此解決方案是我最初解決方案的更好版本。

解決方案

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define INPUT_FILE "wordlist.txt"
#define TOTAL_WORDS 7
#define CHARS_PER_WORD 256
#define DELIMETER '\n'

FILE* input;

char word[CHARS_PER_WORD];
char words[TOTAL_WORDS][CHARS_PER_WORD];

void openFile();    
void readWord();
void saveWord(int position);
void pickWords();
void printWords();
int hasWordAt(int position);
int isFull();

int main(int argc, char const *argv[]) {
    srand(time(NULL));

    openFile();

    pickWords();

    printWords();

    return 0;
}

void printWords() {
    for( int i = 0; i<TOTAL_WORDS; i   ) 
        printf("%d: %s\n", i, words[i]);
}

void pickWords() {
    int pos;
    while( !feof(input) && !isFull() ) {
        readWord();
        do {
            pos = rand() % TOTAL_WORDS;
        } while( hasWordAt(pos) );
        saveWord(pos);
    }
    while( !feof(input) ) {
        readWord();
        if( (rand() % 2) == 0 )
            continue;
        pos = rand() % TOTAL_WORDS;
        saveWord(pos);
    }
}

int hasWordAt(int position) {
    return words[position][0] != '\0';
}

int isFull() {
    for( int i = 0; i<TOTAL_WORDS; i   ) 
        if( words[i][0] == '\0' )
            return 0;
    return 1;
}

void saveWord(int position) {
    strcpy(words[position],word);
}

void readWord() {
    int i = 0;
    char ch = (char) fgetc(input);
    while( ch != DELIMETER && !feof(input) ){
        word[i  ] = ch;
        ch = (char) fgetc(input);
    }
    word[i]='\0';  
}

void openFile() {
    input = fopen(INPUT_FILE,"r");
    if( input == NULL ) {
        printf("Couldn't open file.");
        exit(0);
    }
}

改進

  • 第一個詞的分布
  • 代碼結構

目前我沒有時間編輯完整的解釋,雖然大部分都在我的初始答案中進行了解釋,但更好地解釋了這個答案

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/467402.html

標籤:C

上一篇:C動態結構陣列

下一篇:如何實作數字河流?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more