xcode 如何使它接受用户输入的大小写形式,并使它更安全

xdnvmnnf  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(155)

这保持打印包含类似信件的所有SMS。
我需要运行代码而不考虑大小写
每次用户输入和短信,代码打印所有短信有关的信,例如,如果另一个短信有一个'a',它打印,加上原来的短信。

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

char *
replaceWord(const char *string, const char *oldWord, const char *newWord)
{
    char *result;
    int i, cnt = 0;
    int newWordlen = strlen(newWord);
    int oldWordlen = strlen(oldWord);

    for (i = 0; string[i] != '\0'; i++) {
        if (strstr(&string[i], oldWord) == &string[i]) {
            cnt++;

            // Jumping to index after the old word.
            i += oldWordlen - 1;
        }
    }

    // Making new string of enough length
    result = (char *) malloc(i + cnt * (newWordlen - oldWordlen) + 1);

    i = 0;
    while (*string) {
        // compare the substring with the result
        if (strstr(string, oldWord) == string) {
            strcpy(&result[i], newWord);
            i += newWordlen;
            string += oldWordlen;
        }
        else
            result[i++] = *string++;
    }

    result[i] = '\0';
    return result;
}

char *
getMessage(char sms[25][5], char message[25][25], char *input)
{
    int i = 0;

    for (i = 0; i < 25; i++) {
        if (strstr(input, sms[i]) != NULL) {
            char *result = replaceWord(input, sms[i], message[i]);

            input = result;
        }
    }
    return input;
}

char *
getSMS(char sms[25][5], char message[25][25], char *input)
{
    int i = 0;

    for (i = 0; i < 30; i++) {
        if (strstr(input, message[i]) != NULL) {
            char *result = replaceWord(input, message[i], sms[i]);

            input = result;
        }
    }
    return input;
}

int
main(void)
{
    char sms[25][5] = { "R", "OMG", "L8", "2DAY", "U", "2", "PLS", "PPL",
        "GAS", "FTL", "GG", "WYA", "ETA", "WYD", "HBU", "WTM", "WYM", "LOL",
        "L", "W", "TTYL", "SYL", "ILY", "BRB", "NRN" };
    char message[25][25] = { "ARE", "OH MY GOD", "LATE", "TODAY", "YOU",
        "TO", "PLEASE", "PEOPLE", "GREETINGS AND SALUTATIONS", "FOR THE LOSS",
        "GOOD GAME", "WHERE YOU AT", "ESTAMATED TIME ARIVAL", "WHAT YOU DOING",
        "HOW ABOUT YOU", "WHATS THE MOVE", "WHAT YOU MEAN", "LAUGH OUT LOUD",
        "LOST", "WON", "TALK TO YOU LATER", "SEE YOU LATER", "I LOVE YOU",
        "BE RIGHT BACK", "NOT RIGHT NOW" };
    // int i=0;
    int choice = 1;
    char input[100];

    while (choice != 3) {
        printf("Please choose :\n"
            "1: SMS to Message.\n"
            "2: Message to SMS.\n"
            "3:Exit\n");
        scanf("%d", &choice);
        fflush(stdin);

        if (choice == 1) {
            printf("Please give SMS :");
            scanf("%[^\n]", input);
            strcpy(input, getMessage(sms, message, input));
            printf("Converting SMS to Message :%s\n", input);
        }
        else if (choice == 2) {
            printf("Converting Message to SMS :\n");
            scanf("\n%[^\n]", input);
            strcpy(input, getSMS(sms, message, input));
            printf("%s\n", input);
        }
        else if (choice == 3) {
            printf("Program Ended.\n");
        }
        else {
            printf("Invalid Choice.\n");
        }
    }
    getchar();
}

输出如下:

Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
1
Please give SMS :OMG
Converting SMS to Message :OH MY GOD
Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
1
Please give SMS :WYM
Converting SMS to Message :WONHAT YOU MEAN
Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
1
Please give SMS :LOL
Converting SMS to Message :LOSTAUGH OUT LOSTOUD
Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
s6fujrry

s6fujrry1#

几个问题...

  1. fflush(stdin)是UB [如顶部评论中所述]。
  2. smsmessage是“并行”数组。也就是说,它们的索引方式相同。可以通过使用单个struct数组来简化它们。
  3. replaceWord为每个单词/短语替换复制 * 整个 * 字符串。
    1.直接调用replaceWord会在每次迭代时泄漏内存。
  4. main中的strcpy代码泄漏由getMessagegetSMS分配和返回的内存。
    1.使用strstr必须大量重新扫描原始字符串。
    1.更容易/更好的方法是复制原始字符串,然后逐个字符、逐个短语地处理。不需要用临时副本来malloc结果字符串。而且,不需要replaceWord [及其复杂性]。
    1.大写/小写可以由strcase*函数处理(例如,用strcasecmp代替strcmp)。
    下面是修改后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <termios.h>

// SMS/Message conversion
#if 1
struct sms {
    const char *sms;                        // SMS short string
    const char *message;                    // message long string
    int slen;                               // sms string length
    int mlen;                               // message string length
};
#endif

#if 1
struct sms smslist[] = {
    { "R", "ARE" },
    { "OMG", "OH MY GOD" },
    { "L8", "LATE" },
    { "2DAY", "TODAY" },
    { "U", "YOU" },
    { "2", "TO" },
    { "PLS", "PLEASE" },
    { "PPL", "PEOPLE" },
    { "GAS", "GREETINGS AND SALUTATIONS" },
    { "FTL", "FOR THE LOSS" },
    { "GG", "GOOD GAME" },
    { "WYA", "WHERE YOU AT" },
    { "ETA", "ESTAMATED TIME ARIVAL" },
    { "WYD", "WHAT YOU DOING" },
    { "HBU", "HOW ABOUT YOU" },
    { "WTM", "WHATS THE MOVE" },
    { "WYM", "WHAT YOU MEAN" },
    { "LOL", "LAUGH OUT LOUD" },
    { "L", "LOST" },
    { "W", "WON" },
    { "TTYL", "TALK TO YOU LATER" },
    { "SYL", "SEE YOU LATER" },
    { "ILY", "I LOVE YOU" },
    { "BRB", "BE RIGHT BACK" },
    { "NRN", "NOT RIGHT NOW" },

    // end of list
    { NULL, NULL }
};
#endif

int
haseos(const char *eos)
{
    int match;

    switch (*eos) {
    case 0:
        // fall through
    case ' ':
        match = 1;
        break;

    default:
        match = 0;
        break;
    }

    return match;
}

void
getMessage(const struct sms *arr, char *out)
{
    char buf[1000];

    // copy the argument buffer
    char *inp = buf;
    strcpy(inp,out);

    *out = 0;

    while (*inp != 0) {
        int match = 0;

        // try for match on any/all SMS strings
        for (const struct sms *cur = arr;  cur->sms != NULL;  ++cur) {
            if (strncasecmp(inp,cur->sms,cur->slen) != 0)
                continue;

            // ensure the string has a delimiter after it
            match = haseos(inp + cur->slen);

            // copy over replacement string and advance input/output pointers
            if (match) {
                strcpy(out,cur->message);
                out += cur->mlen;
                inp += cur->slen;
                break;
            }
        }

        // ordinary char
        if (! match)
            *out++ = *inp++;
    }

    // add final EOS terminator
    *out = 0;
}

void
getSMS(const struct sms *arr, char *out)
{
    char buf[1000];

    // copy the argument buffer
    char *inp = buf;
    strcpy(inp,out);

    *out = 0;

    while (*inp != 0) {
        int match = 0;

        // try for match on any/all message strings
        for (const struct sms *cur = arr;  cur->sms != NULL;  ++cur) {
            if (strncasecmp(inp,cur->message,cur->mlen) != 0)
                continue;

            // ensure the string has a delimiter after it
            match = haseos(inp + cur->mlen);

            // copy over replacement string and advance input/output pointers
            if (match) {
                strcpy(out,cur->message);
                out += cur->slen;
                inp += cur->mlen;
                break;
            }
        }

        // ordinary char
        if (! match)
            *out++ = *inp++;
    }

    // add final EOS terminator
    *out = 0;
}

FILE *fin;

#define ASKSTR(_prompt,_str) \
    askstr(_prompt,_str,sizeof(_str))

void
askstr(const char *prompt,char *buf,size_t buflen)
{

    static int fileflg = -1;
    if (fileflg < 0) {
        struct termios tio;
        fileflg = tcgetattr(fileno(fin),&tio) < 0;
    }

    printf("%s",prompt);
    if (prompt[strlen(prompt) - 1] != '\n')
        printf(": ");
    fflush(stdout);

    if (fgets(buf,buflen,fin) == NULL)
        exit(7);

    if (fileflg)
        fputs(buf,stdout);

    // strip newline
    buf[strcspn(buf,"\n")] = 0;
}

int
asknum(const char *prompt)
{
    char *cp;
    char buf[100];
    int ret = -1;

    ASKSTR(prompt,buf);

    do {
        errno = 0;
        int num = strtol(buf,&cp,10);

        if (errno)
            break;

        if (*cp == 0)
            ret = num;
    } while (0);

    return ret;
}

int
main(int argc,char **argv)
{
#if 0
    const char **sms = { "R", "OMG", "L8", "2DAY", "U", "2", "PLS", "PPL",
        "GAS", "FTL", "GG", "WYA", "ETA", "WYD", "HBU", "WTM", "WYM", "LOL",
        "L", "W", "TTYL", "SYL", "ILY", "BRB", "NRN", NULL };
    const char **message = { "ARE", "OH MY GOD", "LATE", "TODAY", "YOU",
        "TO", "PLEASE", "PEOPLE", "GREETINGS AND SALUTATIONS", "FOR THE LOSS",
        "GOOD GAME", "WHERE YOU AT", "ESTAMATED TIME ARIVAL", "WHAT YOU DOING",
        "HOW ABOUT YOU", "WHATS THE MOVE", "WHAT YOU MEAN", "LAUGH OUT LOUD",
        "LOST", "WON", "TALK TO YOU LATER", "SEE YOU LATER", "I LOVE YOU",
        "BE RIGHT BACK", "NOT RIGHT NOW", NULL };
#endif

    // for debug input:
#if 1
    if (argc == 2)
        fin = fopen(argv[1],"r");
    else
        fin = stdin;
    if (fin == NULL) {
        perror(argv[1]);
        exit(1);
    }
#endif

    // for speed, compute string lengths
#if 1
    for (struct sms *cur = smslist;  cur->sms != NULL;  ++cur) {
        cur->slen = strlen(cur->sms);
        cur->mlen = strlen(cur->message);
    }
#endif

    // int i=0;
    int choice = 1;
    char input[1000];

    while (choice != 3) {
#if 0
        printf("Please choose :\n"
            "1: SMS to Message.\n"
            "2: Message to SMS.\n"
            "3:Exit\n");
        scanf("%d", &choice);
        fflush(stdin);
#else
        choice = asknum("Please choose :\n"
            "1: SMS to Message.\n"
            "2: Message to SMS.\n"
            "3:Exit\n");
#endif

        switch (choice) {
        case 1:
            ASKSTR("Please give SMS",input);
#if 0
            strcpy(input, getMessage(sms, message, input));
#else
            getMessage(smslist, input);
#endif
            printf("Converting SMS to Message :%s\n", input);
            break;

        case 2:
            ASKSTR("Converting Message to SMS",input);
#if 0
            strcpy(input, getSMS(sms, message, input));
#else
            getSMS(smslist, input);
#endif
            printf("%s\n", input);
            break;

        case 3:
            printf("Program Ended.\n");
            break;

        default:
            printf("Invalid Choice.\n");
            break;
        }
    }

    fclose(fin);
}

在上面的代码中,我使用了cpp条件语句来表示旧代码和新代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

注意:通过unifdef -k运行文件可以清除此问题
下面是我用来测试的示例输入(根据您的示例):

1
OMG
1
WYM
1
LOL
3

下面是程序输出:

Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
1
Please give SMS: OMG
Converting SMS to Message :OH MY GOD
Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
1
Please give SMS: WYM
Converting SMS to Message :WHAT YOU MEAN
Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
1
Please give SMS: LOL
Converting SMS to Message :LAUGH OUT LOUD
Please choose :
1: SMS to Message.
2: Message to SMS.
3:Exit
3
Program Ended.

相关问题