C - 无法创建char字符串矩阵

时间:2016-11-19 06:58:07

标签: c

更新:想出来......错误代码底部的更新代码确实如此。 谢谢你们

我试图将input.txt文件中的行读入三个矩阵,一个用于名字,一个用于姓氏,一个用于成绩。

等级矩阵很好,我无法弄清楚名称矩阵。

跑步时我得到输出:

Row 1, column 1 of grades: 1.30
Row 1, column 1 of first: P
Row 1, column 1 of last: V

字符数组不正确。

我认为问题在于如何初始化数组的第一个和最后一个。 这里的第一个例子是:

//Store first token in first[][]
if(counter == 1){
first[i][j] = token;
}

这是将名为token的字符串存储到数组的首先[] []的索引[0] [0]中的正确方法吗?

初始化字符串矩阵的正确方法是什么? 我需要第一行包含名字, 第二行包含第二个名称, 等

我很难想象实际矩阵与它们如何存储在RAM中(我理解数组的名称是指向数组的第一个索引的指针,但当它到达2d数组时,我无法看到指针在RAM中的结构如何

input.txt文件:

Alice Wonderland 1.3 2 3 4 5.5
Bob Marley 7 8 9.8 10 11.5
Charley Manson 12 13.5 14 15 16

代码:

/* Input: input file name, as char array;
          matrix of names, and matrix of grades
   Functionality: opens the file, extracts names into matrix of names,
                  extracts grades into the matrix of grades;
   Output: 0 if everything went well, -1 otherwise
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNUMSTUDENT 100
#define MAXNUMGRADES 100

//#define DEBUG1
#define DEBUG2

char first[MAXNUMSTUDENT][1]; //One first name per row (one column)
char last[MAXNUMSTUDENT][1];  //One last name per row (one column)
float grades[MAXNUMGRADES][MAXNUMGRADES];
float grade;




int counter = 1; //Counts the token number (First two tokens = names, rest = grades)
int i = 0; //Row index
int j = 0; //Column index for first[][], last[][]
int n = 0; //Row index for grades[][]
int m = 0; //Column index for grades[][]

int main(void)
{
    //Initialize all arrays to 0

    // First[i][j]
    for(i=0; i<MAXNUMSTUDENT; i++){
        first[i][j] = "0";
        for(j=0; j<=1; j++){
            first[i][j] = "0";
        }
    }

    // Last[i][j]
    for(i=0; i<MAXNUMSTUDENT; i++){
        last[i][j] = "0";
        for(j=0; j<=1; j++){
            last[i][j] = "0";
        }        

    }

    // grades[n][m]
    for(n=0; n<MAXNUMGRADES; n++){
        grades[n][m] = 0;
        for(m=0; m<MAXNUMGRADES; m++){
            grades[n][m] = 0;
        }
    }

    //Reset indexes
    i=0;
    j=0;
    n=0;
    m=0;

    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("gradebook.txt", "r");  //Name of input file goes here
    if (fp == NULL)
        return -1;

    //Loops through each line of gradebook (1 loop = 1 line)
    while ((read = getline(&line, &len, fp)) != -1) {

        /****   AT THIS POINT YOU HAVE A STRING CALLED line *****/


        char delim[] = " ";   //delimiters are space comma and hyphen

        char* token;

        //For loop tokenizes string, runs until there are no more tokens
        for (token = strtok(line, delim); token; token = strtok(NULL, delim))
        {   
            #ifdef DEBUG1
            printf("Retrieved line of length %zu :\n", read);
            printf("%s\n", line);
            printf("token=%s counter=%d i=%d j=%d n=%d m=%d\n\n", token, counter, i, j, n, m);
            #endif

            //Store first token in first[][]
            if(counter == 1){
                first[i][j] = token;
            }

            //Store second token in last[][]
            if(counter == 2){
                last[i][j] = token;

                //Increment row of first[][] and last[][] (for next line)
                i++;
            }

            //Store the rest of tokens in grades[][]
            if(counter > 2){
                grade = atof(token);
                grades[n][m] = grade;

                //Increment column of grades[][]
                m++;
            }

        //Counter for token number
        counter++;
        }

        //Increment row of grades[][]
        n++;

        //Reset counter
        counter = 1;

        //Reset column index of grades[][]
        m = 0;
    }


    //Test arrays
    printf("Row 1, column 1 of grades: %.2f\n", grades[0][0]);
    printf("Row 1, column 1 of first: %c\n", first[0][0]);
    printf("Row 1, column 1 of last: %c\n", last[0][0]);

    fclose(fp);
    if (line)
        free(line);
    return 0;
}

谢谢。

更新代码:

/*  File    : extractgrades.c          *
*   team    : SnS                   *
*   Date    : 11-20-16           */

/* Input: input file name, as char array;
          matrix of names, and matrix of grades
   Functionality: opens the file, extracts names into matrix of names,
                  extracts grades into the matrix of grades;
   Output: 0 if everything went well, -1 otherwise
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNUMSTUDENT 100
#define MAXNUMGRADES 100

//Comment out to turn off debugging
#define DEBUG1
#define DEBUG2

char first[MAXNUMSTUDENT][MAXNUMSTUDENT]; 
char last[MAXNUMSTUDENT][MAXNUMSTUDENT];  
float grades[MAXNUMGRADES][MAXNUMGRADES];

int numberofscores; //Number of scores
int numberofstudents;
int maxnumberofscores;

int main(void)
{
    char first[MAXNUMSTUDENT][MAXNUMSTUDENT] = {{0}}; 
    char last[MAXNUMSTUDENT][MAXNUMSTUDENT] = {{0}}; 
    float grades[MAXNUMGRADES][MAXNUMGRADES] = {{0}};
    float grade;

    int i; //Row index
    int j; //Column index for first[][], last[][]
    int n; //Row index for grades[][]
    int m; //Column index for grades[][]
    int counter; //Counts the token number (First two tokens = names, rest = grades)

    //Initialize indexes
    counter=1;
    numberofscores=0;
    i=0;
    j=0;
    n=0;
    m=0;

    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("gradebook.txt", "r");  //Name of input file goes here
    if (fp == NULL)
        return -1;

    //Loops through each line of gradebook (1 loop = 1 line)
    while ((read = getline(&line, &len, fp)) != -1) {

        char delim[] = " ";   //delimiters are space comma and hyphen
        char * token;

        //For loop tokenizes string, runs until there are no more tokens
        for (token = strtok(line, delim); token; token = strtok(NULL, delim))
        {   
            #ifdef DEBUG1
                printf("Retrieved line of length %zu :\n", read);
                printf("%s\n", line);
                printf("token=%s counter=%d i=%d j=%d n=%d m=%d\n\n", token, counter, i, j, n, m);
            #endif

            //Store first token in first[][]
            if(counter == 1){
               strcpy(first[i], token);
            }

            //Store second token in last[][]
            if(counter == 2){
                strcpy(last[i], token);
                //Increment row of first[][] and last[][] (for next line)
                i++;
            }

            //Store the rest of tokens in grades[][]
            if(counter > 2){
                grade = atof(token);
                grades[n][m] = grade;

                //Increment column of grades[][]
                m++;
            }

        //Counter for token number
        counter++;
        }

        //Save pseudo max number of scores
        maxnumberofscores = counter;
        if(counter >= maxnumberofscores){
            maxnumberofscores = counter;
        }
        printf("maxnumberofscores: %d\n", maxnumberofscores);

        //Increment row of grades[][]
        n++;

        //Reset column index of grades[][]
        m = 0;

        //Reset counter
        counter = 1;
    }

    //Get actual max number of scores
    numberofscores = maxnumberofscores - 3;

    //Get number of students
    numberofstudents = i;


  //Debug sandwich to test everything
  #ifdef DEBUG2
    //Test arrays
    printf("Row 1, column 1 of grades: %.2f\n", grades[0][0]);
    printf("Row 1, column 1 of first: %c\n", first[0][0]);
    printf("Row 1, column 1 of last: %c\n", last[0][0]);

    //Print all arrays
    i=0;
    j=0;
    n=0;
    m=0;

    //Print grades[n][m]
    for(n=0; n<numberofstudents; n++){
        printf("\n");
        for(m=0; m<numberofscores; m++){
            printf("grades[%d][%d]: %.2f\n", n, m, grades[n][m]);
        }
    }

    //Print first[i][j]
    for(i=0; i<numberofstudents; i++){
        printf("first[%d]: %s\n", i, first[i]);
    }

    //Print last[i][j]
    for(i=0; i<numberofstudents; i++){
        printf("last[%d]: %s\n", i, last[i]);
    }

    //Print number of scores, number of students
    printf("Max number of scores = %d\n", numberofscores);
    printf("Number of students: %d\n", numberofstudents);    
  #endif


    fclose(fp);
    if (line)
        free(line);
    return 0;
}

2 个答案:

答案 0 :(得分:2)

first[i][j] = "0";

first[i][j]char(不是字符串),更改为

first[i][j] = '0';
  

这是将名为token的字符串存储到索引中的正确方法   [0] [0]数组的第一个[] []?

first[i][j] = token;

不,首先,您无法使用=分配数组,您需要使用strcpy之类的功能或更好的更安全的版本,例如strlcpy或{{1} }。

其次,你的数组只有一个字符的空间:

snprintf

你需要更多空间:

char first[MAXNUMSTUDENT][1];

另外,您最后会释放char first[MAXNUMSTUDENT][100]; ,但每次调用line时都需要调用free以避免内存泄漏:

getline

答案 1 :(得分:2)

您的数组声明不正确

char first[MAXNUMSTUDENT][1]

仅分配1个字符的MAXNUMSTUDENT。

对于C,上面只是一个内存块,其大小为MAXNUMSTUDENT个字符,无论您给出的维数是多少。当您取消引用内存块以计算内存块中的偏移量时,将使用这些维度。

您需要的是

char first[MAXNUMSTUDENT][MAX_LENGTH_NAME];

其中MAX_LENGTH_NAME是第一个名称可以包含的字符数加上一个结尾\ 0的字符。其他阵列也是如此。

然而,这看起来像动态内存分配会更好。

因此,不是分配字符数组而是分配一个指向字符串的指针数组。

char* first[MAXNUMSTUDENT]

然后当你strtok行分配并复制字符串

first[i] = strdup(token); // same as malloc/strcpy

我认为如果将所有学生信息放入结构中会更好。

struct student
{
  char* first;
  char* last;
  char* grades; 
};

...

struct student students[MAXNUMSTUDENT];

..

students[i].first = strdup(token);

当然你也可以使数组动态化而不是用固定大小声明它,初始大小可以是MAXNUMSTUDENT

struct student** students;
students = malloc(sizeof(struct student*) * MAXNUMSTUDENT);

以后可以使用realloc()

进行更改