【问题标题】:Function for scanning string - what's the problem?扫描字符串的功能 - 有什么问题?
【发布时间】:2022-01-22 18:35:53
【问题描述】:
char* scanString()
{
    char* str = NULL;
    char* temp = NULL;
    int  numOfChars = 0;
    char c = '0';
    while (c != '\n')
    {
        scanf(" %c", &c);
        if (c != '\n')
        {
            if (numOfChars == 0)
            {
                char* str = (char*)malloc(sizeof(char));
                char* temp = str;
                if (str == NULL)
                    return str;
                str[0] = c;
                numOfChars++;
            }
            else
            {
                str = (char*)realloc(str, sizeof(char) * (numOfChars + 1));
                str[numOfChars] = c;
                if (str == NULL)
                    return temp;
                else
                {
                    temp = str;
                    numOfChars++;
                }
            }
        }
    }
    str = (char*)realloc(str, sizeof(char) * (numOfChars+1));
    if (str == NULL)
    {
        str = temp;
        return str;
    }
    str[numOfChars] = '\0';
    return str;
}
int main()
{
    char* m;
    printf("write:\n");
    m = scanString();
    printf("%s\n", m);
}

我试图创建一个函数来逐个字符地扫描未知大小的字符串,但我不知道这里有什么问题。顺便说一句,请不要接近我任何其他代码或尝试使用不同的库。

【问题讨论】:

  • 由于scanf 格式字符串" %c" 中的前导空格,scanf 函数将跳过所有空格,包括换行符。所以c永远成为换行符'\n'
  • 你实际上并没有说“问题”是什么。

标签: c string pointers char realloc


【解决方案1】:

有一个大错误和一些不一致的地方。

大错误在这里:

        if (numOfChars == 0)
        {
            char* str = (char*)malloc(sizeof(char)); // Oops a new var!
            char* temp = str;                        // and another one!
            if (str == NULL)
                return str;
            str[0] = c;
            numOfChars++;
        }

您在该块中声明了 2 个新变量,这些变量将隐藏外部范围的变量。结果,第一个字符会丢失,你会得到一个随机值。

不一致之处:

  • temp没用,应该删除

  • 您使用" %c" 格式阅读。该格式将跳过任何空白字符包括\n。应该是"%c"

  • 您未能测试scanf 的返回值。在文件结束时(任何其他读取错误),您将进入无限循环。应该是:

          if (1 != scanf("%c", &c)) break;
    

一旦这个问题得到解决,您应该会得到预期的输出,但其他改进仍然是可能的:

  • 读取一个字符的惯用方式是getcgetchar
  • 一次分配一个字符是一种反模式,因为(重新)分配是一项相当昂贵的操作。对于现实世界的程序,您应该始终分配一堆或内存并跟踪可用部分
  • sizeof(char) 每个标准 1 个
  • numOfChars == 0 的区别是没有用的。 NULL 指针上的reallocmalloc 相同。

【讨论】:

    【解决方案2】:

    您的代码过于复杂和错误并且如评论中所述,您需要将格式字符串" %c" 替换为"%c"

    主要问题在这里:

    if (numOfChars == 0)
    {
      char* str = (char*)malloc(sizeof(char));
    

    您声明了一个新的str 变量,它隐藏了您在函数开头声明的str 变量。

    只需将char* str = (char*)malloc(sizeof(char)) 替换为str = malloc(sizeof(char));。顺便说一句,演员表是不必要的。

    temp 也有同样的问题。

    以下代码完全基于您的代码,但更简单、更正确。基本上,numOfChars 为 0 的情况不应特殊处理。您可以只使用realloc,因为realloc(NULL, foo) 等价于malloc(foo)

    char* scanString()
    {
      char* str = NULL;
      char* temp = NULL;
      int  numOfChars = 0;
      char c = '0';
      while (c != '\n')
      {
        scanf("%c", &c);
        if (c != '\n')
        {
          str = realloc(str, sizeof(char) * (numOfChars + 1));
          if (str == NULL)
            return temp;
          
          str[numOfChars] = c;
          temp = str;
          numOfChars++;
        }
      }
       
      str = realloc(str, sizeof(char) * (numOfChars + 1));
      if (str == NULL)
      {
        str = temp;
        return str;
      }
      str[numOfChars] = '\0';
      return str;
    }
    

    甚至更简单:

    char* scanString()
    {
      char* str = NULL;
      char* temp = NULL;
      int  numOfChars = 0;
      char c = '0';
      while (c != '\n')
      {
        scanf("%c", &c);
    
        str = realloc(str, sizeof(char) * (numOfChars + 1));
        if (str == NULL)
          return temp;
    
        str[numOfChars] = c;
        temp = str;
    
        if (c == '\n')
        {
          str[numOfChars] = '\0';
        }
    
        numOfChars++;
      }
    
      return str;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 2011-12-21
      • 1970-01-01
      • 2018-07-14
      相关资源
      最近更新 更多