[英]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.