c - 如何逐字计算文件中的元音数量并将结果附加到单词中?
问题描述
我正在尝试用 C 编写代码,从文件中读取n 个单词并逐字修改内容。
该程序将计算每个单词中元音的数量。如果当前单词中元音的个数是偶数,程序会将元音成对交换(如果是奇数则不交换),然后将元音个数附加到单词上。
例如,如果单词是apple
,修改后的单词将看起来像eppla_2vow
。
我的问题是我不太清楚我应该如何逐字进行修改。
FILE *f = fopen("input.dat","r");
int i;
int bufflen=256;
char buff[bufflen];
while(n)
{
fscanf(f,"%s",buff);
n--;
}
int vowels=0;
for(i=0; buff[i]!='\0'; i++)
{
if (buff[i] == 'a' || buff[i] == 'e' || buff[i] == 'i' ||
buff[i] == 'o' || buff[i] == 'u' || buff[i] == 'A' ||
buff[i] == 'E' || buff[i] == 'I' || buff[i] == 'O' ||
buff[i] == 'U')
{ vowel++;}
if (buff[i] == ' ')
{
vowels=0;
}
}
我什至不确定我是否以正确的方式迭代字符串以便能够进行这些修改。
我再举一个例子,假设文件的内容是:
apple juice strawberry can make pineapple
修改后的单词将如下所示:
eppla_2vow juice_3vow strewbarry_2vow can_1vow meka_2vow penieppla_4vow
解决方案
这可以分为几个子任务:
首先,我们需要一个函数来计算字符串中元音的数量。这很简单。我们可以将其概括为计算一个字符串中任何字符在另一个字符串中出现的次数,而不会遇到任何麻烦。
其次,我们需要一个交换字符串中元音的函数。两分球技术似乎是解决这个问题的方法。当前指针和后指针没有相遇时,向前迭代前指针,直到它落在一个元音上。此时,递减反向指针,直到它碰到一个元音并交换它们。继续这样交换,直到指针交叉。如上所述,很容易将字符列表传递到字符串中。
除此之外,其他一切都是样板文件——在空格和 IO 上对字符串进行分块。将结果写回文件而不是字符串可以更轻松地处理_Nvow
需求的重新分配;您可以使用fprintf
将单词粘合在一起并计数。
把它们放在一起:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int str_count_in_chars(char *start, char *end, char *chars) {
int count = 0;
for (; start != end; count += !!strchr(chars, *(start++)));
return count;
}
void str_swap_in_chars(size_t str_len, char **str, char *chars) {
for (int front = 0, back = str_len - 1; front < back; front++) {
if (strchr(chars, (*str)[front])) {
for (; !strchr(chars, (*str)[back]); back--);
char tmp = (*str)[front];
(*str)[front] = (*str)[back];
(*str)[back--] = tmp;
}
}
}
char *file_to_str(FILE *fin) {
int buf_len = 64;
char buf[buf_len];
char *str = malloc(buf_len);
str[0] = '\0';
for (int i = 1; fgets(buf, buf_len, fin); i++) {
if (!(str = realloc(str, i * buf_len))) {
fprintf(stderr, "%s:%d realloc failed\n", __FILE__, __LINE__);
exit(1);
}
strcat(str, buf);
}
return str;
}
int main() {
char *vowels = "aeiou";
FILE *fin = fopen("input.dat", "r");
FILE *fout = fopen("output.dat", "w");
if (!fin || !fout) {
fprintf(stderr, "%s:%d fopen failed\n", __FILE__, __LINE__);
exit(1);
}
char *words = file_to_str(fin);
fclose(fin);
int words_len = strlen(words);
for (int i = 0; i < words_len;) {
if (isspace(words[i])) {
fputc(words[i++], fout);
continue;
}
int start = i;
for (; i < words_len && !isspace(words[i]); i++);
char *word = words + start;
int word_len = i - start;
int vowel_count = str_count_in_chars(word, words + i, vowels);
if (vowel_count % 2 == 0) {
str_swap_in_chars(word_len, &word, vowels);
}
fprintf(fout, "%.*s_%dvow", word_len, word, vowel_count);
}
fclose(fout);
free(words);
return 0;
}
执行此操作后,output.dat
包含:
eppla_2vow juice_3vow strewbarry_2vow can_1vow meka_2vow penieppla_4vow
推荐阅读
- web-scraping - 即使在使用 selenium 自动滚动后也无法抓取所有照片
- javascript - 如何访问嵌套对象值
- javascript - How to catch the exception in the right way? [beginner]
- python - how display contexts of two different app and different view in one template in one project in django?
- python-3.x - NameError on a function while calling for it in another function of a class
- java - “java.lang.IllegalStateException:测试上下文的 WebApplicationContext [...] 必须使用 MockServletContext 进行配置。”
- azure - 将 Python API 部署到 Azure 应用服务
- c# - 我有一个将字符分配给 char 数组的 for 循环,错误:System.IndexOutOfRangeException
- aurelia - 通过 HTML 循环在 Aurelia 中每行有一个项目的表格和一些属性
- python - boto3:generate_presigned_url 在上传期间被拒绝访问