简体   繁体   English

在C中绕元音旋转单词

[英]Rotate words around vowels in C

I am trying to write a program that reads the stdin stream looking for words (consecutive alphabetic characters) and for each word rotates it left to the first vowel (eg "friend" rotates to "iendfr") and writes this sequence out in place of the original word. 我正在尝试编写一个程序,该程序读取stdin流以查找单词(连续的字母字符),然后将每个单词向左旋转到第一个元音(例如,“ friend”旋转为“ iendfr”),并以此顺序代替原来的词。 All other characters are written to stdout unchanged. 所有其他字符均不变地写入stdout。

So far, I have managed to reverse the letters, but have been unable to do much more. 到目前为止,我设法扭转了这些字母,但无法做更多的事情。 Any suggestions? 有什么建议么?

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_STK_SIZE 256

char stk[MAX_STK_SIZE];
int tos = 0; // next available place to put char

void push(int c) {
    if (tos >= MAX_STK_SIZE) return;
    stk[tos++] = c;
}

void putStk() {
    while (tos >= 0) {
        putchar(stk[--tos]);
    }
}

int main (int charc, char * argv[]) {
    int c;
    do {
        c = getchar();
        if (isalpha(c) && (c == 'a' || c == 'A' || c == 'e' || c ==         'E' || c == 'i' || c == 'o' || c == 'O' || c == 'u' || c == 'U')) {
            push(c);
        } else if (isalpha(c)) {
            push(c);
        } else {
            putStk();
            putchar(c);
        }
    } while (c != EOF);
}

-Soul -灵魂

I am not going to write the whole program for you, but this example shows how to rotate a word from the first vowel (if any). 我不会为您编写整个程序,但是此示例显示了如何从第一个元音(如果有)旋转一个单词。 The function strcspn returns the index of the first character matching any in the set passed, or the length of the string if no matches are found. 函数strcspn返回与所传递的集合中的任何字符匹配的第一个字符的索引,如果找不到匹配项,则返回字符串的长度。

#include <stdio.h>
#include <string.h>

void vowelword(const char *word)
{
    size_t len = strlen(word);
    size_t index = strcspn(word, "aeiou");
    size_t i;
    for(i = 0; i < len; i++) {
        printf("%c", word[(index + i) % len]);
    }
    printf("\n");
}

int main(void)
{
    vowelword("friend");
    vowelword("vwxyz");
    vowelword("aeiou");
    return 0;
}

Program output: 程序输出:

iendfr
vwxyz
aeiou

There are a number of ways your can approach the problem. 您可以采用多种方法来解决问题。 You can use a stack, but that just adds handling the additional stack operations. 您可以使用堆栈,但这只是增加了对其他堆栈操作的处理。 You can use a mathematical reindexing, or you can use a copy and fill solution where you copy from the first vowel to a new string and then simply add the initial characters to the end of the string. 您可以使用数学上的重新索引编制,也可以使用复制和填充解决方案,从第一个元音复制到新字符串,然后将初始字符添加到字符串的末尾。

While you can read/write a character at a time, you are probably better served by creating the rotated string in a buffer to allow use of the string within your code. 虽然您一次可以读取/写入一个字符,但最好通过在缓冲区中创建旋转的字符串以允许在代码中使用该字符串来更好地为您服务。 Regardless which method you use, you need to validate all string operations to prevent reading/writing beyond the end of your input and/or rotated strings. 无论使用哪种方法,都需要验证所有字符串操作,以防止在输入和/或旋转的字符串末尾进行读/写操作。 An example of a copy/fill approach to rotating to the first vowel in your input could be something like the following: 复制/填充方法以旋转到输入中的第一个元音的示例可能类似于以下内容:

/* rotate 's' from first vowel with results to 'rs'. 
 * if 's' contains a vowel, 'rs' contains the rotated string, 
 * otherwise, 'rs' contais 's'. a pointer to 'rs' is returned
 * on success, NULL otherwise and 'rs' is an empty-string.
 */
char *rot2vowel (char *rs, const char *s, size_t max)
{
    if (!rs || !s || !max)  /* validate params */
        return NULL;

    char *p = strpbrk (s, "aeiou");
    size_t i, idx, len = strlen (s);

    if (len > max - 1) {    /* validate length */
        fprintf (stderr, "error: insuffieient storage (len > max - 1).\n");
        return NULL;
    }

    if (!p) {   /* if no vowel, copy s to rs, return rs */
        strcpy (rs, s);
        return rs;
    }

    idx = p - s;        /* set index offset    */
    strcpy (rs, p);     /* copy from 1st vowel */

    for (i = 0; i < idx; i++)   /* rotate beginning to end */
        rs[i+len-idx] = s[i];

    rs[len] = 0;        /* nul-terminate */

    return rs;
}

Above, strpbrk is used to return a pointer to the first occurrence of a vowel in string 's' . 上面, strpbrk用于返回指向字符串's'元音的第一个出现的指针。 The function takes as parameters a pointer to a adequately sized string to hold the rotated string 'rs' , the input string 's' and the allocated size of 'rs' in 'max' . 该函数将指向足够大小的字符串的指针作为参数,以容纳旋转后的字符串'rs' ,输入字符串's''rs'的已分配大小'max' The parameters are validated and s is checked for a vowel with strpbrk which returns a pointer to the first vowel in s (if it exists), NULL otherwise. 验证参数并检查s是否具有strpbrk的元音,该元音返回指向s第一个元音的指针(如果存在),否则返回NULL The length is checked against max to insure adequate storage. 对照max长度检查长度,以确保有足够的存储空间。

If no vowels are present, s is copied to rs and a pointer to rs returned, otherwise the pointer difference is used to set the offset index to the first vowel, the segment of the string from the first vowel-to-end is copied to rs and then the preceding characters are copied to the end of rs with the loop. 如果不存在元音,则将s复制到rs并返回指向rs的指针,否则使用指针差将第一个元音的偏移量索引设置为从第一个元音到末尾的字符串段rs ,然后使用循环将前面的字符复制到rs的末尾。 rs is nul-terminated and a pointer is returned. rsnul终止,并返回一个指针。

While I rarely recommend the use of scanf for input, (a fgets followed by sscanf or strtok is preferable), for purposes of a short example, it can be used to read individual strings from stdin . 虽然我很少建议使用scanf作为输入((最好在fgets后面加上sscanfstrtok ),但出于简短示例的目的,它可以用于从stdin读取单个字符串。 Note: responding to upper/lower case vowels is left to you. 注意:对大/小写元音的响应留给您。 A short example setting the max word size to 32-chars (31-chars + the nul-terminating char) will work for all known words in the unabridged dictionary (longest word is 28-chars): 一个简短的示例将最大单词大小设置为32个字符(31个字符+零终止字符)将适用于未删节词典中的所有已知单词(最长单词为28个字符):

#include <stdio.h>
#include <string.h>

enum { BUFSZ = 32 };

char *rot2vowel (char *rs, const char *s, size_t max);

int main (void)
{
    char str[BUFSZ] = {0};
    char rstr[BUFSZ] = {0};

    while (scanf ("%s", str) == 1)
        printf (" %-8s => %s\n", str, rot2vowel (rstr, str, sizeof rstr));

    return 0;
}

Example Use/Output 使用/输出示例

(shamelessly borrowing the example strings from WeatherVane :) (无耻地从WeatherVane借用示例字符串:)

$ echo "friend vwxyz aeiou" | ./bin/str_rot2vowel
 friend   => iendfr
 vwxyz    => vwxyz
 aeiou    => aeiou

Look it over and let me know if you have any questions. 仔细看一下,如果您有任何问题,请告诉我。 Note: you can call the rot2vowel function prior to the printf statement and print the results with rstr , but since the function returns a pointer to the string, it can be used directly in the printf statement. 注意:您可以在printf语句之前调用rot2vowel函数,并使用rstr打印结果,但是由于该函数返回指向字符串的指针,因此可以直接在printf语句中使用它。 How you use it is up to you. 如何使用取决于您自己。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM