C - 计算2D数组中空元素数的结果不正确

时间:2018-02-18 14:44:26

标签: c arrays sorting

我正在为大学作业创建一个程序,用户需要输入艺术家和他们的歌曲。程序然后按字母顺序对它们进行排序并将它们混洗。艺术家名称存储在名为artists[][80]的数组中,歌曲名称存储在songsArtistx中,其中x是1到4之间的数字。我初始化所有数组以填充NULL终结符 - '\ 0 ”。要使程序正常工作,我需要找到输入的歌曲数量(必须至少为1,但可以是3或更少)。为此,我使用了一个名为checkSongs的函数:

int checkSongs(char songsOfAnArtist[][80])
{
    int i,numOfSongs;

    //Loop goes through 4 possible artists.
    for (i=0;i<4;i++)
    {
        //Assume there are 3 songs for each artits, and decrement by 1 each time an empty string occurs.
        numOfSongs = 3;
        if (songsOfAnArtist[i][0]=='\0' || songsOfAnArtist [i][0] == '\n')
        {
            numOfSongs--;
            break;
        }
    }

    return numOfSongs;
}

然而,当歌曲的数量小于3时,这个函数给我一个错误的结果。这是命令行的一个例子,还有来自调试器的变量的屏幕截图:

Example from Command line

在上面的照片中,最后一行的数字表示输入的艺术家数量(在这种情况下是正确的)和songsArtsist1songsArtsist2,{{1}中的歌曲数量},songsArtsist3。最后一个数字是艺术家的数量。

Debugger varaibles

如何更改我的代码,以便songsArtsist4返回为每位艺术家输入的歌曲数量?

以下也是主文件的摘录,可能与问题有关:

checkSongs

这里有数组:

//Get all inputs from command line: artists and songs
getInputs(artists,songsArtist1,songsArtist2,songsArtist3,songsArtist4);

//Use checkArtists to store the number of entered artists in variable 'numOfArtists'
numOfArtists = checkArtists(artists);
printf("%d ",numOfArtists);

//Use check songs to store number of songs per artist in array 'numSongsPerArtists'
numSongsPerArtist[0] = checkSongs(songsArtist1);
numSongsPerArtist[1] = checkSongs(songsArtist2);
numSongsPerArtist[2] = checkSongs(songsArtist3);
numSongsPerArtist[3] = checkSongs(songsArtist4);


//DEBUG
printf("%d ",numSongsPerArtist[0]);
printf("%d ",numSongsPerArtist[1]);
printf("%d ",numSongsPerArtist[2]);
printf("%d ",numSongsPerArtist[3]);
printf("%d ",numOfArtists);

2 个答案:

答案 0 :(得分:1)

当你编写一个以数组作为参数的函数时,它总是应该问 来自调用者的长度,除非以某种方式标记数组的末尾 (如字符串'\0')。如果您以后更改程序以接受更多或 歌曲数量减少,你忘记更新循环条件,你在一个 麻烦的世界。调用者知道数组的大小,因为它 创建了数组,或者因为数组及其大小已经传递。这是 标准C库中函数的标准行为。

所以我将你的功能重写为:

int checkSongs(char songsOfAnArtist[][80], size_t len)
{
    int numOfSongs = 0;

    for(size_t i = 0; i < len; ++i)
    {
        if(songsOfAnArtist[i][0] != 0 && songsOfAnArtist[i][0] != '\n')
            numOfSongs++;
    }

    return numOfSongs;
}

然后调用函数

numSongsPerArtist[0] = checkSongs(songsArtist1, sizeof songsArtist1 / sizeof *songsArtist1);
numSongsPerArtist[1] = checkSongs(songsArtist2, sizeof songsArtist2 / sizeof *songsArtist2);
numSongsPerArtist[2] = checkSongs(songsArtist3, sizeof songsArtist3 / sizeof *songsArtist3);
numSongsPerArtist[3] = checkSongs(songsArtist4, sizeof songsArtist4 / sizeof *songsArtist4);

这样更好,因为如果您稍后从char songsArtist3[3][80];更改为 char songsArtist3[5][80];,你不必重写边界 循环条件。每个艺术家都可以拥有不同大小的歌曲插槽。

当您存储歌曲名称时,请确保源字符串不是 如果长度超过79个字符,请使用strncpy,并确保编写'\0' - 终止字节。

如果你得到错误的结果,则可能是songsArtist s 变量未正确初始化,请检查您的getInputs函数 这样在初始化时所有 songsArtist[i][0]都设置为0。如果你这样做 那,你应该得到正确的结果。

例如:

int main(void)
{
    ...
    char songsArtist1[3][80];
    char songsArtist2[3][80];
    char songsArtist3[3][80];
    char songsArtist4[3][80];

    memset(songsArtist1, 0, sizeof songsArtist1);
    memset(songsArtist2, 0, sizeof songsArtist2);
    memset(songsArtist3, 0, sizeof songsArtist3);
    memset(songsArtist4, 0, sizeof songsArtist4);

    ...
}

答案 1 :(得分:0)

在您打破循环的区块中添加条件。

if(sumOfSongs==0)
    break;

此外,我建议使用unsigned类型作为变量,因为数字最有可能永远不会小于0;

并将numOfSongs = 3;置于for循环之外,正如其他人所建议的那样。