首页 > 解决方案 > 如何逐字计算文件中的元音数量并将结果附加到单词中?

问题描述

我正在尝试用 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

标签: cstringfileconcatswap

解决方案


这可以分为几个子任务:

首先,我们需要一个函数来计算字符串中元音的数量。这很简单。我们可以将其概括为计算一个字符串中任何字符在另一个字符串中出现的次数,而不会遇到任何麻烦。

其次,我们需要一个交换字符串中元音的函数。两分球技术似乎是解决这个问题的方法。当前指针和后指针没有相遇时,向前迭代前指针,直到它落在一个元音上。此时,递减反向指针,直到它碰到一个元音并交换它们。继续这样交换,直到指针交叉。如上所述,很容易将字符列表传递到字符串中。

除此之外,其他一切都是样板文件——在空格和 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

推荐阅读