【问题标题】:Capitalization of first letter of string in c - Code a myprintf function in under 110 charactersc 中字符串首字母的大写 - 用 110 个字符编写 myprintf 函数
【发布时间】:2019-04-05 10:15:49
【问题描述】:

我需要创建一个my_printf 函数,它接受一个字符串,仅将字符串的第一个字母大写(即使之前有空格),然后执行一个 \n,全部在 110 个字符以下(空格/制表符不是包括)。

我只能修改cmets“TO BE DONE START”和“TO BE DONE END”之间的函数。

这是我到目前为止编写的代码:我唯一遇到的问题是在输出中它没有大写 \t 之后的“looks OK :)”的字母“l”,我有不知道如何在不超过此代码中 110 个字符的最大限制的情况下实现不在字符串位置 q[0] 中的字符的大写;我知道它需要一个循环,但我似乎总是超出限制。

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

void my_printf(char*p){
    char s[strlen(p)+1], *q=s;
    strcpy(s,p);

    /* TO BE DONE START */
    q[0]=toupper(q[0]);
    putchar(q[0]);
    for(*q=1;*q!='\0';++q) {
         putchar(*q);
    }
    putchar('\n');

    /* TO BE DONE END */
}

int main(){
    my_printf("hello world!");
    my_printf("How are you?");
    my_printf("i\'m OK, and you?");
    my_printf("1, 2, 3, testing ...");
    my_printf("\t  looks OK :-)");
    my_printf("bye bye!");
    return 0;
}

我需要帮助以使这段代码尽可能短,这是所需的输出:

 Hello world!
 How are you?
 I'm OK, and you?
 1, 2, 3, testing …
            Looks OK :-)
 Bye bye!

而我的是:

 Hello world!
 How are you?
 I'm OK, and you?
 1, 2, 3, testing …
            looks OK :-)
 Bye bye!

【问题讨论】:

  • while(isspace(*q))putchar(*q++); putchar(toupper(*q++);while(*q)putchar(*q++); 应该可以工作。
  • @PaulOgilvie: char 参数应转换为 (unsigned char) 并且需要尾随换行符。
  • @chqrlie 只要输入真的是一个字符串,就没有必要这样做。否则,施法也无济于事。
  • @JensGustedt:如果输入是一个 8 位字符的字符串并且 char 类型是有符号的,那么 isspace(*q)toupper(*q) 都会有未定义的行为。转换参数解决了这个问题:isspace((unsigned char)*q)toupper((unsigned char)*q)。参见7.4 字符处理 头文件声明了几个对字符分类和映射有用的函数。在所有情况下,参数都是一个 int,其值应表示为无符号字符或应等于宏 EOF 的值。如果参数有任何其他值,则行为未定义
  • @PaulOgilvie: 不,将char 转换为unsigned char 不会首先将char 扩展为int,它只是将可能的负值转换为范围内的值0..UCHAR_MAX(在 2 的补码架构上具有相同的位表示),然后在传递给 isspacetoupper 时将提升为 int。非常重要的是不要将负值(EOF 除外)传递给这些函数,因为它们可能会将其参数用作包含 257 个条目的表的索引。大多数负值会导致数组外的引用或不正确的索引值。

标签: c capitalization


【解决方案1】:

您可以使用 isspace 函数 - 类似于:

/* TO BE DONE START */
while (isspace(*q)) putchar(*q++);
for(*q = toupper(*q); *q; ) putchar(*q++);
putchar('\n');
/* TO BE DONE END */

【讨论】:

  • isspacetoupper 的参数应转换为 (unsigned char) 以避免在负 char 值上出现未定义的行为。
【解决方案2】:

请注意,isspace()tolower()char 参数 必须 转换为 unsigned char 以避免在带有签名 char 类型的平台上对负 char 值的未定义行为.您的代码和所有其他解决方案都有这个问题。

这里是一个不修改数组的短句(98个字符):

/* TO BE DONE START */
while (isspace((unsigned char)*q)) putchar(*q++);
if (*q) putchar(toupper((unsigned char)*q++));
puts(q);
/* TO BE DONE END */

一个更短的修改s(75 个字符):

/* TO BE DONE START */
while (isspace((unsigned char)*q)) q++;
*q = toupper((unsigned char)*q));
puts(s);
/* TO BE DONE END */

【讨论】:

    【解决方案3】:

    这让我觉得很脏:

    /* TO BE DONE START */
    int f = 1;
    while (*q) {
      if (f && !isspace(*q))
        *q = toupper(*q), f=0;
      putchar(*q++);
    }
    putchar('\n');
    /* TO BE DONE END */
    

    84 个非空白字符。

    注意使用逗号操作符以避免{},保存一个字符。

    (假设char 是无符号的,或者如果有符号,则它所采用的字符串中永远不会有负值。)

    【讨论】:

    • isspacetoupper 的参数应转换为 (unsigned char) 以避免在负 char 值上出现未定义的行为。
    • @chqrlie 因此我在底部的注释。
    • 注释没问题,但这个假设值得评论。使用, 肯定看起来很糟糕...但是您可以使用if (f * !isspace(*q)) 节省一个额外的字节
    • @chqrlie 这是代码高尔夫。 当然它看起来很糟糕。如果 OP 没有说空格不计入字符限制,那看起来会更糟。
    猜你喜欢
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 2011-01-20
    • 2014-06-19
    • 2020-01-04
    • 2016-02-15
    • 2023-04-09
    • 2018-12-29
    相关资源
    最近更新 更多