将单词写入新文件

时间:2018-03-19 22:04:12

标签: c++

我有3个多小时无法理解这项任务的执行情况。

要做到这一点:

  1. 用户必须输入带有分隔符号的句子(昏迷,破折号)。
  2. 将句子写入文件TF4_1.txt
  3. 创建一个新文件TF4_2并写入:  清单项目:

    1)带有一个字母的单词及其在句子中的重复次数。

    2)带有两个字母的单词和句子中的重复次数。

    3)带有三个字母的单词和句子中的重复次数。

    等。最多16个。

  4. 一个单词的长度不能超过16个字符。 必须仅使用char arraysstring不允许。

    #include <fstream>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const char text_separator[] = " ,./?!:();";
    
    int smallest_srt()
    {
        ifstream read_file("TF4_1.txt");
        char buff[256] = { NULL };
        read_file >> buff;
        char *token = strtok(buff, text_separator);
        int smallest = strlen(buff);
        while (token != NULL)
        {
            if (smallest > strlen(token))
                smallest = strlen(token);
            read_file.getline(buff, 256, '\n');
            token = strtok(buff, text_separator);
        }
        read_file.close();
        return smallest;
    }
    
    int main()
    {
        char text_array[256];
        ofstream write_file;
        write_file.open("TF4_1.txt", ios::out | ios::trunc);
        cout << "Enter text: ";
        cin.getline(text_array, 256, '\n');
        write_file << text_array;
        write_file.close();
        int smallest = smallest_srt();
        ifstream read_file("TF4_1.txt");
        char buff[256] = { NULL };
        for (int i = smallest; i < 16; i++)
        {
            read_file.getline(buff, 256, '\n');
            char *token = strtok(buff, text_separator);
            while (token != NULL)
            {
                if (strcmp(world,token) && strlen(token) == i)
                    n++;
    
            }
            //WRITE WORDS IN FILE; ??? (HOW?)
        return 0;
    }
    

    代码无效,尚未完全实现,但至少提供一些提示,如何修复它并制作优化代码。

    结果

    用户类型:这是我的测试句。这很有趣吗?

    我应该在新文件中得到这个:

     1. is - 2 times
     2. my - 1 times
     3. it - 1 times
     4. fun - 1 times
     5. test - 1 times
     6. this - 1 times
    

1 个答案:

答案 0 :(得分:0)

您可以在编程中执行的最昂贵的任务之一是文件I / O.您希望最小化文件打开和读取的数量(尽管您确实获得了BUFSIZ个字符的默认文件缓冲区,在Linux上为8192个字节,在windoze上为512个。

您希望接近任务的方法是读取您的输入一次,根据需要处理它,然后将处理过的信息写入所需的文件一次。

在这里,根据您对我的评论和编辑的回答,您需要确定每个单词的出现次数(每个单词最多16个字符),将用户输入的句子写入{{1将单词频率写入"TF4_1.txt"。 (未指定排序顺序,如果需要特定订单,请添加对"TF4_2.txt"的调用)

当您考虑协调不同类型的多条信息时,您应该立即考虑qsort。对于两个数据,您可以使用多个数组,但通常情况下,首选保存信息的struct数组。在这里,您需要为每个单词保留一个单词和一个计数。您可以声明一个简单的结构来处理您的存储需求,如下所示:

struct

(方便使用#define MAXC 1024 /* if you need constants, define them */ #define MAXL 32 /* (don't skimp on buffer size) */ #define MAXW 256 /* max chars in buf, word len, no. words */ ... typedef struct { /* struct to associate word and count */ char word[MAXL]; int count; } wstat;

逻辑的其余部分对于此类问题是相当标准的。你读了你的句子,你将字符串标记,(在你的情况下你将每个标记转换为小写),你循环你已经存储的单词 - 比较小写标记和存储的单词。如果找到匹配项,只需增加该单词的typedef,否则将小写标记复制到struct数组中的下一个可用count,增加element.word和数组结构索引。

您还必须注意保护数组边界,然后将索引与最大元素数进行比较。

处理完每个令牌后,只需将数组写入element.count,关闭文件即可 - 完成后。

完全放弃,你可以做类似以下的事情:

"TF4_2.txt"

示例使用/输出

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cctype>

using namespace std;

#define MAXC 1024   /* if you need constants, define them    */
#define MAXL   32   /*    (don't skimp on buffer size)       */
#define MAXW  256   /* max chars in buf, word len, no. words */

#define SENTOUT "TF4_1.txt"       /* sentence out filename   */
#define STATOUT "TF4_2.txt"       /* statistics out filename */

typedef struct {       /* struct to associate word and count */
    char word[MAXL];
    int count;
} wstat;

int main (void) {

    char buf[MAXC] = "",                /* buffer to hold line */
        *p = buf;                       /* pointer to buffer */
    const char *delim = " ,./?!:();";   /* strtok delimiters */
    int wcount = 0;                     /* word count */
    wstat wstats[MAXW] = {{"", 0}};     /* word stats array */

    /* prompt for input */
    cout << "enter sentence (words 16 char or less): ";
    if (!(cin.get (buf, MAXC, '\n'))) { /* validate input */
        cerr << "error: invalid input or user canceled.\n";
        return 1;
    }
    cout << buf << "\n";                /* output to stdout (optional) */
    ofstream f(SENTOUT, ios::trunc);    /* open TF4_1.txt for writing */
    if (!f.is_open()) {                 /* validate file open for writing */
        cerr << "error: file open failed '" << SENTOUT << "'.\n";
        return 1;
    }
    f << buf << "\n";                   /* write sentence to TF4_1.txt */
    f.close();                          /* close TF4_1.txt */

    /* tokenize input */
    for (p = strtok (p, delim); p; p = strtok (NULL, delim)) {
        int seen = 0;                   /* flag if word already seen */
        char lccopy[MAXL] = "",         /* array for lower-case copy */
            *rp = p,                    /* read-pointer to token */
            *wp = lccopy;               /* write-pointer for copy */
        while (*rp)                     /* iterate over each char */
            *wp++ = tolower(*rp++);     /* convert to lowercase */
        *wp = 0;                        /* nul-terminate lccopy */
        for (int i = 0; i < wcount; i++)    /* loop over stored words */
            /* compare lccopy to stored words */
            if (strcmp (lccopy, wstats[i].word) == 0) { /* already stored */
                wstats[i].count++;      /* increment count for word */
                seen = 1;               /* set seen flag */
            }
        if (!seen) {    /* if not already seen */
            strcpy (wstats[wcount].word, lccopy);   /* copy to wstats */
            wstats[wcount++].count++;   /* increment count for word */
            if (wcount == MAXW) {       /* protect array bounds */
                cerr << "maximum words reached: " << MAXW << "\n";
                break;
            }
        }
    }

    f.open (STATOUT, ios::trunc);       /* open TF4_2.txt */
    if (!f.is_open()) {                 /* validate file open for writing */
        cerr << "error: file open failed '" << STATOUT << "'.\n";
        return 1;
    }
    for (int i = 0; i < wcount; i++) {  /* loop over stored word stats */
        /* output to stdout (optional) */
        cout << " " << left << setw(16) << wstats[i].word << 
                "   " << wstats[i].count << "\n";
        /* output to TF4_2.txt */
        f << " " << left << setw(16) << wstats[i].word << 
            "   " << wstats[i].count << "\n";
    }
    f.close();                          /* close TF4_2.txt */
}

示例TF4_1.txt

$ ./bin/wordlenfreq
enter sentence (words 16 char or less): This is my test sentence. Is it fun?
This is my test sentence. Is it fun?
 this               1
 is                 2
 my                 1
 test               1
 sentence           1
 it                 1
 fun                1

示例TF4_2.txt

$ cat TF4_1.txt
This is my test sentence. Is it fun?

虽然掌握使用基本类型(例如$ cat TF4_2.txt this 1 is 2 my 1 test 1 sentence 1 it 1 fun 1 并且学会考虑您填充的字符和存储的元素索引)总是很好,但您也可以在C中编写代码。这将是一个简单的头文件名更改,为char交换fgets或POSIX getlinecin.get(或printffprintf和{ {1}}和cout用于文件流打开/关闭操作。

使用C ++,cerrfopen/fclose类型可以让您的工作更轻松。它将处理字符串和结构存储要求,并确保您不要超出存储的范围。 (但注意:您仍需要stringvector,因为C ++ <cstring>无法根据多个分隔符分隔字符串。

仔细看看,如果您有其他问题,请告诉我。