【问题标题】:Populating a jagged char array in C from an unknow size list从未知大小的列表中填充 C 中的锯齿状字符数组
【发布时间】:2016-06-15 18:19:09
【问题描述】:

C 程序。 将为 linux 32 位和 windows 32 位编译。

gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

i686-w64-mingw32-gcc (GCC) 4.8.2

目标:

将包含歌曲列表的单个字符数组分解为多维字符数组。 我将“遍历”这个数组并与另一个列表进行比较,然后对其进行“工作”,例如删除歌曲或转换歌曲。

缓冲区和歌曲名称的大小未知。

缓冲区包含“[playlist1]\n12345\n54321\n[playlist2]\n6789\n9876\n[playlist3]\n更长的歌曲名称\n”

需要一个包含播放列表# 和歌曲名称的数组。

112345

154321

26789

29876

3更长的歌曲名称

array[0][0] 应该包含 1 (int 48)

array[0][2] 应该包含 2 (int 50) ...

工作:

我已经计算了“\n”的数量以获得数组总行大小(暂时忽略“[playlist1])

int array_length_all_songs = 0;
int index;
for (index = 0; index<plLength; index++)
{
    if (plBuffer[index] == '\n')
    {
        array_length_all_songs++;
    }
}

创建了一个char类型的数组

char **array_playlist = calloc(array_length_all_songs, sizeof(char *));

填充数组

char *token; /* "\x0a" == "\n"  */
char pl_num; /* remember a char is an int */
int array_length_working;
int song_name_length;
token = strtok(plBuffer,"\x0a");
while(token != NULL)
    /* set playlist number */
    if(strncmp(token,"[Playlist",9) == 0)
    {
        //printf("token: %s\n",token);
        pl_num = (unsigned char)token[9];
        //printf("pl: %c\n",pl_num);
    }
    else
    {
        array_length_working++;

        switch (pl_num)
        {
            case '1':
                if(strncmp(token,"[Playlist",9) != 0)
                {
                    song_name_length = strlen(token);
                    array_playlist[array_length_working] = calloc(song_name_length, sizeof(char));
                    strcpy(&array_playlist[array_length_working], token);

                }   
                break;
            case '2':

...

此代码不起作用,因为我正在努力处理指针和类型转换。

strcpy(&array_playlist[array_length_working], token);

我已经决定使用这种创建数组的方法,即使我必须遍历缓冲区一次才能获得大小。 我相信这种方法被称为 Iliffe 矢量

问题:

对于内存有限的计算机来说,我处理这一切是错误的还是效率低下?

如果不是……

我需要弄清楚如何将 $token 复制到数组 $array[123][0] 由于令牌是一个字符数组(int),我必须复制每个字符还是可以将整个“字符串”复制到新位置?

我无法动态创建变量 $song1,因此我无法将歌曲名称的指针放入数组中。因此,我必须将所有单个字符复制到数组中。 $数组[123][n++]。对吧?

我多年来一直在编程,但 c 编程对我来说是新的,似乎需要一种不同的思维方式,我仍在努力。

我已经阅读了很多书籍和帮助问题,但我似乎在绕圈子。

如果我的方法有误,概览可能会有所帮助。

【问题讨论】:

  • 我不明白您为什么需要将每首歌曲的标题与播放列表编号连接起来。由于播放列表编号必须是单个数字(否则您将无法区分播放列表编号和标题),播放列表的最大数量为 10,可以是每个标题数组的索引。所以array[3][0] 将是指向播放列表 3 中第一首歌曲的指针,以此类推。
  • 顺便说一句,最好不要硬编码newline 字符,最好有token = strtok(plBuffer, "\n");
  • 播放列表的最大数量为 4。用户将选择四个播放列表之一或所有播放列表来执行“工作”。我在想我可以对第一个字符(播放列表)做一个“如果”,以确定是否需要对该播放列表进行工作。
  • 我看到了使用锯齿状列表的问题。也许最好有一个由 4 个 struct 组成的数组,它告诉您每个播放列表中的歌曲数量、可以保存的最大数量以及指向这些标题的指针数组,当它们增长时可以是 realloced。这些指针可以由strdup(token); 设置
  • 如果没有真正为您编写它,它变得太复杂了。但我建议使用结构数组。

标签: c arrays string


【解决方案1】:

这说明了如何构建播放列表数组,每个播放列表都包含一组歌曲标题。使用全局数组不是一个好习惯,但为了简单起见,我这样做了。

每个播放列表都有一个歌曲标题指针数组。当该数组已满时,它会被扩展。在实践中,SONGS 的值越大,程序效率越高。

我让你从文件中提取数据。因为token 指向的标题会被覆盖,所以我在MSVC(调用malloc)中使用strdup_strdup 来制作每个标题的副本。在你的程序结束时,你应该迭代数组,到free每个标题的内存,然后free每个指针数组。

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

#define LISTS   4                   // number of play lists
#define SONGS   3                   // incremental number of songs per list

typedef struct {
    int numsongs;                   // number of songs in list
    int maxsongs;                   // maximum possible songs in list
    char **song;                    // base of array of pointers
} list_t;

list_t lib[LISTS] = { {0} };

void addsong(int listnum, char *title)
{
    list_t *ptr;
    char **arr;
    if (listnum < 1 || listnum > LISTS) {
        exit(1);                    // or other error checking
    }
    ptr = &lib[listnum-1];          // for convenience, and arrays are 0-based
    if (ptr->numsongs >= ptr->maxsongs) {
        // extend the song titles array
        arr = realloc(ptr->song, (ptr->maxsongs + SONGS) * sizeof(char*));
        if(arr == NULL) {
            exit(1);                // or other error checking
        }
        ptr->song = arr;            // new bigger array
        ptr->maxsongs += SONGS;     // more capacity
    }
    // save a pointer to a copy of the song title
    ptr->song[ ptr->numsongs ] = _strdup(title); 
    ptr->numsongs++;
}

int main(void)
{
    int i, j;

    // add songs to playlists in random order
    addsong(2, "Song two/one");
    addsong(1, "Song one/one");
    addsong(4, "Song four/one");
    addsong(2, "Song two/two");
    addsong(1, "Song one/two");
    addsong(2, "Song two/three");
    addsong(2, "Song two/four");
    addsong(2, "Song two/five");
    addsong(1, "Song one/three");

    // show what we've got
    for(i=0; i<LISTS; i++) {
        printf("Playlist %d\n", i + 1);
        for(j=0; j<lib[i].numsongs; j++) {
            printf("   %s\n", lib[i].song[j]);
        }

    }
    return 0;
}

程序输出:

Playlist 1
   Song one/one
   Song one/two
   Song one/three
Playlist 2
   Song two/one
   Song two/two
   Song two/three
   Song two/four
   Song two/five
Playlist 3
Playlist 4
   Song four/one

【讨论】:

  • 非常感谢您花时间解释我需要知道的事情。
猜你喜欢
  • 1970-01-01
  • 2018-09-15
  • 2012-11-27
  • 2021-05-13
  • 2023-03-04
  • 1970-01-01
  • 2019-11-17
  • 1970-01-01
  • 2021-12-14
相关资源
最近更新 更多