如何从文件中逐字计算元音数,并将结果附在单词上?

问题描述 投票:1回答:1

我想用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
c string file concat swap
1个回答
1
投票

这可以分解成几个子任务。

首先,我们需要一个函数来计算一个字符串中元音的数量。这是非常直接的。我们可以把它泛化为计算一个字符串中的任何字符在另一个字符串中的出现次数,而不会有任何麻烦。

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

除此之外,其他的都是锅炉式的--在空格和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

1
投票

我会调整程序,让事情变得更简单。下面是一个大纲。

  • 获取输入的文件大小,例如 stat()
  • 分配size+1字节,并在最后放置一个空字节
  • 将文件读入分配的缓冲区
  • 定义一个小的缓冲区,有足够的空间来容纳一个字+。_XXvow 字节数
  • 在循环中扫描分配的缓冲区,用 strtok()
  • 抄袭 strtok() 返回地址到本地小缓冲区
  • 修改小缓冲区中的字节(在复制过程中或之后),并输出修改后的字。

额外的:你可以为所有的元音字符创建一个字节数组,而不是许多测试的集合,将所有东西初始化为零,然后用替换字母填充元音位置;当任何索引的字节是非零时,用新的元音替换元音,并递增一个元音数。 这种方法通过索引一个数组而不是许多数组(测试+分支)来提高效率。

© www.soinside.com 2019 - 2024. All rights reserved.