【问题标题】:How to add characters to reach the maximum size of a char[]如何添加字符以达到 char[] 的最大大小
【发布时间】:2010-12-21 16:27:44
【问题描述】:

我有以下部分代码:

for(int i=0;i<n;i++)
{
    printf("Student %d\n",i+1);
    printf("Enter name : ");
    scanf("%s",&(student+i)->name);
    fflush(stdin);

    lengthName = strlen((student+i)->name);
    while(lengthName !='\0')
    {

    }} 

当长度小于 10 时,它会添加连字符,直到达到最大长度。 例如:John =>> 将添加 6 个连字符

我知道如何在 csharp 中做到这一点,但在 c 中无法弄清楚。 请你们中的一些人给我一些灯好吗?

PS:哦,是的,变量名是 char name[10+1],它是结构的一部分,称为 student。

【问题讨论】:

  • 当您打印出学生姓名时,您是否希望出现- 字符?
  • @Matt:不,我不想要 strcat()。 @birryree:是的,我希望这些角色出现。

标签: c char


【解决方案1】:

这太简单了,我好像错过了什么。

lengthName = strlen(student[i].name);
while (lengthName < 10)
  student[i].name[lengthName++] = '-';
student[i].name[lengthName] = '\0';

也许您对 C#(假定)拥有一流的字符串类型感到困惑? C 中没有这样的东西,只有裸字符数组;这既乏味(你必须自己做所有的内存管理)又解放(如你所见)。

【讨论】:

    【解决方案2】:
    while(lengthName < 10)  
    {  
        student[i]->name[lengthName++] = '-'; // add this line  
    }  
    student[i]->name[lengthName] = 0;  // and this line 
    

    【讨论】:

    • 最后一行没看懂。为什么会影响 0 到 name[lengthName] ?不应该是'\0'吗?
    • C 中的字符常量被视为数字,因此0'\0' 是写相同数字的两种不同方式。
    【解决方案3】:

    这个怎么样?

    // Pre-fills with hyphens.
    memset(student[i].name, '-', sizeof(student[i].name) - 1);
    scanf("%10s", student[i].name);
    

    【讨论】:

    • fgets 更好,但会输出 '\n''\0' 字节。您可以在fgets 之后的剩余部分上执行memset 来解决此问题。
    • 可维护性? (如果 student[i].name 的大小发生变化怎么办?)
    • fflush 未在输入流上定义;你不能这样清除输入缓冲区。
    【解决方案4】:

    @kotlinski 想法的修改版:

    #define NAME_SIZE 10
    
    fgets(student[i].name, NAME_SIZE, stdin);
    lengthName = strlen(student[i].name);
    if (lengthName > 0 && student[i].name[lengthName-1] == '\n') {
        --lengthName;
    }
    if (lengthName < NAME_SIZE) {
        memset(student[i].name + lengthName, '-', NAME_SIZE - lengthName);
        student[i].name[NAME_SIZE] = '\0';
    }
    

    【讨论】:

      【解决方案5】:

      您的 char name[10 + 1]; 变量显然是 11 个字节长。添加超过 11 个字节的内容会导致缓冲区溢出。

      这是可能发生缓冲区溢出的地方:

      scanf("%s",&amp;(student+i)-&gt;name);

      您的连字符功能可以在您解决此可能的缓冲区溢出问题后使用。

      修复缓冲区溢出

      解决此类问题的一种简单方法是让 scanf 本身限制要读取的字符数:

      // read only 10 chars, since `name` can only 
      // hold 10 chars, plus the extra NULL char
      scanf("%10s", &(student+i)->name);
      

      用连字符预填充

      最后,在你解决了你的记忆问题之后,你可以在用实际的学生数据覆盖之前预先填充你的字符串。

      // pre-fill your data with hypens.
      memset((student+i)->name, '-', sizeof((student+i)->name) - 1);
      
      // read only 10 chars, since `name` can only 
      // hold 10 chars, plus the extra NULL char
      scanf("%10s", &(student+i)->name);
      

      【讨论】:

      • 可维护性? (如果 student[i].name 的大小发生变化怎么办?)
      • @user:我是来解决他的具体问题的。如果他使用的是 11 字节长的变量,我写了适用于这种空间的最佳解决方案。也许他不能使用超过 11 个字节,谁知道呢。当然,如果分配的空间更大,它会更易于维护,但这不是问题的一部分。
      • 我并没有指出它是一个可以使用的小缓冲区,我只是说不要重复自己en.wikipedia.org/wiki/Don't_repeat_yourselfname已经定义为11个字符了,为什么还要重复自己说%10s
      • 感谢您指出有关“不要重复自己”概念的链接,我很清楚它是什么。然而,在这种情况下,它与重复自己无关。如果您不提供%10s,scanf() 会将任意数量的字节复制到name 变量,从而可能导致缓冲区溢出。拥有%10s 告诉scanf() 只读取10 个字节,这是变量name 允许的最大值。
      • 这正是重点。在这种情况下,您不得不重复name 的大小。如果 name 的长度变为 15,则必须返回并将其更改为 %14s。如果它再次更改为 25,您必须返回并将其更改为 %24s。如果您忘记更改这两个位置,则会出现随机错误。如果您将项目交给某人而忘记告诉他们在这两个地方都进行更改,他们会得到随机错误。
      【解决方案6】:

      使用fgets() 读取输入,如果有空间,它将把换行符保存到缓冲区;您必须为此添加一些特殊处理。

      请注意,fflush() 的行为对于输入流未定义;您无法通过调用fflush(stdin); 清除不需要的输入。

      然后就是将剩余的字符设置为连字符。

      if (fgets(students[i].name, sizeof students[i].name, stdin) != NULL)
      {
        size_t max = sizeof students[i].name - 1;
        size_t len = 0;
      
        char *newline = strchr(students[i].name, '\n');
        if (newline)
          *newline = 0; // clear out newline
        else
        {
          while (fgetc(stdin) != '\n') // clear out remaining input; 
                                       // name potentially truncated
            ;
        }
      
        // pad remainder with hyphens
        len = strlen(students[i].name);
        while (len < max)
          students[i].name[len++] = '-';
        students[i].name[max] = 0;
      }
      

      【讨论】:

        【解决方案7】:

        尝试以下方法:

        while (lengthName < 10)
        {
            (student+i)->name[lengthName++] = '-';
        }
        

        【讨论】:

          猜你喜欢
          • 2018-12-05
          • 2015-08-22
          • 2017-04-24
          • 2020-03-08
          • 2012-03-05
          • 2015-04-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多