【问题标题】:String concatenation without libraries in CC中没有库的字符串连接
【发布时间】:2021-01-05 05:38:41
【问题描述】:

在没有库函数的情况下,我无法在 C 中连接字符串。 我尝试了以下方法:

#include <stdio.h>

struct word {
  char *str;
  int wordSize;
};

void concat(struct word words[], int arraySize, int maxSize) { // word array, its size, and max size given
  char result[maxSize];
  int resultSize = 0;
  struct word tmp;

  for (int i = 0; i < arraySize; i++) {
    tmp = words[i];
    for (int j = 0; j < words[i].wordSize; j++,  resultSize++) {
      result[resultSize + j] = tmp.str[j];
    }
  }

  puts(result);
}

例如,如果结构数组words 包含[{"he", 2}, {"ll", 2}, {"o", 1}],则result 应该是hello。但是,此代码打印h�l�o,其中第二个和第四个字母是问号。谁能帮我调试一下?

【问题讨论】:

  • result[resultSize + j] = tmp.str[j]; 是错误的,您在每次迭代中递增 jresultSize,因此您将跳过 result 中的每个第二个索引。
  • @mch 我明白了。感谢那。这解决了问题。
  • @mmmdwldmm 除我之外的所有答案都是错误的,并且提供的函数可以调用未定义的行为。

标签: c struct concat c-strings function-definition


【解决方案1】:

在这个for循环中

for (int j = 0; j < words[i].wordSize; j++,  resultSize++) {
  result[resultSize + j] = tmp.str[j];
}

您同时递增resultSizej,而您只需要增加变量j 并在循环之后将变量resultSize 增加j

但无论如何该函数都是错误的,因为没有检查resultSize 是否小于maxSize

此外,构建的字符串没有附加终止零'\0'。结果这个说法

puts(result);

调用未定义的行为。

无需创建变长数组

char result[maxSize];

只是为了输出连接的字符串。

该函数可以通过以下方式声明和定义,如下面的演示程序所示。

#include <stdio.h>

struct word {
  char *str;
  int wordSize;
};

void concat( const struct word words[], size_t arraySize, size_t maxSize )
{
    for ( size_t i = 0, j = 0; i < maxSize && j < arraySize; j++ )
    {
        for ( size_t k = 0; i < maxSize && k < words[j].wordSize; i++, k++ )
        {
            putchar( words[j].str[k] );
        }
    }
    
    putchar( '\n' );
}

int main(void) 
{
    struct word words[] =
    {
        { "he", 2 }, { "ll", 2 }, { "o", 1 }
    };
    const size_t arraySize = sizeof( words ) / sizeof( *words );
    
    concat( words, arraySize, 5 );
    
    return 0;
}

程序输出是

hello

【讨论】:

    【解决方案2】:

    这里有几个问题。 result[resultSize + j] 表示您实际上跳过了结果中的一半以上的字符。其次,如果您复制整个字符串,包括空字符,puts 将在第一个单词本身的末尾停止打印结果字符串。因此,您需要跳过复制字符串终止符并将其放在整个连接字符串的末尾。

    #include <stdio.h>
    
    struct word {
      char *str;
      int wordSize;
    };
    
    void concat(struct word words[], int maxSize) { // word array and max size given
      char result[maxSize];
      int resultSize = 0;
      struct word tmp;
    
      for (int i = 0; i < 3; i++) {
        tmp = words[i];
        // Keep copying the words to result, one after the other
        // But drop the last NULL character
        for (int j = 0; j < (words[i].wordSize - 1); j++,  resultSize++) {      
          result[resultSize] = tmp.str[j]; 
        }
      }
      // Put the NULL character in after all words have been copied
      result[resultSize] = 0;
      puts(result);
    }
    
    struct word mywords[] = 
    {
      { "TestWord", sizeof("TestWord")},
      { "TestWord2", sizeof("TestWord2")}
    };
    
    int main(void)
    {
      concat(mywords, 100);
      return 0;
    }
    

    【讨论】:

    • 非常感谢。抱歉,我不能同时接受这两个答案。我只是选择了较早的那个。
    【解决方案3】:

    保持简单,错误会自行修复。不要将result 缓冲区中的位置与循环迭代器混淆。不需要临时变量。

    #include <stdio.h>
    
    typedef struct {
      char *str;
      int wordSize;
    } word;
    
    void concat(word words[], int arraySize, int maxSize) { 
      char result[maxSize];
      int count=0;
      
      for(int i=0; i<arraySize; i++)
      {
        for(int j=0; j<words[i].wordSize; j++)
        {
          result[count]= words[i].str[j];
          count++;
        }
      }
      result[count] = '\0';
      
      puts(result);
    }
    
    int main()
    {
      word w[3] = { {"he", 2}, {"ll", 2}, {"o", 1} };
      concat(w, 3, 128);
    }
    

    【讨论】:

    • 我看到我实际上已经在@mch 的评论的帮助下解决了这个问题,但是看看你的代码,我的代码似乎需要很多改进。非常感谢您的提示。
    • 您可能想在concat() 循环中检查maxSIze
    • @IngoLeonhardt 不,但可能在函数的开头。因为result 显然是一个足以容纳maxSize 的缓冲区。
    • 我的意思是没有检查单个单词的添加大小是否超过maxSize。当然这也可以在单独的循环中完成
    • @IngoLeonhardt 啊我现在明白了,确实应该在某个地方进行这样的检查。但是这些人为的新手程序总体上在错误处理方面往往缺乏很多:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 2021-08-02
    • 1970-01-01
    • 2018-03-06
    • 2013-09-21
    相关资源
    最近更新 更多