将两个列表的笛卡尔积创建到 C 中的新列表中

Creating the cartesian product of two lists into a new list in C

我想创建一个数组,它是两个数组的笛卡尔积。例如:

const char *first[] = {"1", "2","3"};
const char *second[] = { "a" , "b" , "c", "e"};

结果是数组:

Cartesian = {"(1,a)","(1,b)","(1,c)",....};

这是我目前拥有的:

int main(int argc, const char * argv[]) {

    const char *first[] = {"1", "2","3"};
    const char *second[] = { "a" , "b" , "c", "e"};

    int size = sizeof(first) * sizeof(second);

    char *both[size];
    int i=0;

    for (int f=0; f<sizeof(first); f++) {  
       for (int s=0; s<sizeof(second); s++) {
          char *temp[size];
           strcpy(temp[s], "("+first[f]+ ","second[s]+")");
           both[i] = temp;
           i++;
       }
   }
   return 0;
}

您的代码中的问题:

  1. sizeof(first)(和 sizeof(second))给出 number of string literals in the array * sizeof(char*)。您需要丢弃第二部分。只需将它除以 sizeof(char*)sizeof(*str) 作为 @BLUEPIXY sizeof(str[0]):

    相同
    int size = (sizeof(first) / sizeof(*first)) * (sizeof(second) / sizeof(*second));
    
  2. 你的循环:

    for (int f=0; f<sizeof(first); f++)
    for (int s=0; s<sizeof(second); s++)
    

    遇到同样的问题。我建议使用

    int size1 = sizeof(first) / sizeof(*first);
    int size2 = sizeof(second) / sizeof(*second)
    
    for (int f=0; f < size1; f++)
    for (int s=0; s < size2; s++)
    
  3. 你的循环体有很多问题。从中删除所有内容。以下步骤显示了在那里可以做什么。

解决问题的步骤:

  1. 您需要为 char *both[size]; 分配内存。从循环体分配内存:

    int i=0;
    
    for (int f=0; f < size1; f++)
    {
        for (int s=0; s < size2; s++)
        {
            both[i] = malloc(strlen(first[f]) + strlen(second[s]) + 4);
            /*Mallocing space for two brackets, a comma, a NUL-terminator and the coordinates*/
            i++; //Increment counter
        }
    }
    
  2. strcpy 是这里使用的错误函数。使用 sprintf 代替:

    int i=0;
    
    for (int f=0; f < size1; f++)
    {
        for (int s=0; s < size2; s++)
        {
            both[i] = malloc(strlen(first[f]) + strlen(second[s]) + 4);
    
            sprintf(both[i], "(%s,%s)",first[f],second[s]); // Make the string
            i++;
        }
    }
    
  3. 循环后,both根据你的需要填充。使用以下方式打印它们:

    for(int j=0; j<i ; j++)
        printf("%s \n",both[j]);
    
  4. 使用后,free分配的内存使用:

    for(int j=0; j<i ; j++)
        free(both[j]);
    

固定程序:

#include <stdio.h>
#include <stdlib.h> //For malloc and free
#include <string.h> //For strlen

int main(int argc, const char * argv[]) {

    const char *first[] = {"1", "2","3"};
    const char *second[] = { "a" , "b" , "c", "e"};

    int size = (sizeof(first) / sizeof(*first)) * (sizeof(second) / sizeof(*second));

    char *both[size];
    int i=0;

    int size1 = sizeof(first) / sizeof(*first);
    int size2 = sizeof(second) / sizeof(*second)

    for (int f=0; f < size1; f++)
    {
        for (int s=0; s < size2; s++)
        {
            both[i] = malloc(strlen(first[f]) + strlen(second[s]) + 4);
            sprintf(both[i], "(%s,%s)",first[f],second[s]);
            i++;
        }
    }

    for(int j=0; j<i ; j++)
        printf("%s\n",both[j]);

    for(int j=0; j<i ; j++)
        free(both[j]);

    return 0; //or return(EXIT_SUCCESS);
}

其他说明:

  • 查看malloc的结果,看是否分配内存成功。 malloc returns NULL 失败。
  • 检查 sprintf 的结果也很好,虽然不是必需的。 sprintf returns 失败时为负数。

程序如下所示

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

int main( void )
{
    const char *first[] = { "1", "2", "3" };
    const char *second[] = { "a" , "b" , "c", "e" };
    const size_t N = sizeof( first ) / sizeof( *first );
    const size_t M = sizeof( second ) / sizeof( *second );
    char product[N * M][3];

    for ( size_t i = 0; i < N; i++ )
    {
        for ( size_t j = 0; j < M; j++ )
        {
            strcpy( product[i*M + j], first[i] );
            strcat( product[i*M + j], second[j] );
        }
    }

    for ( size_t i = 0; i < N * M; i++ ) printf( "%s ", product[i] );
    printf( "\n" );

    return 0;
}

程序输出为

1a 1b 1c 1e 2a 2b 2c 2e 3a 3b 3c 3e 

如果您想将每个字符串括在括号中,那么程序可以看起来像

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

int main( void )
{
    const char *first[] = { "1", "2", "3" };
    const char *second[] = { "a" , "b" , "c", "e" };
    const size_t N = sizeof( first ) / sizeof( *first );
    const size_t M = sizeof( second ) / sizeof( *second );
    char product[N * M][6];

    for ( size_t i = 0; i < N; i++ )
    {
        for ( size_t j = 0; j < M; j++ )
        {
            strcpy( product[i*M + j], "(" );
            strcat( product[i*M + j], first[i] );
            strcat( product[i*M + j], "," );
            strcat( product[i*M + j], second[j] );
            strcat( product[i*M + j], ")" );
        }
    }

    for ( size_t i = 0; i < N * M; i++ ) printf( "%s ", product[i] );
    printf( "\n" );

    return 0;
}

程序输出为

(1,a) (1,b) (1,c) (1,e) (2,a) (2,b) (2,c) (2,e) (3,a) (3,b) (3,c) (3,e) 

还有循环

    for ( size_t i = 0; i < N; i++ )
    {
        for ( size_t j = 0; j < M; j++ )
        {
            strcpy( product[i*M + j], "(" );
            strcat( product[i*M + j], first[i] );
            strcat( product[i*M + j], "," );
            strcat( product[i*M + j], second[j] );
            strcat( product[i*M + j], ")" );
        }
    }

可以用sprintf(甚至snprintf)写得更简单

for ( size_t i = 0; i < N; i++ )
{
    for ( size_t j = 0; j < M; j++ )
    {
        sprintf( product[i*M + j], "(%s,%s)", first[i], second[j] );
    }
}