【问题标题】:How to copy a string to a 2D array in c如何在c中将字符串复制到二维数组
【发布时间】:2021-07-02 21:47:08
【问题描述】:

我想创建一个 c 程序,当用户输入这样的单词时:“some,words,in,c,proramming。”程序将单词保存在字符串“str”中,然后动态创建一个二维数组并将单词复制到二维数组中:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <math.h>
#include <conio.h>

void freeMememory(int**array, int row){
    for(int i=0;i<row;i++)
        free(array[i]);
    free(array);
}

int lettersCount(char *arr){
    int space=0, letters=0;
        do{
        if(*arr !=' '&& *arr!='\t' && *arr!=','&& *arr!='.'){
          letters =letters+1;
        }
        ++arr;
        }while(*arr);

    return letters;
}

int wordCount(char *arr){
    int space=0, words=0;
    for(int i=0; arr[i]!='\0'; i++){
        if(arr[i] ==' '|| arr[i]=='\t'|| arr[i]=='\n'||arr[i]==','||arr[i]=='.'){
          space++;
        }
        if(space>0){
            words++;
            space=0;
        }
    }

    return words;
}
int main    (){
    char arr[100];
    int i, j, row, column;

    scanf("%[^\n]s", &arr);
    int *words = wordCount(arr);
    int *letters = lettersCount(arr);
    row=words;
    column=letters;

    int **ptr = (int **)malloc(row*column*sizeof(int));
    for(i=0;i<row;i++){ptr[i]=(int*)malloc(column*sizeof(int));}

    /*

    //how should I write here to copy only words from arr to ptr?
    like this:

    arr = "some words, two,three,four."
    
    ptr = {
       "some", "words", "two", "", "three", "four",
      }
     
    */

    freeMememory(ptr, row);
    return 0;}


那么任何想法如何只将字符串中的单词复制到二维数组而不复制(句点、空格、cammas)?

【问题讨论】:

  • ⟼请记住,尤其是在 Stack Overflow 上学习和提问时,尽可能让代码保持井井有条是很重要的。 Consistent indentation 有助于传达结构,更重要的是,意图,这有助于我们快速找到问题的根源,而无需花费大量时间来尝试解码正在发生的事情。将语句放在一行上确实会使事情变得一团糟。
  • 提示:如果您使用 rows 甚至 rowsCount 之类的东西而不是非常具有误导性的 row 变量,这会有所帮助。
  • int *words = wordCount(arr);int 分配给int*,这是无效的,任何使用它都会导致未定义的行为。
  • @tadman 我编辑了我的代码以便更容易理解。
  • 你应该解释一下,代码是用来做什么的,不要让人猜。

标签: arrays c string 2d


【解决方案1】:

您可能正在寻找来自&lt;string.h&gt;strtok。我还将在以下代码 sn-p 中将 row 替换为 rowscolumn 替换为 columns,正如 cmets 中的 tadman 所建议的那样。

/* no need to cast `malloc` */
char *ptr[rows];
for (int i = 0; i < rows; ++i) {
    ptr[i] = malloc(columns);
    if (!token) {
        fprintf(stderr, "Error: memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
}

const char *delims = " \t\n,.";

/* second argument are delimiters */
strcpy(ptr[0], strtok(arr, delims));
for (int i = 1; i < rows; ++i)
    strcpy(ptr[i], strtok(NULL, delims));

我还建议简化您的功能。例如,您的 wordCount 函数可能会简化为:

int count_words(char *str, const char *delims)
{
    words = 1;
    for (int i = 0; str[i] != '\0'; ++i)
        if (strchr(delims, str[i]))
            ++words;
    return words;
}

然后可以像这样调用函数count_words

const char *delims = " \t\n,.";
int words = count_words(arr, delims);

【讨论】:

  • 不确定,好像有点苛刻。
  • @tadman 正如我所见,这里有几个错误。 1) 通过覆盖 malloc 的 ptr[i] 导致内存泄漏 2) 没有 strcpy 到目的地
  • @4386427 你说得对!我想我现在解决了这两个问题,但如果还有其他需要改进的地方,请告诉我。
  • 谢谢你们(tadman,Andy)。它有效。
【解决方案2】:

首先请注意,您的代码没有使用二维数组。它使用一个字符指针数组,每个指针都指向一个字符数组。这是另一回事,但可以以几乎相同的方式使用。

下面是一个使用strtok 分割输入字符串的实现。此外,它使用realloc 使字符指针数组在找到新单词时增长。最后,它使用标记(即NULL)来指示词尾。

代码很简单,但性能很差。

例子:

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

char** split(const char* str)
{
    if (str == NULL) exit(1);

    // Copy input string as strtok changes its input    
    char* str_cpy = malloc(strlen(str) + 1);
    if (str_cpy == NULL) exit(1);
    strcpy(str_cpy, str);
    
    unsigned num_rows = 0;
    char** arr = NULL;

    // Get first token
    const char *delims = " \t\n,.";
    char* ptr = strtok(str_cpy, delims);
    while (ptr)
    {
        // Allocate one more row
        arr = realloc(arr, (num_rows + 1) * sizeof *arr);
        if (arr == NULL) exit(1);
        
        // Allocate memory for one more word
        arr[num_rows] = malloc(strlen(ptr) + 1);
        if (arr[num_rows] == NULL) exit(1);
        strcpy(arr[num_rows], ptr);
        ++num_rows;

        // Get next token
        ptr = strtok(NULL, delims);
    }

    // Add a sentinel to indicate end-of-words
    arr = realloc(arr, (num_rows + 1) * sizeof *arr);
    if (arr == NULL) exit(1);
    arr[num_rows] = NULL;
    
    free(str_cpy);    
    return arr;
}

int main(void) 
{
    char* str = "some,words, in,    c, programming.";
    char** arr = split(str);
    
    printf("Original string: %s\n", str);
    for (int i=0; arr[i] != NULL; ++i)
    {
        printf("Word[%d]: %s\n", i, arr[i]);
    }

    // Free array       
    for (int i=0; arr[i] != NULL; ++i)
    {
        free(arr[i]);
    }
    free(arr);
    
    return 0;
}

输出:

Original string: some,words, in,    c, programming.
Word[0]: some
Word[1]: words
Word[2]: in
Word[3]: c
Word[4]: programming

【讨论】:

  • 谢谢,我还有一个问题,如何编写一个函数来打印字符串数组中的唯一单词。例如arr[] = "this this this this is text" 它只打印 "is, text" ?
  • 如果你只想保存唯一的单词,你必须扩展while (ptr)循环并检查当前单词是否已经在数组中(如果是,不要再插入它)。对于这个strcmp很有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-10
  • 2010-10-16
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多