繁体   English   中英

如何处理CS50的首字母缩写词之前或之间的多个空格(更舒适)?

[英]How do I deal with multiple spaces before or in between the words in CS50's initials (more comfortable)?

问题: http : //docs.cs50.net/problems/initials/more/initials.html正如我在标题中所说,如果用户输入多余的空格,我似乎无法使程序输出没有空格的缩写名称之前,或在名字和姓氏之间输入多余的空格。

现在,仅当我输入我的名字时它才起作用:First Last名称前没有空格,两个单词之间只有一个空格。 它将打印出FL,而没有任何其他空格。 无论我在名字和姓氏之前或之间有多少多余的空格,我都希望这样做。

我当前的代码:

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

int main(void) {
    printf("Name: ");
    string s = get_string();

    printf("%c", toupper(s[0]));

    for (int i = 0; i < strlen(s); i++) {
        if (s[i] == ' ') {
            printf("%c", toupper(s[i +1]));
        }
}

    printf("\n");
}

尽管您已经有了一个很好的答案,但是假设string s = get_string(); cs50.h世界中, s只填充了一个以n终止的字符串,并且s字符数组指向已分配内存的指针 ,您可以在几个方面进行改进。

首先,不要使用printf打印单个字符。 这就是putchar (或fputc )的用途。 (授予智能优化编译器应为您执行此操作,但不要依靠编译器为您解决效率低下的问题)

printf("%c", toupper(s[0]));

只是

putchar (toupper(s[0]));

另外,您可能需要考虑一些逻辑问题。 您想知道的是(1)“ 当前字符是字母吗? ”(例如isalpha (s[x]) ,(2)” 这是第一个字符(例如index 0 ),还是紧随其后的字符一个空格? ”(例如s[x-1] == ' ' )。使用than信息,您可以使用单个putchar输出缩写。

此外,以s为字符串,您可以简单地使用指针算术 (例如, while (*s) {.. do stuff with *s ..; s++;} )在到达nul-terminator时结束 ,或者如果需要保留s作为指向第一个字符的指针,或者如果它是一个数组 ,则char *p = s; 并在p操作

将这些部分放在一起,您可以不依赖string.h进行以下操作(您也可以使用if和s以及第6位的简单操作来消除对ctype.h函数的依赖-稍后再介绍):

#include <stdio.h>
#include <cs50.h>
#include <ctype.h>

int main (void) {

    char *p = NULL;

    printf ("Name: ");
    string s = get_string();    /* assuming this works as it appears */

    for (p = s; *p; p++)
        /* if current is [a-zA-Z] and (first or follows space) */
        if (isalpha (*p) && (p == s || (*(p - 1) == ' ')))
            putchar (toupper (*p));

    putchar ('\n');    /* tidy up */

    return 0;
}

使用/输出示例

$ ./bin/initials
Name: David C. Rankin
DCR

$ ./bin/initials
Name: Jane Doe
JD

$ ./bin/initials
Name: d
D

$ ./bin/initials
Name:    George     W...    Bush
GWB

不要在for循环的条件下使用strlen ,它会在每个步骤中执行,最好将值保存在变量中,而在条件中使用变量。

在这种情况下,我将使用strtok ,它处理诸如Tom marvolo riddle类的输入,其中名称之间有多个空格。

#include <stdio.h>
#include <ctype.h>


int main(void)
{

    char line[1024];

    fgets(line, sizeof line, stdin);

    char *token, *src = line;

    while(token = strtok(src, " \t"))
    {
        src = NULL; // subsequent calls of strtok must be called
                    // with NULL

        printf("%c", toupper(*token));
    }

    printf("\n");

    return 0;
}

使用strtok ,必须记住不要传递字符串文字( "this is a string literal" ),因为它们是只读的,并且strtok在找到分隔符的位置写入\\0 如果您不知道是否具有对缓冲区的写访问权,则必须制作一个副本(在具有足够长度的静态缓冲区中,或使用malloc ),然后在strtok使用该副本。

在我的示例中,我知道line不是只读变量,因此可以安全地在strtok使用(前提是我将不再使用它,否则需要一个副本)。

strtok一个问题是它不是可重入的,最好使用strtok_r

char *token, *src = line, *saveptr;

while(token = strtok_r(src, " \t", &saveptr))
    ...

为了使您的代码正常工作,一种简单的方法是添加一个标志,告知前一个字符是否为空格。 就像是:

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

int main(void) 
{
    int wasSpace = 1;   // Add a flag.
    printf("Name: ");
    string s = get_string();

    for (int i = 0; i < strlen(s); i++) 
    {
        if (wasSpace && s[i] != ' ')  // Only print if previous was a space and this isn't
        {
            wasSpace = 0;
            printf("%c", toupper(s[i]));
        }
        else if (s[i] == ' ')
        {
            wasSpace = 1;    // Update the flag
        }
    }
    printf("\n");
    return 0;
}

暂无
暂无

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

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