我有3个多小时无法理解这项任务的执行情况。
要做到这一点:
创建一个新文件TF4_2并写入: 清单项目:
1)带有一个字母的单词及其在句子中的重复次数。
2)带有两个字母的单词和句子中的重复次数。
3)带有三个字母的单词和句子中的重复次数。
等。最多16个。
一个单词的长度不能超过16个字符。
必须仅使用char arrays
。 string
不允许。
#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
答案 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 getline
,cin.get
(或printf
)fprintf
和{ {1}}和cout
用于文件流打开/关闭操作。
使用C ++,cerr
和fopen/fclose
类型可以让您的工作更轻松。它将处理字符串和结构存储要求,并确保您不要超出存储的范围。 (但注意:您仍需要string
和vector
,因为C ++ <cstring>
无法根据多个分隔符分隔字符串。
仔细看看,如果您有其他问题,请告诉我。