C 如何在游戏板(2d阵列)内打印随机单词?

C 如何在游戏板(2d阵列)内打印随机单词?,c,arrays,pointers,struct,function-pointers,C,Arrays,Pointers,Struct,Function Pointers,我正在用C语言和Cygwin终端编写一个打字游戏 我从一个.txt文件中读取了1000个单词,然后我随机打印了一个单词。我需要在2d数组框“gameboard”中打印这个随机单词 如何在框内打印随机单词? 单词需要显示在框的顶行的随机水平位置 注:当我说方框时,我指的是由破折号和星号组成的20(高)乘80(宽)的方框 任何帮助都将不胜感激。事先非常感谢 #include <stdio.h> #include <stdlib.h> #include <string.

我正在用C语言和Cygwin终端编写一个打字游戏

我从一个.txt文件中读取了1000个单词,然后我随机打印了一个单词。我需要在2d数组框“gameboard”中打印这个随机单词

如何在框内打印随机单词?

单词需要显示在框的顶行的随机水平位置

注:当我说方框时,我指的是由破折号和星号组成的20(高)乘80(宽)的方框

任何帮助都将不胜感激。事先非常感谢

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

void main(){

    int g, h; //index for use in for loop

        //creates box
    const int boxLength = 20;
    const int boxWidth = 75;
    char box[boxLength][boxWidth];
    for(int g = 0; g < boxLength; g++){
        for(int h = 0; h < boxWidth; h++){
            if(g == 0 || g == boxLength - 1)
                box[g][h] = '-';
            else if(h == 0 || h == boxWidth - 1)
                box[g][h] = '|';
            else
                box[g][h] = ' ';
            }
    }       

            FILE *myFilePointer2 = fopen("wordList.txt", "r");

            srand(time(0));
            int size = 1000;

            if(myFilePointer2 == NULL){
                printf("Unable to open file wordList.txt");
                exit(0);
            }

            char** words = (char**)malloc(sizeof(char**)*size); //2d pointer array, dynamically allocated, to store words from text file

            char wordBankArray[1050];//wordBankArray

            int wordQuantity = 0;

            while(fgets(wordBankArray, 1050, myFilePointer2) != NULL){// read data from myFilePointer line by line and store it into words array
                words[wordQuantity] = (char*)malloc(sizeof(char)*(strlen(wordBankArray)+1)); //dynamically allocates memory for words array
                strcpy(words[wordQuantity], wordBankArray); //copying words from text file to wordBankArray
                wordQuantity++;
            }

            printf("Randomly generated word from .txt file: ");
            int index = rand()%wordQuantity;   // psuedo randomly generates an index in range of 0 to wordQuantity)

            printf("%s\n", words[index]); //prints randomly generated word from index

            for(int g = 0; g < boxLength; g++){ //prints 2d box
                for(int h = 0; h < boxWidth; h++){
                    printf("%c", box[g][h]);
                }
                printf("\n");
                fclose(myFilePointer2); //close file for reading
            }
    }
#包括
#包括
#包括
#包括
#包括
void main(){
int g,h;//用于for循环的索引
//创建长方体
const int boxLength=20;
const int boxWidth=75;
字符框[boxLength][boxWidth];
对于(int g=0;g
您有许多小错误,如果您正在读取一个包含1000个单词但只分配了100个指针的文件,您将调用未定义的行为,试图写入不存在的指针

您不需要在
for(int g=0;gfclose()中执行
fclose()
(关闭文件
boxLength
的次数)

如果您正在定义
const int…
,那么您正在创建一个2D VLA(可变长度数组),这很好,但是如果边界在编译时之前已知,请使用
#define
声明常量,并避免C89/90中不存在的VLA,该VLA在C99中引入,并成为C11中的可选功能

您还应该将
-Wshadow
添加到编译字符串中,以隐藏变量:

int g, h; //index for use in for loop
for(int g = 0; g < boxLength; g++){
    for(int h = 0; h < boxWidth; h++){
    ...
声明循环变量时:

int g, h; //index for use in for loop
for(int g = 0; g < boxLength; g++){
    for(int h = 0; h < boxWidth; h++){
    ...
(你可以选择任何你喜欢的名字)

除非您在独立环境(没有操作系统)中工作,否则您对
void main()
的声明是错误的。在符合标准的实现中,
main
for的允许声明是
int main(void)
int main(int argc,char*argv[])
(您将看到它是用等效的
char**argv
编写的)。请参阅:

参数
int argc和char**argv
允许您在命令行上将信息传递到程序中。不要硬编码文件名。(如果您在嵌入式系统上,这是一个例外,因为您可能无法在命令行上传递文件名),否则,您可以执行以下操作:

int main (int argc, char **argv)
{
    int nptrs = WRDSZ, index, wordQuantity = 0;     /* declare/initialize vars */
    char box[BXLEN][BXWDT] =  {{0}},
        **words = NULL,
        wordBankArray[ARRSZ] = "";
    FILE *fp = NULL;

    if (argc < 2 ) {    /* validate 1 argument given for filename */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }
    for (int i = 0; i < wordQuantity; i++)      /* free allocated strings */
        free (words[i]);
    free (words);                               /* free pointers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#define BXLEN   20      /* if you need a constant, #define one (or more) */
#define BXWDT   75
#define WRDSZ  100
#define ARRSZ 1050

int main (int argc, char **argv)
{
    int nptrs = WRDSZ, index, wordQuantity = 0;     /* declare/initialize vars */
    char box[BXLEN][BXWDT] =  {{0}},
        **words = NULL,
        wordBankArray[ARRSZ] = "";
    FILE *fp = NULL;

    if (argc < 2 ) {    /* validate 1 argument given for filename */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename\n", argv[0]);
        return 1;
    }

    for (int g = 0; g < BXLEN; g++) {                   /* initialize box */
        for (int h = 0; h < BXWDT; h++) {
            if (g == 0 || g == BXLEN - 1)
                box[g][h] = '-';
            else if (h == 0 || h == BXWDT - 1)
                box[g][h] = '|';
            else
                box[g][h] = ' ';
        }
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

    srand (time (NULL));                                /* seed rand generator */

    if (!(words = malloc (nptrs * sizeof *words))) {    /* allocate/validate */
        perror ("malloc-words");
        return 1;
    }

    while (fgets (wordBankArray, ARRSZ, fp) != NULL) {  /* read each line in file */
        size_t len;     /* save length, then memcpy */
        if (wordQuantity == nptrs) {    /* check if all pointers used - realloc */
            /* always realloc using a temporary pointer -- not the pointer itself */
            void *tmp = realloc (words, 2 * nptrs * sizeof *words);
            if (!tmp) {     /* validate realloc succeeds */
                perror ("realloc-words");
                break;      /* don't exit, original words pointer still valid */
            }
            words = tmp;    /* assign reallocated block to original pointer */
            nptrs *= 2;     /* update number of pointers allocated */
        }
        if (!(words[wordQuantity] = malloc ((len = strlen (wordBankArray)) + 1))) {
            perror ("malloc-words[wordQuantity]");
            return 1;
        }
        memcpy (words[wordQuantity], wordBankArray, len + 1);
        wordQuantity++;
    }
    fclose (fp);

    fputs ("Randomly generated string from list : ", stdout);
    index = rand() % wordQuantity;
    printf ("%s\n", words[index]);

    for (int g = 0; g < BXLEN; g++) {
        for (int h = 0; h < BXWDT; h++) {
            printf ("%c", box[g][h]);
        }
        putchar ('\n');
    }

    for (int i = 0; i < wordQuantity; i++)      /* free allocated strings */
        free (words[i]);
    free (words);                               /* free pointers */
}
注意:您必须验证每个分配)

请注意,您仅分配初始
WRDSZ
100
)指针。如果您的文件有1000个字,则必须跟踪已填充的指针数,(您的
wordQuantity
),并且必须跟踪分配的指针数(例如使用
nptrs
)。当
wordQuantity==nptrs
时,您必须
realloc
在尝试使用另一个指针之前,通过
words
可用的指针数量(通常将当前分配的数量加倍是一个合理的增长方案)。添加额外的测试和重新分配,您的读取循环将变为:

    while (fgets (wordBankArray, ARRSZ, fp) != NULL) {  /* read each line in file */
        size_t len;     /* save length, then memcpy */
        if (wordQuantity == nptrs) {    /* check if all pointers used - realloc */
            /* always realloc using a temporary pointer -- not the pointer itself */
            void *tmp = realloc (words, 2 * nptrs * sizeof *words);
            if (!tmp) {     /* validate realloc succeeds */
                perror ("realloc-words");
                break;      /* don't exit, original words pointer still valid */
            }
            words = tmp;    /* assign reallocated block to original pointer */
            nptrs *= 2;     /* update number of pointers allocated */
        }
        if (!(words[wordQuantity] = malloc ((len = strlen (wordBankArray)) + 1))) {
            perror ("malloc-words[wordQuantity]");
            return 1;
        }
        memcpy (words[wordQuantity], wordBankArray, len + 1);
        wordQuantity++;
    }
    fclose (fp);
注意:您只需调用
strlen()
一次,保存大小,然后使用
memcpy()
复制字符串。如果调用
strcpy()
,您只需再次扫描调用
strlen()
中已有的字符串结尾)

阅读完毕后,在该点调用
fclose()
。还要注意
sizeof(char)
1
,应该从大小乘法中省略。剩下的部分将打印框并输出一个随机字符串,但请注意,如果输出中不需要转换,则无需调用
printf
put
fputs
即可(一个好的编译器会在幕后为您进行更改)

您错过的是释放已分配的内存。为此,您可以执行以下操作:

int main (int argc, char **argv)
{
    int nptrs = WRDSZ, index, wordQuantity = 0;     /* declare/initialize vars */
    char box[BXLEN][BXWDT] =  {{0}},
        **words = NULL,
        wordBankArray[ARRSZ] = "";
    FILE *fp = NULL;

    if (argc < 2 ) {    /* validate 1 argument given for filename */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }
    for (int i = 0; i < wordQuantity; i++)      /* free allocated strings */
        free (words[i]);
    free (words);                               /* free pointers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#define BXLEN   20      /* if you need a constant, #define one (or more) */
#define BXWDT   75
#define WRDSZ  100
#define ARRSZ 1050

int main (int argc, char **argv)
{
    int nptrs = WRDSZ, index, wordQuantity = 0;     /* declare/initialize vars */
    char box[BXLEN][BXWDT] =  {{0}},
        **words = NULL,
        wordBankArray[ARRSZ] = "";
    FILE *fp = NULL;

    if (argc < 2 ) {    /* validate 1 argument given for filename */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename\n", argv[0]);
        return 1;
    }

    for (int g = 0; g < BXLEN; g++) {                   /* initialize box */
        for (int h = 0; h < BXWDT; h++) {
            if (g == 0 || g == BXLEN - 1)
                box[g][h] = '-';
            else if (h == 0 || h == BXWDT - 1)
                box[g][h] = '|';
            else
                box[g][h] = ' ';
        }
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

    srand (time (NULL));                                /* seed rand generator */

    if (!(words = malloc (nptrs * sizeof *words))) {    /* allocate/validate */
        perror ("malloc-words");
        return 1;
    }

    while (fgets (wordBankArray, ARRSZ, fp) != NULL) {  /* read each line in file */
        size_t len;     /* save length, then memcpy */
        if (wordQuantity == nptrs) {    /* check if all pointers used - realloc */
            /* always realloc using a temporary pointer -- not the pointer itself */
            void *tmp = realloc (words, 2 * nptrs * sizeof *words);
            if (!tmp) {     /* validate realloc succeeds */
                perror ("realloc-words");
                break;      /* don't exit, original words pointer still valid */
            }
            words = tmp;    /* assign reallocated block to original pointer */
            nptrs *= 2;     /* update number of pointers allocated */
        }
        if (!(words[wordQuantity] = malloc ((len = strlen (wordBankArray)) + 1))) {
            perror ("malloc-words[wordQuantity]");
            return 1;
        }
        memcpy (words[wordQuantity], wordBankArray, len + 1);
        wordQuantity++;
    }
    fclose (fp);

    fputs ("Randomly generated string from list : ", stdout);
    index = rand() % wordQuantity;
    printf ("%s\n", words[index]);

    for (int g = 0; g < BXLEN; g++) {
        for (int h = 0; h < BXWDT; h++) {
            printf ("%c", box[g][h]);
        }
        putchar ('\n');
    }

    for (int i = 0; i < wordQuantity; i++)      /* free allocated strings */
        free (words[i]);
    free (words);                               /* free pointers */
}
内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于任何块,您都有两个职责