【问题标题】:Printing a character n time based on input根据输入打印一个字符 n 次
【发布时间】:2020-11-11 00:50:20
【问题描述】:

我正在编写一个程序,它将根据用户输入打印“*”,用户需要输入一个介于 1 和 30 之间的数字,然后程序将打印 * n 次。其中 n 介于 1 到 30 之间。

例如:用户输入 7,对于 1 到 30 之间的任何 n 值,输出为“*******”。

这是我目前得到的:

int x;
char c = "*";

printf("%s","Please Enter a number between 1 and 30\n");
scanf("%d", &x);

if (x>=1)
{
    printf("%d",x,c);;
}

在 printf 部分寻找一些指导,我如何让它通过 x 打印 *,这是下限,因为 1 是用户可以输入的最低值 30 是上限,但通常我喜欢确保下限在上限之前首先起作用,然后是简单的复制粘贴并更改数字。一个单独的 if 将用于任何超出范围的数字,即小于 1 和大于 30 的任何数字都需要用户重新输入,到目前为止它只打印输入的数字而不是 * 多次。 另外,如果我的代码中有任何其他错误,请随时纠正我仍在学习中。

【问题讨论】:

  • 你想了解循环。
  • 我最初使用的是 while 循环,但我卡在了 printf 部分,我仍然无法让它打印 n 次,这就是我转向 if 语句的原因。
  • if 应该如何重复任何内容?也许你可以使用while 发布你的方法,我们一起找出你在那里做错了什么。因为if 不会重复任何事情。
  • 您希望printf("%d",x,c);; 应该做什么?我想看看你对此的看法。

标签: c loops char printf


【解决方案1】:

一种方法是使用循环并在每次迭代时打印一个*

unsigned int x;

printf("Please Enter a number between 1 and 30\n");
if (scanf("%u", &x) != 1)
{
    // error routine.
}

if (x >= 1 && x <= 30)
{
    while (x--)
    {
        printf("%c", '*');
    }

    puts("");
}
else
{
    printf("Wrong input value!\n");
}

如果你想通过一个printf()调用打印*s的序列,

一种方法是使用 30 个*s 的字符串文字,并且只显示用户输入的*s 的数量。可以使用 .* 修饰符进行打印,该修饰符提供相对于给定参数 x 的值的输出字符串的长度。

unsigned int x;
const char* p = "******************************";

printf("Please Enter a number between 1 and 30\n");
if (scanf("%u", &x) != 1)
{
    // error routine.
}

if (x >= 1 && x <= 30)
{
    printf("%.*s\n", x, p);
}
else
{
    printf("Wrong input value!\n");
}

这里有几点说明:

  • 您需要将if (x &gt;= 1) 更改为if (x &gt;= 1 &amp;&amp; x &lt;= 30),因为它只应该打印130 之间的值,而不仅仅是1 或更高版本。

  • 如果发生错误,请始终检查输入函数的返回,例如 scanf()

  • 我将x 的类型更改为unsigned int,因为很明显它不应该有负值。请注意,您需要将 scanf() 中的格式说明符从 %d 更改为 %u

【讨论】:

  • 在这种情况下,printf-ing 和 "%.*s" 不是矫枉过正吗...? :)
  • @CiaPan 它可能看起来有点奇怪,但它很可能是最有效的版本,它使用字符串文字并在一次调用 printf() 时从中打印一定数量的字符。还是我误解了你的评论? :-)
  • 嗯,有一个简单的技巧,您可以在外部调用printf。我将在几个小时内将其添加到我的答案中;)。提示:“这种情况”指的是与预期输出完全相同的简单性和统一性,它允许您使用长字符串文字。
  • Added。你觉得怎么样?
【解决方案2】:

char 类型对象的这个初始化

char c = "*";

错了。而不是字符串文字 "*" 你必须使用字符文字 '*' like

char c = '*';

printf的这个电话

printf("%s","Please Enter a number between 1 and 30\n");

太复杂了。你可以写

printf("Please Enter a number between 1 and 30\n");

这个printf 的调用带有一个冗余的空语句

printf("%d",x,c);;

有一个未使用的参数并且没有做你认为它应该做的事情。

另外这个if语句

if (x>=1)

不检查x 是否小于或等于30

除此之外,用户可以中断输入。在这种情况下,如果变量x 声明为具有块内的自动存储持续时间,则该变量将具有不确定的值。

尽量不要将幻数用作130。而是使用命名常量。

由于重复输出字符的个数不能为负数,将对应的变量x声明为无符号整数类型。

这是一个演示程序,展示了如何编写代码。

#include <stdio.h>

int main(void) 
{
    const unsigned int MIN_VALUE = 1;
    const unsigned int MAX_VALUE = 30;
    const char c = '*';
    
    printf( "Please Enter a number between %u and %u inclusive: ", 
            MIN_VALUE, MAX_VALUE );
            
    unsigned int n;
    
    if ( scanf( "%u", &n ) == 1 && MIN_VALUE <= n && n <= MAX_VALUE )
    {
        putchar( '\n' );
        
        do
        {
            putchar( c );
        } while ( n-- != MIN_VALUE );
        putchar( '\n' );
    }
    else
    {
        puts( "\nSorry. The input is not valid." );
    }
    
    return 0;
}

程序输出可能看起来像

Please Enter a number between 1 and 30 inclusive: 20

********************

【讨论】:

  • 首先感谢您对字符的更正,我被告知它是“”而不是“”。其次,如果我知道 x 我的情况将在 1 到 30 之间,那么所有其他值将基本上停在 if else 语句的 else 部分,我们为变量分配 max 和 min 的原因是什么?小于 1 和大于 30 的任何内容都会导致 if 语句跳过第一个条件并输出第二个条件结果?
  • 第三 put 和 printf 之间有什么区别,在您的评论中第一次看到它,在把 put 和 printf 弄乱之后对我来说,到目前为止,它们看起来基本上做同样的事情,那里一定是发生了什么我看不到的事情?
  • @JKS printf 需要一个表示字符串的 char * 类型的参数。但是您只需要在循环中输出一个字符。所以用putchar代替printf效率更高。
  • @JKS 正如您在问题中写的那样,有效数字应在 1 到 30 之间。因此您必须检查输入的数字是否属于指定范围。
  • 所以本质上puts只会打印出一个字符串,其中printf可以输出一个字符串和在该字符串中声明的任何变量,或者在我的情况下,如果我使用printf函数我必须分配char在 printf 中,就像您对变量所做的那样,至于 puts 我可以只使用字符 * 而不在 puts 函数中定义它?我理解正确吗?
【解决方案3】:

你只需要替换你的想法'打印一次一组N个字符'
'打印N一个字符'。

那么解决方法就很简单了:

if (x >= 1 && x <= 30)    // test number of chars to print
{
    while (--x >= 0)      // decrement it and see if anything remains
        printf("*");      // print a character and reiterate

    printf("\n");         // terminate the output line
}
else
    printf("The value entered is not between 1 and 30.\n");   // error message

编辑

the answer by @RobertS supports Monica Cellio的基础上,可以特别使用要求输出为重复单个字符的简单字符串,并且输出的大小严格限制在很小的长度。

因此您可以定义一个显式的字符数组,其中包含所需的最长输出字符串:

const char outString[31] = "******************************";

31 的长度足以容纳 30 个星号 '*' 和一个零字符(ASCII NUL 代码),以终止字符串。

当你想输出一个包含 x 星号的字符串时,你可以打印字符串的 tail 部分,从适当的位置开始:

if (x >= 1 && x <= 30)         // test number of chars to print
    puts( outString + 30 - x); // print appropriate part of the string
else
    puts("The value entered is not between 1 and 30.");

这样可以避免printf 格式和循环开销——代价是声明一个常量数组。

【讨论】:

  • 是的,它也是偷偷摸摸的。 :-) - 虽然还没有真正的优势,但如果您使用具有 31 个元素的 char 数组而不是具有 30 个元素的字符串文字。建议:我的版本的一个真正优势是如果您为char 数组动态分配内存并在使用后释放它。 ;-)
  • @RobertSsupportsMonicaCellio 但是需要填充分配的数组。有很多选择:一个可以strcpy 一个静态字符串到它里面(但是原始字符串必须是静态分配的);或者可以用循环填充它(OP显然努力避免);或者可以通过调用calloc('*',31)(内部有一个循环)来假装没有循环,然后最后一个字符必须用零覆盖。
猜你喜欢
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多