在C

时间:2016-02-15 22:34:45

标签: c arrays string char stack

我正在尝试编写一个程序来读取stdin流来查找单词(连续的字母字符),并且每个单词将它左旋转到第一个元音(例如“friend”旋转到“iendfr”)并将此序列写出取代原来的单词。所有其他字符都写入stdout不变。

到目前为止,我已设法扭转这些字母,但却无法做更多的事情。有什么建议吗?

#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

2 个答案:

答案 0 :(得分:2)

我不打算为你编写整个程序,但这个例子展示了如何从第一个元音(如果有的话)旋转一个单词。函数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;
}

节目输出:

iendfr
vwxyz
aeiou

答案 1 :(得分:1)

您可以通过多种方式解决问题。您可以使用堆栈,但这只会增加处理额外的堆栈操作。您可以使用数学重建索引,也可以使用复制和填充解决方案,从第一个元音复制到新字符串,然后只需将初始字符添加到字符串的末尾。

虽然您可以一次读/写一个字符,但通过在缓冲区中创建旋转字符串以允许在代码中使用字符串,可能会更好。无论使用哪种方法,都需要验证所有字符串操作,以防止在输入结束和/或旋转字符串之外进行读/写操作。旋转到输入中第一个元音的复制/填充方法示例如下所示:

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

上面,strpbrk用于返回指向字符串's'中元音的第一个匹配项的指针。该函数将指向足够大小的字符串的指针作为参数,以保存旋转的字符串'rs',输入字符串's'以及'rs''max'的分配大小。对参数进行验证,并检查s是否有strpbrk的元音,该元音返回指向s中的第一个元音的指针(如果存在),否则为NULL。根据{{​​1}}检查长度以确保足够的存储空间。

如果没有元音,则max被复制到s并返回指向rs的指针,否则指针差异用于设置第一个元音的偏移索引,将第一个元音到结尾的字符串段复制到rs,然后使用循环将前面的字符复制到rs的末尾。 <{1}} nul-terminated 并返回指针。

虽然我很少建议使用rs作为输入,但最好使用rs后跟scanffgets),为了简短的例子,可用于从sscanf读取单个字符串。注意:回答大/小写元音留给你。将最大字大小设置为32个字符(31个字符+ nul-terminatedating 字符)的简短示例将适用于未删节字典中的所有已知字词(最长字为28个字符):< / p>

strtok

示例使用/输出

(无耻地从WeatherVane stdin

借用示例字符串
#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;
}

仔细看看,如果您有任何疑问,请告诉我。注意:您可以在:)语句之前调用$ echo "friend vwxyz aeiou" | ./bin/str_rot2vowel friend => iendfr vwxyz => vwxyz aeiou => aeiou 函数并使用rot2vowel打印结果,但由于函数返回指向字符串的指针,因此可以直接在printf声明。你如何使用它取决于你。