Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何逐字计算文件中元音的数量,并将结果附加到单词上?_C_String_File_Concat_Swap - Fatal编程技术网

C 如何逐字计算文件中元音的数量,并将结果附加到单词上?

C 如何逐字计算文件中元音的数量,并将结果附加到单词上?,c,string,file,concat,swap,C,String,File,Concat,Swap,我试图用C编写一个代码,从文件中读取n单词,并逐字修改内容 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++)

我试图用C编写一个代码,从文件中读取n单词,并逐字修改内容

     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;
          }
     }

该程序将计算每个单词中的元音数。如果当前单词中的元音数为偶数,程序将两个元音成对交换(奇数情况下不交换),然后将元音数附加到单词上

     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
,则修改后的单词看起来像
eppla\u 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

我会重新调整计划,让事情变得更简单。这里有一个提纲:

  • 获取输入文件大小,例如
    stat()
  • 分配大小+1字节,并在末尾放置空字节
  • 将文件读入分配的缓冲区
  • 定义一个小的缓冲区,该缓冲区有足够的空间容纳一个字+xxWaw字节
  • 使用
    strtok()
  • strtok()
    返回地址复制到小型本地缓冲区
  • 修改小缓冲区中的字节(复制期间或之后),并输出修改后的字

额外:您可以为所有字符创建一个字节数组,将所有字符初始化为零,然后用替换字母填充元音位置,而不是对元音字符进行大量测试;当任何索引字节非零时,用新的元音替换元音并增加元音计数。此方法通过索引一个数组而不是多个数组(测试+分支)来提高效率。

这可以分解为几个子任务:

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

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

除此之外,其他一切都是样板——在空格和IO上分块字符串。将结果写回文件而不是字符串,可以更容易地处理
\u 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;
}

无需获取文件大小,只需对最大字长做一个合理的假设,例如80字节。也不需要分配。为什么在这里读取
n
for(i=0;iI可以使用
str\u swap\u in\u chars
来交换辅音,对吗?当然,只需将第三个参数更改为一个辅音字符串。另外,我在哪里可以实现“从文件读取n个字”语句?只需在主循环中添加一个计数器。每次
fprintf(fout,“%.*s\u%dvow”,单词、单词、元音\u计数)执行;
,即向文件写入一个字。如果文件很大,而您只想获取第一个块,最好将块逻辑移到文件读取函数中,并从那里开始,这样您就不会为了几个字而将整个内容拖到内存中。好吧,我必须做一些在我的代码中,读取发生在父进程中,然后将n个字发送给子进程,子进程执行修改。