【问题标题】:Convert words in char array to a line with single space [duplicate]将char数组中的单词转换为带有单个空格的行[重复]
【发布时间】:2019-01-27 16:35:15
【问题描述】:

将给定的char *input[] 转换为包含单个空格的行

输入

int n =3;
char *result;
char *input[]= {"one", "two", "three" };
result = convertToLine(n, input)

代码

char *convertToLine(int n, char *input[]) {
    int size = n* 2;
    char* string = (char*)malloc(sizeof(char)*size);        
    int i = 0;
    int k = 0;
    while (i <size){
        string[i] = *input[k];         
        string[i+1] = ' ';
        i++;
        k++;
     }
   string[n] = '\0';
   return string;
}

我的输出:

预期输出

result = "one two three"

【问题讨论】:

  • 你的问题是?
  • 问题是“为什么那个代码不起作用”^^
  • 嗯,n = 3 => size = 6。string 将是一个大小为 6 的 char 数组。最终数组中将有超过 6 个字符,这是肯定的。 (作为最初的错误)。
  • 调试器有助于找出您的程序为何如此运行。如果您还不知道如何使用调试器,那么这看起来是一个很好的程序,可以在您学习基础知识时使用。
  • @Sanjana 在 C 中你没有字符串,你有字符数组。 string[i] = *input[k]; 不会从“字符串”中的输入中复制第 k 个字符串,它只会复制一个字母。此外,string 只有 6 个字符的空间,您需要 3 + 3 + 5 + 2(来自空格)+ 1(来自 NULL 终止符)= 13。` 不使用库函数` => 你还需要一个函数获取每个单词的长度,否则您将不得不多次重新分配缓冲区。

标签: c arrays


【解决方案1】:

您的代码中有几个错误

int 大小 = n* 2; char* 字符串 = (char*)malloc(sizeof(char)*size);

所需的size必须是最终的大小,所以要合并的字符串的长度总和更多的地方为空格和最终的空字符。 n *2 只是字符串数的两倍,这个不一样

字符串[i] = *输入[k];

不复制字符串,只复制第一个字符

你可以这样做:

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

char *convertToLine(int n, char *input[]) {
  /* compute the needed size,
     of course can also use malloc then realloc to avoid that */
  int size = 0;
  int i;

  for (i = 0; i != n; ++i)
    size += strlen(input[i]) + 1;

  /* copy the strings */
  char * string = (char*)malloc(size); /* sizeof(char) is 1 by definition */
  char * p = string;

  for (i = 0; i != n; ++i) {
    strcpy(p, input[i]);
    p += strlen(p);
    *p++ = ' ';
  }
  p[-1] = 0;

  return string;
}


int main()
{
  char *input[]= {"one", "two", "three" };
  char * result = convertToLine(3, input);
  puts(result);

  free(result);
}

执行:

one two three

valgrind下执行:

pi@raspberrypi:/tmp $ valgrind ./a.out
==14749== Memcheck, a memory error detector
==14749== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14749== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14749== Command: ./a.out
==14749== 
one two three
==14749== 
==14749== HEAP SUMMARY:
==14749==     in use at exit: 0 bytes in 0 blocks
==14749==   total heap usage: 2 allocs, 2 frees, 1,038 bytes allocated
==14749== 
==14749== All heap blocks were freed -- no leaks are possible
==14749== 
==14749== For counts of detected and suppressed errors, rerun with: -v
==14749== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

【讨论】:

    【解决方案2】:

    如果我理解你的问题,你的问题是你不能分配字符串,例如

    string[i] = *input[k];
    

    在上面,您试图将第 kth 指针的第一个字符分配给string[i],这将超出input 的末尾。相当于:

    *(input[k] + 0)
    

    input[k][0]
    

    见:C Operator Precedence

    相反,您需要调用 strcpy 或简单地使用额外的循环来复制每个所需的字符,例如

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char *convertToLine (size_t n, char *input[])
    {
        size_t  ndx = 0,        /* string index */
                len = 0;        /* length of combined strings */
        char *string = NULL;    /* pointer to string */
    
        for (size_t i = 0; i < n; i++)  /* length of all in input */
            len += strlen (input[i]);
    
        string = malloc (len + n);      /* allocate len + n-1 space + 1 */
        if (!string) {                  /* validate allocation */
            perror ("malloc-string");
            return NULL;
        }
        for (size_t i = 0; i < n; i++) {        /* for each string */
            if (i)                              /* if not 1st */
                string[ndx++] = ' ';            /* add space */
            for (int j = 0; input[i][j]; j++)   /* copy input string */
                string[ndx++] = input[i][j];
        }
        string[ndx] = '\0';     /* nul-terminate */
        return string;
    }
    

    用您的input 添加一个简短的示例,您将拥有:

    int main (void) {
        char *input[]= {"one", "two", "three" },
            *result = NULL;
        size_t n = sizeof input / sizeof *input;
    
        result = convertToLine (n, input);
        if (result) {
            printf ("result: '%s'\n", result);
            free (result);
        }
    }
    

    使用/输出示例

    $ ./bin/str_combind
    result: 'one two three'
    

    【讨论】:

      【解决方案3】:

      您需要在每次迭代中将 i 增加 2,因为如果将其增加 1,您将继续覆盖空格并最终复制单词,并最终读取未初始化的内存。祝你好运:)

      【讨论】:

        【解决方案4】:
        char *arr_to_sentece(char **arr, size_t len)
        {
            size_t mems = 0;
            char *sentence, *saveds; 
        
            for(size_t index = 0; index < len; index++)
                mems += strlen(arr[index]);
            mems += len - 1;
            sentence = malloc(mems + 1);
            if(sentence)
            {
                size_t wlen;
        
                saveds = sentence;
                while(len--)
                {
                    wlen = strlen(*arr);
        
                    strcpy(sentence, *arr++);
                    sentence[wlen] = ' ';
                    sentence += wlen + 1;
                }
                *sentence = 0;
            }
            return saveds;
        }
        

        【讨论】:

          【解决方案5】:

          我接受了您的代码并进行了一些更改,之前的一些答案可以正常工作,但是如果您想在不使用任何第三个库函数的情况下实现这一点,这是我的方法

          #include <iostream>
          using namespace std;
          
          int getWordLength(const char input[]) {
              int cont = 0;
              int i = 0;
              //count the characters of the word, the last defining char always is '\0'
              while (input[i] != '\0') {
                  cont++;
                  i++;
              }
              return cont;
          }
          
          int getSentenceLength(int n, const char *input[]) {
              int sentenceLength = 0;
              //add the word length to the total sentence length
              for (int i = 0; i < n; i++) {
                  sentenceLength += getWordLength(input[i]);
              }
              //add the spaces length
              sentenceLength += n;
              return sentenceLength;
          }
          
          void addWordToSentence(char* string, const char input[]) {
              int length = getWordLength(input); //get the word length
          
              //add the word to tha final sentence char by char
              int i = 0;
              int j = getWordLength(string);
              for ( ; i < length; i++, j++) {
                  string[j] = input[i];
              }
          
              //add one space after the added word
              string[j] = ' ';
          }
          
          void cleanString(char* string, int size) {
              for (int i = 0; i < size; i++) {
                  string[i] = '\0';
              }
          }
          
          char *convertToLine(int n, const char *input[]) {
              //get the total size
              int size = getSentenceLength(n, input);
              char* string = (char*)malloc(sizeof(char)*size);
          
              //clean the string with '\0'
              cleanString(string, size);
          
              int i = 0;
              while (i < n) {
                  addWordToSentence(string, input[i]);
                  i++;
              }
          
              string[size - 1] = '\0';
              return string;
          }
          
          int main() {
              int n = 3;
              char *result;
              const char *input[] = { "one", "two", "three" };
              result = convertToLine(n, input);
              cout << result;
          
              getchar();
              return 0;
          }
          

          测试和工作

          【讨论】:

            【解决方案6】:
            char *convertToLine(int size, char *input[]) {
            
               char *string = NULL;
               for(int i =0; i<size; i++)
               {
            
                    int size_to_allocate = string != NULL ? strlen(string)+ strlen(input[i]) +2 : strlen(input[i]) +2;
                    string = (char*)realloc(string, sizeof(char) * size_to_allocate);
                    strcat(string, input[i]);
                    if(i< size -1)strcat(string, " ");
               }
               return string;
            }
            

            【讨论】:

              【解决方案7】:

              您可以在需要时使用 realloc 重新分配内存并连接需要的单词。

                  char *convertToLine(int size, char *input[]) {
              
                 char *string = NULL;
                 for(int i =0; i<size; i++)
                 {
                      int size_to_allocate = string != NULL ? strlen(string)+ strlen(input[i]) : strlen(input[i]);
                      string = (char*)realloc(string, sizeof(char) * size_to_allocate);
                      strcat(string, input[i]);
                      if(i< size -1)strcat(string, " ");
                 }
                 return string;
              }
              

              【讨论】:

              • 对不起,那段代码根本不起作用,如果不是正确的,则重新分配大小
              • 感谢布鲁诺,幸运的是它正在工作我不知道如何。但我意识到我的错误
              • char convertToLine(int size, char *input[]) { char *string = NULL; for(int i =0; i)realloc(string, sizeof(char) * size_to_allocate); strcat(字符串,输入[i]); if(i
              • 你的新版本还是错了,你漏掉了一个字符。我鼓励你看看 valgrind 来检查你的内存访问/泄漏,跳到你可以在站中使用它
              • 谢谢。是的!你说的对。我会检查 valgrind
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-08-30
              • 1970-01-01
              • 2017-06-08
              • 1970-01-01
              • 2011-02-13
              • 1970-01-01
              相关资源
              最近更新 更多